[ANN] CliffordNumbers.jl: because multivectors are just as fundamental as numbers

I’ve been working on a new Julia package, CliffordNumbers.jl, that aims to provide an easy-to-use and high-performance implementation of geometric algebras.

My thought process when developing this package was that the Julia Number abstract type encompasses Real and Complex, and the Quaternions.jl package provides Quaternion <: Number. Since all of these systems are Clifford algebras, it stands to reason that a multivector implementation can also subtype Number!

This leads to a few interesting decisions. For instance, multivectors (which are represented by the AbstractCliffordNumber{Q,T} type, behave like scalars for the sake of broadcasting. While they can be indexed, they can only be indexed with a BitIndex object, not an Integer: the whole point is to index by basis blades of the algebra, not by elements of the underlying Tuple.

Along with the full-grade CliffordNumber{Q,T,L} we provide shorter types, EvenCliffordNumber{Q,T,L}, OddCliffordNumber{Q,T,L} (which are both aliases for CliffordNumbers.Z2CliffordNumber{P,Q,T,L}, where P is a Bool that determines grade parity), and KVector{K,Q,T,L}. These are all statically-sized types that can be stored inline in an array.

Algebras with arbitrary signatures and an orthogonal basis are supported when constructing types as the Q parameter. I’d like to support non-orthogonal basis vectors in the future. The generic Signature type specifies any combination of positive-squaring, negative-squaring, and zero-squaring basis vectors, but other types like VGA, PGA, and CGA are provided to simplify implementation.

Multivector products are implemented in terms of a multiply kernel, CliffordNumbers.mul(::AbstractCliffordNumber{Q,T}, ::AbstractCliffordNumber{Q,T}, ::CliffordNumbers.GradeFilter), which uses the CliffordNumbers.GradeFilter argument to filter out multiplications which go to zero for certain products. This is a generated function that uses aggressive constant propagation to achieve extremely high performance. Aside from several common products (geometric product, contractions, dot, Hestenes dot, wedge, regressive, commutator, and anticommutator) this package supports other basic arithmetic operations, exponentation, grade automorphisms, and complements.

This package has no dependences, not even LinearAlgebra or StaticArrays, so it is extremely lightweight and its load time is miniscule. In the future I will have package extensions that can integrate some of the functionality of this package with the two aforementioned packages. I’m not opposed to taking hard dependencies, I just haven’t found it necessary yet. (In the future, some functionality I’ve written that’s not specific to GA may be split off into different packages.)

Of course, a lot is subject to change with the API, but if you have feedback about how things can/should change, I’d love to hear it! The goal is to provide an easy point of entry for programmers who are curious about GA but don’t know where to start.


Congratulations on imitating Grassmann.jl; I have submitted an academic misconduct report to your university for plagiarism; since you refused to acknowledge where you got inspired from. Your implementation is a direct imitation of my type system design, which I pioneered for the Julia language 5 years before. This has happened several times before with other people too, you’re not the first to imitate my project, but usually they acknowledge where the inspiration came from.

You made it clear that you dont want to discuss this issue, so I am investigating this in detail with your university academic misconduct department.

Julia Community can be very proud to have pushed me out and now you have all these great replacements, which happen to imitate the features, types, and definitions of Grassmann.jl

When I first started Grassmann.jl, it was a very unpopular topic nobody in academia cared about.

First they ridicule you (oh, who cares about Grassmann.jl we can use StaticArrays.jl)

Second, it is violently opposed (Grassmann.jl is banned everywhere from every scientific institution)

Third, it is accepted as self evident, and there is no need to cite Grassmann.jl when imitating the obvious

Those are the stages of scientific revolution. I truly experienced it. Can’t make this stuff up …

Nice work! Looking forward to giving it a try. I’m curious about adding derivative operators to a GA library and how that can be done. For example automatic differentiation by using dual numbers (which are CliffordNumbers anyway) to find gradients etc.

Send me a message here or on the Bivector discord if you have any questions, and feel free to file issues/PRs if you run into bugs.

I’ve been meaning to try out the interoperability with Zygote and other AD tools, though at the moment I haven’t had a serious application come to mind (though I was thinking of possibly writing a very simple Hartree-Fock implementation as an example). Let me know how it goes!

Grassmann.jl already does that in several ways for several years now, but I know you’re probably not interested in being involved with Grassmann.jl, so I won’t bother explaining it to you further.