Gem (C++ library)

Hello BiVector!

I wrote a modern C++ library for geometric algebra. I’m pretty happy with it so far, but being new to this community and subject matter, I thought I’d consult you for opinions (if you have the time to spare). A design that looks clean and intuitive to me might look rather different to someone with practical experience in the field.

Thanks for reading this and I hope you will find it interesting!

1 Like

Hi,

Please have a look at this :

I have made is quite some time ago, but it might be similar to yours.
You can also cross-link to this topic from there if you want.

Interesting!

The design of both libraries take an agnostic approach to what algebra is represented. It seems to me that most interesting operations, like the geometric product, can be easily accommodated in such a framework, but a few cases stand out.

For example, you mention “you just define e1,e2,e3, and go add, multiply, or exponentiate them to produce higher-level objects” and I wonder how you approached exponentiation of a general multivector? Reducing the problem to exponentiation of blade products, the obvious cases are when the product squares to -1 (Euler’s formula) and when the series expansion terminates after a finite number of steps, but I struggle to find a general approach (which is a bit disheartening since it is such a fundamental operation). Since your library supports symbolic expressions, I wonder if this is part of the answer?

Thank you for responding. I’m afraid I don’t know how to cross-link to your thread, however.

For the exponentiation, I have tried to use the series expansion, but it was not practical. Instead, to compute exp(x), I evaluate and return 1+x or cos/sin cosh/sinh formulas depending on the sign. If possible, this evaluation is made at compile time. See “https://github.com/godefv/math/blob/master/geometry/algebra/exponential.h”.

Then, I have had some work implementing important trigonometric formulas to simplify them at compile-time, because they appeared on every sandwich product with exponentials.

To get all compile-time optimizations, it is often a good idea to use symbolic formulas in code, then evaluate them with dynamic values, because you can define properties on the symbolic values (like squares to zero, is positive, is between 0 and pi, etc). It boils down to defining types with wanted properties but dynamic values.

I see. The code is symbolic in the sense that the blades contained in a multivector store information in template parameter bitflags, so the type of optimizations and compile-time selection of algorithms you describe are possible.

Using cosh/sinh as an additional special case was not obvious to me, however. That adds a large chunk to the puzzle :). Also, trig simplifications for sandwitch products sounds like a good idea. I wonder if it can be integrated with expression templates, though.

Lots to think about. Will definitely look closer at your code :).

Actually, I don’t need any bitflags. The c++20 concepts allow me to easily query whether an expression is constexpr or not. For instance, symbols like x, integer<4>*pi, or e1*e2 are constexpr, so are expressions formed by combining such symbols. Then, for any constexpr expression X, I can just run square(X) inside a template requires clause to select the correct overload.

cosh/sinh appear naturally if you do the calculations from the definition of the exponential (with the infinite sum). Obviously, when x²=0, only 1+x remains. Else, if x²<0 cos/sin appear because of the flipping sign in the series. Else cosh/sinh appear because of the non flipping sign in the series. What geometric algebra revealed to me is that they are all rotations in planes, just with different metrics. In particular, boosts in space-time are just plain rotations ! Therefore, the library is agnostic about the dimension of the algebra, but also about its metric.

Yes I agree sinh/cosh are rather obvious in retrospect. Though to make use of those three special cases (at least in my representation) the multivector would first need to be decomposed into parts that square to scalars, and then account for the commutation of those parts in going from exponentiation of a sum to a product of exponentiations, like with commuting operators in quantum mechanics.

That might have to wait until I get the time to work more on the library, though :).

Absolutely, I actually only support exponentiation of multivector that square to a scalar. It is good enough for most use cases. Other multivectors should probably have their own overload.