this is a javascript library for fundamental calculations in euclidean and conformal geometric algebras. custom algebras are supported.
the focus of this implementation is on flexibility (functional with basic data structures and loose coupling for easy abstraction) as well as compactness and generality (straightforward with no limitations).
the collection of automated tests may also be useful for testing other geometric algebra libraries.
fundamentals have been implemented and tested. currently being refined through use in an initial application. users are encouraged to try the library and report any issues.
compiled/sph_ga.js contains the javascript version.
use with node.js via require("./sph_ga.js")
or include the code in html using <script type="text/javascript" src="sph_ga.js"></script>
.
the examples are using the coffeescript javascript syntax.
r3 = new sph_ga [1, 1, 1]
this example supplies an euclidean metric. for more options, see the section "customization" below.
all these types are represented as multivector objects.
s(number)
creates a scalar.
s1 = r3.s 1
basis(n, scale=1)
creates the basis vector with that index.
e3 = r3.basis 3
vector([coefficient, ...])
creates a multivector for as many bases in order as specified. the first array element is the scalar.
a = r3.vector [0, 2, 3, 4] # a = 0 + 2e1 + 3e2 + 4e3
mv([[[basis_index ...], coefficient], ...])
creates custom multivectors where multiple exterior-product-combined basis indices can be specified for each blade. blades can be specified arbitrarily in any order.
a = r3.mv [
[[0], 1] # scalar part: 1
[[2], 3] # 3 * e2
[[2, 3], 4] # 4 * e23
]
strings can also be used: r3.mv_from_string "1 + e2 + 2e1_3"
. this is only for multivector creation and does not support other calculations.
e1 = r3.basis 1
e2 = r3.basis 2
e3 = r3.basis 3
exterior_product = r3.ep e1, e2
geometric_product = r3.gp e1, e2
# 1 + 2 * e1 + 3 * e23
a = r3.mv [
[[0], 1]
[[1], 2]
[[2, 3], 3]
]
# 4 * e2 + 5 * e123
b = r3.mv [
[[2], 4]
[[1, 2, 3], 5]
]
inner_product = r3.ip a, b
see section "api" for all available functions.
blades are accesible by id
in a vector object.
get(multivector, id)
extracts a blade with a specific id or returns null
if it is not included.
a = r3.s -4
scalar_coefficient = blade_coeff get a, 0 # -4
ps = r3.pseudoscalar()
ps_grade = r3.grade ps # should be 3 for r3
ps_squared = r3.gp ps, ps # should be -1 for r3
r3.n # dimensions
sph_ga uses three compound types: space (object), multivector (array[][3]), and blade (array[3]).
in this library, round bracket enclosed lists are javascript arrays. note that the functions do not validate input arguments and expect strict adherence to the contract. the listing uses this type signature format.
# the number of dimensions is defined by the length of the metric.
constructor :: metric options -> object
# create a scalar
s :: coefficient -> multivector
# get a basis vector of index. 1 -> e1, 2 -> e2, ..., n -> en
basis :: basis_index -> multivector
# a multivector of the scalar and one or more 1-blades.
# adds as many basis blades in order as specified.
vector :: (coefficient ...) -> multivector
# create a multivector by specifying multiple blade terms
mv :: (((basis_index ...) coefficient) ...) -> multivector
# calculates the left contraction clifford (geometric) inner product.
# the grade of the first argument must be less than or equal to the grade of the second argument
ip :: multivector ... -> multivector
# calculates the exterior product (also known as the wedge product or outer product)
ep :: multivector ... -> multivector
# calculates the geometric product
gp :: multivector ... -> multivector
# compute the sandwich product: a * b * a ** -1
sp :: multivector multivector -> multivector
# reverse the order of basis vectors of each blade.
# each coefficient is multiplied by (-1 ** (k * (k - 1) / 2)), where k is the grade
reverse :: multivector -> multivector
# changes the sign of blades based on their grade.
# each coefficient is multiplied by (-1) ** k
involute :: multivector -> multivector
# combines the reverse and involute operations.
# each coefficient is multiplied by (-1) ** (k * (k + 1) / 2)
conjugate :: multivector -> multivector
add :: multivector ... -> multivector
subtract :: multivector ... -> multivector
pseudoscalar :: -> multivector
inverse :: multivector -> multivector
grade :: multivector -> integer
id_from_indices :: (basis_index ...) -> id
id_indices :: (id) -> (basis_index ...)
mv_to_string :: multivector -> string
mv_from_string :: string -> multivector
# accessors
get :: multivector id -> blade/null
blade_id :: blade -> id
blade_coeff :: blade -> coefficient
blade_grade :: blade -> integer
space object properties
n: integer # number of dimensions
metric: ((integer) ...) # always an n * n array
pseudoscalar_id
basis_index: integer
id: integer:bitset
coefficient: number
blade: array:(id coefficient grade)
multivector: array:(blade ...)
sph_ga has special features for cga. when the conformal option is set to true for a space, it automatically adds two dimensions and uses the conformal metric.
- the null vectors will always be appended to the end of the list of canonical bases: e1, e2, ..., en, no, ni.
- the default conformal metric is a split-signature metric with two off-diagonal -1 terms for the null vector interactions.
- ei · ei = 1 for 1 <= i <= n
- no · no = 0
- ni · ni = 0
- no · ni = -1
- ei · n0 = 0 and ei · ni = 0 for 1 <= i <= n
- ei · ej = 0 for i != j
- the pseudoscalar is defined as: pseudoscalar = e1 * e2 * ... * en * no * ni
- normalization: pseudoscalar ** 2 = 1
# only the euclidean part of the metric has to be specified.
c3 = new sph_ga [1, 1, 1], conformal: true
# reflecting a point across a plane defined by a normal vector n.
# assume n is a unit vector in the conformal space
e1 = c3.basis 1
e2 = c3.basis 2
n = c3.add e1, e2
point = c3.point 1, 2, 3
# reflection formula: p' = -n * p * n
reflected_point = c3.gp c3.gp(c3.reverse(n), point), n
functions
# create a basis vector for the origin. also known as "e0" and "e+"
no :: coefficient -> multivector
# create a basis vector for infinity. also known as "e∞"" and "e-"
ni :: coefficient -> multivector
# create a conformal point. requires only the coefficients for the euclidean part
point :: (coefficient ...) -> multivector
# create a rotor. takes the coefficient for the scalar followed by the rotation axes
rotor :: (coefficient ...) -> multivector
# a normalized multivector across all basis blades
normal :: -> multivector
space properties
no_index
ni_index
no_id
ni_id
these should better use the name no
and ni
, but coffeescript does not allow no
as a variable name, which might be inconvenient.
the metric array passed in the options defines the signature of the space. each element represents the square of a basis vector combination:
1
for spacelike dimensions-1
for timelike dimensions0
for null dimensions
other values, eg for non-diagonal metrics, are possible. metrics must be symmetric. diagonal metrics can be configured using flat arrays. for example, [1, 1, 1]. custom tensors can be provided as an "n * n" array. example for five dimensions:
metric = [
[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, -1],
[0, 0, 0, -1, 0],
]
space = new sph_ga metric
parsing and creating multivector string representations is supported.
valid example components
20.12
e2
20.12e1
e1_4_6
20.12e1_4_6
multivector example
2 + e1 + e2_3
conversion examples
mystring = r3.mv_from_string "2 + e1 + e2_3"
r3.mv_to_string mymv
input = [ number ], [ letters ], [ "_" , integer_list ] ;
number = digit , { digit } , [ "." , digit , { digit } ] ;
letters = letter , { letter } ;
integer_list = integer , { "_" , integer } ;
integer = digit , { digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
letter = "a" | "b" | "c" | "d" | ... | "z" ;
run via ./exe/tests
. the code for the test cases, data generator, and runner, is located in src/test.coffee.
what this library will not provide:
- operator overloading
- code generation
- string notation for complex operations
- graphical functions
lgpl3+
- simplify multivector component access
- performance optimizations
- the library could easily be ported to c