API Reference
Main symbols:
Aliases:
Usage
SymbolicGA.@ga
— Macro@ga <sig> <T> <ex>
@ga <sig> <ex>
Generate Julia code which implements the computation of geometric elements from ex
in an algebra defined by a signature sig
(see SymbolicGA.Signature
).
Supported syntax:
sig
: Integer literal or tuple of 1, 2 or 3 integer literals corresponding to the number of positive, negative and degenerate basis vectors respectively, where unspecified integers default to zero. May also be a string literal of the form<+++--𝟎>
where the number of+
,-
and𝟎
correspond to the nmuber of positive, negative and degenerate basis vectors respectively.T
: Any arbitrary expression which evaluates to a type or tonothing
.ex
: Any arbitrary expression that can be parsed algebraically.
See also: codegen_expression
.
ex
can be a single statement or a block, and uses a domain-specific language to facilitate the construction of algebraic expressions. ex
is logically divided into two sections: a definition section, which defines bindings, and a final algebraic expression, which will be the object of the evaluation. It is processed in three phases:
- A definition phase, in which bindings are defined with one or several statements for use in the subsequent phase;
- An expansion phase, where identified bindings in the final algebraic expression are expanded. The defined bindings include the ones priorly defined and a set of default bindings.
- An evaluation phase, in which the core algebraic expression is simplified and translated into a Julia expression.
Expression parsing
Binding definitions
All statements prior to the last can define new variables or functions with the following syntax and semantics:
- Variables are either declared with
<lhs::Symbol> = <rhs::Any>
or with<lhs::Symbol>::<type>
, the latter being expanded to<lhs> = <lhs>::<type>
. - Functions are declared with a standard short or long form function definition
<name>(<args...>) = <rhs>
orfunction <name>(<args...>) <rhs> end
, and are restricted to simple forms to encode simple semantics. The restrictions are as follows:where
clauses and output type annotations are not supported.- Function arguments must be untyped, e.g.
f(x, y)
is allowed but notf(x::Vector, y::Vector)
. - Function arguments must not be reassigned; it is assumed that any occurence of symbols declared as arguments will reference these arguments. For example,
f(x, y) = x + y
assumes thatx + y
actually means "perform+
on the first and second function argument". Therefore,f(x, y) = (x = 2; x) + y
will be likely to cause bugs. To alleviate this restriction, usecodegen_expression
with a suitable [SymbolicGA.Bindings
] with function entries that contain specific calls to `:($(@arg <i>)).
Binding expansion
References and functions are expanded in a fairly straightforward copy-paste manner, where references are replaced with their right-hand side and function calls with their bodies with their arguments interpolated. Simple checks are put in place to allow for self-referencing bindings for references, such as x = x::T
, leading to a single expansion of such a pattern in the corresponding expression subtree.
See SymbolicGA.Bindings
for more information regarding the expansion of such variables and functions.
Function calls will be assumed to be either referencing a binding or a built-in function. If you want to call a function, e.g. my_func(x)::Vector
, you will have to interpolate the call: $(my_func(x))::Vector
.
Algebraic evaluation
Type annotations may either:
- Specify what type of geometric entity an input should be considered as, where components are then picked off with
getcomponent
. - Request the projection of an intermediate expression over one or multiple grades.
SymbolicGA.@pga2
— Macro@pga2(T, ex)
@pga2(ex)
Macro generated via SymbolicGA.@geometric_space
with signature (2, 0, 1)
and the following definitions:
embed(x) = x[1]::e1 + x[2]::e2
magnitude2(x) = x ⦿ x
point(x) = embed(x) + 1.0::e3
No documentation found.
SymbolicGA.@pga2
is a macro.
# 2 methods for macro "@pga2" from SymbolicGA:
[1] var"@pga2"(__source__::LineNumberNode, __module__::Module, ex)
@ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:61
[2] var"@pga2"(__source__::LineNumberNode, __module__::Module, T, ex)
@ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:57
SymbolicGA.@pga3
— Macro@pga3(T, ex)
@pga3(ex)
Macro generated via SymbolicGA.@geometric_space
with signature (3, 0, 1)
and the following definitions:
embed(x) = x[1]::e1 + x[2]::e2 + x[3]::e3
magnitude2(x) = x ⦿ x
point(x) = embed(x) + 1.0::e4
No documentation found.
SymbolicGA.@pga3
is a macro.
# 2 methods for macro "@pga3" from SymbolicGA:
[1] var"@pga3"(__source__::LineNumberNode, __module__::Module, ex)
@ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:61
[2] var"@pga3"(__source__::LineNumberNode, __module__::Module, T, ex)
@ ~/work/SymbolicGA.jl/SymbolicGA.jl/src/spaces.jl:57
SymbolicGA.@cga3
— Macro@cga3(T, ex)
@cga3(ex)
Macro generated via SymbolicGA.@geometric_space
with signature (4, 1)
and the following definitions:
embed(x) = x[1]::e1 + x[2]::e2 + x[3]::e3
magnitude2(x) = x ⦿ x
point(x) = (embed(x) + (0.5::Scalar ⟑ magnitude2(embed(x))) ⟑ n + n̄)::Vector
weight(X) = -X ⋅ n
unitize(X) = X / weight(X)
radius2(X) = (magnitude2(X) / magnitude2(X ∧ n))::Scalar
center(X) = (X ⟑ n) ⟑ X
distance(S, X) = unitize(S) ⋅ unitize(X)
3D Conformal Geometric Algebra.
This functionality is experimental and will likely be subject to change in the future. It is not recommended for use beyond prototyping and playing around.
SymbolicGA.@geometric_space
— Macro@geometric_space name sig quote
n = 1.0::e4 + 1.0::e5
n̄ = (-0.5)::e4 + 0.5::e5
... # other definitions
end [warn_override = true]
Generate a macro @name
which defines a geometric space with signature sig
along with optional user-provided definitions.
The resulting macro will have two methods:
@name ex
, which acts as a standard@ga sig ex
(but with potential extra definitions).@name T ex
which wraps the result into typeT
, just like@ga sig T ex
would (see@ga
).
If definitions are provided as an Expr
, they will be parsed into Bindings
and added to the default bindings. If definitions already are Bindings
, they will be used as is. warn_override
can be set to false if you purposefully intend to purposefully override some of the default bindings.
SymbolicGA.KVector
— TypeKVector{K,T,D,N}
Geometric K
-vector with eltype T
with N
elements in a geometric algebra of dimension D
.
The constructors KVector{K,D}(elements...)
and KVector{K,D}(elements::NTuple)
will automatically infer T
from the arguments and N
from K
and D
.
Examples
julia> KVector{1,3}(1.0, 2.0, 3.0)
KVector{1, Float64, 3, 3}(1.0, 2.0, 3.0)
julia> KVector{2,3}(1.0, 2.0, 3.0)
Bivector{Float64, 3, 3}(1.0, 2.0, 3.0)
julia> KVector{4,4}(1.0)
Quadvector{Float64, 4, 1}(1.0)
SymbolicGA.Bivector
— TypeBivector{T,D,N}
Alias for KVector{2,T,D,N}
SymbolicGA.Trivector
— TypeTrivector{T,D,N}
Alias for KVector{3,T,D,N}
SymbolicGA.Quadvector
— TypeQuadvector{T,D,N}
Alias for KVector{4,T,D,N}
Expression generation
SymbolicGA.codegen_expression
— Functioncodegen_expression(sig, ex; T = nothing, bindings::Optional{Bindings} = nothing)
Parse ex
as an algebraic expression and generate a Julia expression which represents the corresponding computation. sig
can be a SymbolicGA.Signature
, a signature integer or a signature string, tuple or tuple expression adhering to semantics of @ga
. See @ga
for more information regarding the parsing and semantics applied to ex
.
Parameters
T
specifies what type to use when reconstructing geometric entities from tuple components withconstruct
. If set tonothing
and the result is in a non-flattened form (i.e. not annotated with an annotation of the type<ex>::(0 + 2)
), then an appropriateKVector
will be used depending on which type of geometric entity is returned; if multiple entities are present, a tuple ofKVector
s will be returned. If the result is in a flattened form,T
will be set to:Tuple
if unspecified.bindings
is a user-providedSymbolicGA.Bindings
which controls what expansions are carried out on the raw Julia expression before conversion to an algebraic expression.
SymbolicGA.Bindings
— TypeBindings(; refs = Dict{Symbol,Any}(), funcs = Dict{Symbol,Any}(), warn_override = true)
Structure holding information about bindings which either act as references (simple substitutions) or as functions, which can be called with arguments. This allows a small domain-specific language to be used when constructing algebraic expressions.
References are lhs::Symbol => rhs
pairs where the left-hand side simply expands to the right-hand side during parsing. Right-hand sides which include lhs
are supported, such that references of the form x = x::Vector
are allowed, but will be expanded only once. Functions are name::Symbol => body
pairs where rhs
must refer to their arguments with Expr(:argument, <literal::Int>)
expressions. Recursion is not supported and will lead to a StackOverflowError
. See @arg
.
Most default functions and symbols are implemented using this mechanism. If warn_override
is set to true, overrides of such default functions will trigger a warning.
SymbolicGA.default_bindings
— FunctionBindings
included by default in @ga
.
By default, any user-defined symbol overriding a symbol defined here will trigger a warning; set warn_override = false
to disable this.
SymbolicGA.Signature
— TypeSignature(positive::Int, negative::Int = 0, degenerate::Int = 0)
Signature(str::AbstractString) # Signature("++-𝟎")
Signature of an Euclidean or pseudo-Euclidean space.
This signature encodes a space with a metric such that the first P
basis vectors square to 1, the following N
to -1 and the following D
to 0. The metric evaluates to zero between two distinct basis vectors.
SymbolicGA.@arg
— Macro@arg <literal::Integer>
Convenience macro to construct expressions of the form Expr(:argument, i)
used within function definitions for SymbolicGA.Bindings
.
Interface methods
SymbolicGA.getcomponent
— Functiongetcomponent(collection)
getcomponent(collection, i)
getcomponent(collection, j, i)
Retrieve a number from a collection to be interpreted as the component of a geometric entity.
getcomponent(collection)
which defaults to collection[]
is used to extract the only component of a scalar or antiscalar.
getcomponent(collection, j, i)
which defaults to collection[j][i]
is used to extract the i-th component the j-th geometric entity for a collection of multiple geometric vectors.
getcomponent(collection, i)
which defaults to collection[i]
is used to extract the i-th component of a single geometric entity or a set of geometric entities backed by collection
. In the case of a set of geometric entities, this is semantically equivalent to getcomponent(collection, j, i)
where a single i
is computed from the cumulated sum of past indices, i.e. as if components from consecutive entities were concatenated together. See @ga
for more information regarding which mode is used depending on the syntax for grade extraction.
Most collections will not need to extend this method, but is exposed should the need arise for a tigher control over how input data is accessed.
SymbolicGA.construct
— Functionconstruct(T, components::Tuple)
Construct an instance of T
from a tuple of components.
Defaults to T(components)
.