This repository contains code to work with multivector expressions of geometric algebra. The idea is to realise a complete toolchain with a geometric algebra specific domain specific language based on truffle/graal with state of the art smart editing features, debugging functionality and a fast implementation based on JCasADi.
The project is in an early state of development, so it is not advised to use it in real world applications. If you have feedback or feature suggestions, please create a new GitHub Issue.
Especially be cautious regarding:
Download GraalVM (23.1.2) for JDK 21 Community 21.0.2 (Linux (amd64), Java21).
Extract the downloaded archive to an arbitrary location.
Add a new java platform with the name "GraalVM". \ If you use Netbeans IDE with newer version than 21 you have to start the IDE with JDK 21 to be able to build because the build configuration is configured to use the default JDK which is the JDK the IDE is started or you can configure explicit the platform to build by following steps and further the project configuration steps:\
or navigate to this point via the Tools main menu.
Redo the GraalVM Setup with the new version. If you use same path and foldername as before, you can skip the step Netbeans configuration.
If you are the first collaborator updating to a new version, you also need to
graalvm.version
property in the pom.xml of the DSL4GA__Parent. Note, that it differs from the JDK Version. "Language runtimes" is the keyword for it in the text of the download page.The project depends on the vecmath library in the refactored version of the JogAmp Community. Your can find this library here. Unfortunately there is no maven repository available. That is why you need to download the jar file manually and add it as a local depency of the project. To do this in the nebeans ide: Right-click on the depencies of the project and add the dependency manually. The group id is "org.jogamp.java3d", the artifactId is "vecmath" and the type is "jar". \ Alternatively clone it from GitHub, update the compiler version in it's pom.xml and build it.
Clone and checkout
and build those projects to have them available in your local Maven cache. SparseMatrix is a simple Java sparse matrix implementation used primarily as interface between the annotation based Java API and the DSL. So it allows to write code independend from GA-specific objects. CGACasADi is a fast symbolic implementation of CGA based on CasADI. A Java-Wrapper for CasADI based on Swig is used for Java integration.
In order to run the example invokation in the package 'de.dhbw.rahmlab.geomalgelang.App' make sure you successfully executed the steps GraalVM Setup and Dependencies Setup beforehand. \ If you use an IDE other than Netbeans and execute the generated .class files directly rather than the generated .jar file, it might be necessary to configure the Maven execution in your IDE with the same properties set in the nbactions.xml file.
An annotation based API useful especially for testing is available.
A Syntax-Highlighting plugin for the Netbeans-IDE can be found here.
A Netbeans-IDE plugin which adds a submenu into the context-menu of the editor to insert CGA-specific symbols and operators can be found here.
There are two implementations of the API:
Their syntax will be the same in the longrun. However, during development of the language, some syntactical constructs will temporarily not supported by one or the other.
The following features are supported ("x" is yes, "-" is no): | F | T | Feature |
---|---|---|---|
- | x | Visualization | |
- | x | Debugger |
main
. Invokations of the program will call this one first.main
needs to be the last function defined.Custom functions can be defined like in the following example:
fn test(a) {
a, 5
}
fn main(a, b) {
_, c := test(b)
a, b, c
}
Variables can be visualized after assignment with a preceding colon. For correct visualization, make sure that the variable is in IPNS representation. \ In the following example, the variable b will be visualized:
fn main(a) {
:b := a
}
Hint: Operator precedence determines how operators are parsed concerning each other. A higher precedence number results in a higher binding strength. Thus operators with higher precedence become the operands of operators with lower precedence.
Exceptions from the precedence rules:
a-b
evaluate to subtraction(a, b)
instead of geometric_product(a, negate(b))
.All 2-ary operators are left-associative.
Hint: The Unicode and Latex name for the symbol used for left contraction is "RIGHT FLOOR" and for right contraction is "LEFT FLOOR". Please be cautious to this detail when writing Latex or programming tools which work with the language.
precedence | symbol | latex | unicode | name | implementation | hints |
---|---|---|---|---|---|---|
4 | \u0020 | geometric product | multivector1.gp(multivector2) | Zero or more space characters are interpreted as the operator. | ||
3 | ∧ | \wedge | \u2227 | outer product (join, span for no common subspace) | multivector1.op(multivector2), not used for double, for tuple3d it makes sense but actually no implementation is available | joining linearily independend vectors/two disjoint subspaces |
1 | + | + | \u002B | addition | multivector1.add(multivector2) | |
1 | - | - | \u002D | subtraction | multivector1.sub(multivector2) | |
3 | ⌋ | \rfloor | \u230B | left contraction | multivetor1.ip(multivector2, LEFT_CONTRACTION) | |
3 | ⌊ | \lfloor | \u230A | right contraction | multivector1.ip(multivector1, RIGHT_CONTRACTION); where the grade operator for negative grades is zero. This implies that something of higher grade cannot be contracted onto something of lower grade . |
|
3 | ∨ | \vee | \u2228 | regressive product (meet if intersected) | multivector1.vee(multivector2) or (multivector1 ∧ multivector2)* | |
2 | / | / | \u002F | division (inverse geometric product) | multivector1.div(multivector2) |
precedence | symbol | latex | unicode | description | implementation | CLUscript |
---|---|---|---|---|---|---|
3 | ⋅ | \cdot | \u22C5 | inner product | multivector1.ip(multivector2, RIGHT_CONTRACTION) | Decreasing dimensions or contracting a subspace. In the default configuration equal to left contraction (corresponding to Ganja.js). But this looks to be incompatible with some formulas in [Kleppe], which work only with the usage of right contraction. In CLUscript this corresponds to ".". |
3 | ∩ | \cap | \u2229 | meet (intersection) = largest common subspace | multivector1.meet(multivector2) | \& |
3 | ∪ | \cup | \u222A | join (union) of two subspaces is there smallest superspace = smallest space containing them both | multivector1.join(multivector2) or multivector2 ⋅ multivector1 or (multivector2 ∧ multivector1) | | |
All 1-ary operators have higher precedence than 2-ary ones. \ All 1-ary operators are right-sides except from the negate operator '-'. \ Except dual/undual the operators cancel itself so if your write X˜˜ no reverse is executed.
precedence | symbol | latex | unicode | description | implementation | CLUscript |
---|---|---|---|---|---|---|
5 | - | - | \u002D | negate | (-1 cast to multivector).gp(multivector) | - |
6 | ⁻¹ | \textsuperscript{-1} | \u207B\u00B9 | general inverse | multivector.generalInverse() | ! |
6 | * | \textsuperscript{*} | \u002A | dual | multivector.dual() | |
6 | ˜ | \textsuperscript{$\tilde$} | \u02DC | reverse/adjoint: reverse all multiplications (a sign change operation) | multivector.reverse() | ˜ |
6 | † | \textsuperscript{\textdagger} | \u2020 | clifford conjugate (a sign change operation) | multivector.conjugate() |
There exist three types of involution operations: Space inversion, reversion and the combination of both the clifford conjugation.
precedence | symbol | latex | unicode | description | implementation |
---|---|---|---|---|---|
6 | ⁻* | \textsuperscript{-*} | \u207B\u002A | undual | multivector.undual() or -multivector.dual() |
6 | ² | \textsuperscript{2} | \u00B2 | square | multivector.gp(multivector), sqr(double) |
6 | ^ | \textsuperscript{$\wedge$} | \u005E | grade involution/inversion (a sign change operation) | multivector.gradeInversion(multivector) |
symbol | latex | unicode | description | implementation |
---|---|---|---|---|
<multivector>ₚ (with ₚ ∈ {₀, ₁, ₂, ₃, ₄, ₅}) | < = \u003C, > = \u003E, ₀ = \u2080, ₁ = \u2081, ₂ = \u2082, ₃ = \u2083, ₄ = \u2084, ₅ = \u2085 | grade extraction, grade p=0-5 as subscript | multivector.extractGrade(int grade) |
symbol | description | implementation |
---|---|---|
exp() | exponential | MultivectorSymbolic.exp() |
normalize() | normalize by squared norm | MultivectorSymbolic.normalize() |
squaredNorm() | squared norm of a mulitvector | MultivectorSymbolic.squaredNorm() |
scp() | scalar product | not yet implemented |
dot() | dot product | not yet implemented |
abs() | absolute value of a scalar only | Math.abs(CGAScalar) |
sqrt() | square root of a scalar only | new CGAScalar(Math.sqrt(CGAScalar)) |
atan2(x,y) | arcus tansgens 2 (Converts the coordinates (x,y) to coordinates (r, theta) and returns the angle theta as the couterclockwise angle in radians between -pi and pi of the point (x,y) to the positive x-axis.) | new CGAScalar(Math.atan2(CGAScalar, CGAScalar)) |
negate14() | negate the signs of the vector- and 4-vector parts of an multivector. Usable to implement gerneral inverse. | MultivectorSymbolic.negate14() |
symbol | description | implementation |
---|---|---|
translator(tuple3d) | creates a translation from an 3d-tuple | createTranslation(tuple3d) |
rotator(tuple3d, double) | creates a rotation from an 3d-tuple representing the rotation axis and a double representing the angle in radian | createTranslation(tuple3d) |
symbol | latex | Unicode | description | implementation |
---|---|---|---|---|
ε₀ | \epsilon_0 | \u03B5\u2080 | base vector representing the origin | createOrigin(1d) |
εᵢ | \epsilon_i | \u03B5\u1D62 | base vector representing the infinity | createInf(1d) |
ε₁ | \epsilon_1 | \u03B5\u2081 | base vector representing x direction | createEx(1d) |
ε₂ | \epsilon_2 | \u03B5\u2082 | base vector representing y direction | createEy(1d) |
ε₃ | \epsilon_3 | \u03B5\u2083 | base vector representing z direction | createEz(1d) |
symbol | latex | Unicode | description | implementation |
---|---|---|---|---|
ε₊ | \epsilon_+ | \u03B5\u208A | ε₀ + 0.5εᵢ | |
ε₋ | \epsilon_- | \u03B5\u208B | 0.5εᵢ - ε₀ | |
π | \pi | \u03C0 | Ludolphs- or circle constant | Math.PI |
∞ | \infty | \u221E | corresponding to infinity vector in Dorst, Fontijne & Mann 2007 | 2ε₀ |
o | o | \u006F | corresponding to origin vector in Dorst, Fontijne & Mann 2007 | 0.5εᵢ |
n | n | \u006E | corresponding to infinity vector in Doran & Lasenby | εᵢ |
ñ | \tilde{n} | \u00F1 | corresponding to origin vector in Doran & Lasenby | -2ε₀ |
E₀ | E_0 | \u0045\u2080 | Minkovsky bi-vector (is its own inverse) | ε₀ ∧ εᵢ |
E₃ | E_3 | \u0045\u2083 | Euclidean pseudoscalar | ε₁ ∧ ε₂ ∧ ε₃ |
E | E | \u0045 | Pseudoscalar | ε₀ ∧ ε₁ ∧ ε₂ ∧ ε₃ ∧ εᵢ |
ε₀E₀=-ε₀, E₀ε₀=ε₀, εᵢE₀=εᵢ, E₀εᵢ=-εᵢ, E₀²=1, ε₀²=εᵢ²=0, ε₊²=1, ε₋²=-1, ε₊⋅ε₋=0