Design choices
There are many ways to implement geometric algebra numerically, and each performs its own trade-offs, depending on the goals it is set to achieve.
In this library, we seek to allow the use of geometric algebra as a language to express logic. In particular, having a concrete representation of the objects and operators of geometric algebra is not a necessity, as long as the relevant operations are easy to express. This is relevant in context of the integration with existing codebases; we chose not to require the use of library-specific types nor, for most cases, to extend specific methods. The interface with this library is based around the way data is to be cast into the semantics of geometric algebra. This should not affect the data structures you choose; be it a tuple, vector or static array, we only need a way to map data to components (see this how-to).
Having direct control over the code that is generated was also one motivation for operating at the symbolic level. It is more work to implement a library which has to manipulate symbolic expressions, but we believe that the benefits are largely worth the effort. The performance guaranteed by processing and optimizing algebraic operations at macro expansion time (i.e. right after parsing, before compilation) furthermore allowed us to escape the limitation of supporting a fixed set of signatures, empowering the user to use whatever space they see fit. In a sense, SymbolicGA.jl can be considered a just-in-time library generator, combining the performance of such generators with the flexibility of other, more dynamic approaches.
Another advantage of operating at the symbolic level is that the way syntax is interpreted can also be controlled. We could implement a fairly simple binding-based substitution with references (which expand to an expression) and basic functions (expanding to an expression, but inserting one argument or more), which prevented us from needing to commit to specific function names and aliases to be exported. This flexibility of notation is particularly relevant in the context of geometric algebra as certain operators or variables may have different notations. Examples include the geometric product, most often noted *
but sometimes noted ⟑
or the pseudoscalar most often noted I
but sometimes noted 𝟙
(see the motivations for the latter notations).