0.5.1 • Published 3 months ago

ts-geometric-algebra v0.5.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

ts-geometric-algebra

Ts-geometric-algebra is a Clifford Algebra Generator for TypeScript and JavaScript. It generates Geometric Algebras of any signature and is mostly combatible with Ganja.js. There is no operator overloading or inline functions yet due to lack of support in TypeScript.

(Mathematically, an algebra generated by ts-geometric-algebra is a graded exterior (Grassmann) algebra with a non-metric outer product, extended (Clifford) with geometric and contraction inner products, a Poincare duality operator and the main involutions and morphisms.)

(Technically, ts-geometric-algebra is a code generator producing classes that reificate algebraic literals.)

(Practically, ts-geometric-algebra enables algebraic operations over reals, complex numbers, dual numbers, hyperbolic numbers, vectors, spacetime events, quaternions, dual quaternions, biquaternions or any other Clifford Algebra with full type support from TypeScript.)

Discourse and Discord

Visit bivector.net for our forum and chat - the perfect place for questions and support.

Using ts-geometric-algebra for the first time

Install ts-geometric-algebra using npm :

npm install ts-geometric-algebra

And require it in your script :

const Algebra = require('ts-geometric-algebra').default;

The Algebra Function

To create an Algebra, call the Algebra function specifying the metric signature (number of positive, negative and zero dimensions). The result is an ES6 class implementing the requested clifford algebra.

function Algebra( p, q, r );
  // p    = number of positive dimensions.
  // q    = optional number of negative dimensions.
  // r    = optional number of zero dimensions.

An extended syntax is also available that allows you to further tweak the created Algebra.

function Algebra( p, q, r, {baseType, metric, mulTable, disableUnroll} )
  // p        = number of positive dimensions.
  // q        = optional number of negative dimensions.
  // r        = optional number of zero dimensions.
  // baseType = Float32Array or similar
  // metric   = basis vector inner products in custom order, must agree with p, q and r
  // mulTable = Custom signs for the Caley table
  // disableUnroll = (boolean) prevent loop unrolling of performance critical methods

Here are some examples :

// Basic
const Hyper   = Algebra(1);         // Hyperbolic numbers.
const Complex = Algebra(0, 1);      // Complex numbers.
const Dual    = Algebra(0, 0, 1);   // Dual numbers.
const H       = Algebra(0, 2);      // Quaternions.

// Clifford
const Cl2 = Algebra(2);             // Clifford algebra for 2D vector space.
const Cl3 = Algebra(3);             // Clifford algebra for 3D vector space.
const TimeSpace = Algebra(1, 3);    // Clifford algebra for timespace vectors.

// Geometric
const PGA2D = Algebra(2, 0, 1);     // Projective Euclidean 2D plane. (dual)
const PGA3D = Algebra(3, 0, 1);     // Projective Euclidean 3D space. (dual)
const CGA2D = Algebra(3, 1);        // Conformal 2D space.
const CGA3D = Algebra(4, 1);        // Conformal 3D space.

// High-Dimensional GA
const DCGA3D = Algebra(6, 2);       // Double Conformal 3D Space.
const TCGA3D = Algebra(9, 3);       // Triple Conformal 3D Space.
const DCGSTA = Algebra(4, 8);       // Double Conformal Geometric Space Time Algebra.
const QCGA   = Algebra(9, 6);       // Quadric Conformal Geometric Algebra.

You can now use these classes to generate algebraic elements. Those elements will have all of the expected properties. (norm, blade access, dot, wedge, mul, dual, inverse, etc ...)

Unlike Ganja.js you must use them in a 'classic' programming style syntax like the example below.

const Complex = Algebra(0, 1);       // Complex numbers.
const a = Complex.fromGanja([3, 2]); // 3 + 2i
const b = Complex.fromGanja([1, 4]); // 1 + 4i
return a.mul(b);                     // returns [-5, 14]

Altough not as pretty or fun as Ganja.js you have the full advantage of types and autocompletion.

Methods

Object orientedGanja EquivalentExplanation
x.equals(y)N/AStrict equality
x.closeTo(y, tol?)N/AEquality within given tolerance
x.hasNaN()N/ACheck for Not-a-Numbers
x.hasInfinity()N/ACheck for (negative) infinity
x.isNil(tol?)N/AEqual or close to zero
x.isGrade(g, tol?)N/AOnly has components of grade g
x.sx.sScalar part (get/set)
x.psN/APseudoscalar part (get/set)
x.getAt(...idx)N/AMetric-aware coefficient of the product of basis factors defined by idx
x.setAt(...idx, a)N/ASet coefficient of product of basis factors idx as a
x.norm()x.LengthConjugate norm (metric-aware)
x.vnorm()x.VLengthVector norm (ignores metric) {x.length is array length}
x.taxicabNorm()N/AL1 norm (ignores metric)
x.maxNorm()N/ALinfinity norm (ignores metric)
x.neg()N/ANegation (additive inverse)
x.cwAbs()N/AComponent-wise absolute value
x.involute()x.InvoluteNegation of basis factors
x.rev()x.ReverseReversal of basis factors {x.reverse is array reversal}
x.conjugate()x.ConjugateConjugation (combined involution and reversal)
x.adjugate()N/AUnscaled multiplicative inverse (suitable for int base class)
x.inverse()x.InverseMultiplicative inverse
x.square()x.Mul(x)Multiplicative squaring (**)
x.normalize(a?)x.Normalizex with norm set to a (default 1)
x.rotorNormalize()N/ANormalize rotor x
x.sqrt()N/ASquare root. Currently reliable only in dimensions < 2
x.rotorSqrt()N/ARotor square root. Available in certain metrics.
x.exp()x.ExpExponential function
x.bivectorExp()x.ExpBivector exponential function (optimized)
x.log()x.Log(Motor) Logarithm. Generic exp inverse available only in dimensions < 2
x.rotorLog()x.LogRotor Logarithm
x.clone()x.Scale(1)Independent copy
x.dual()x.Dual (*)Metric independent dual: x.mul(x.dual()) = Cl.pseudoscalar()
x.undual()N/AInverse of x.dual()
x.scale(a)x.Scale(a)Scalar multiplication
x.pow(n)x.Pow(n)Multiply x with itself n times
x.applyWeights(ws)N/AReplace each basis factor with a weighted copy for every weight in ws
x.negateGrades(...gs)x.Map(...gs)Negate the given grades
x.add(y)x.Add(y)Component-wise addition (**)
x.sub(y)x.Sub(y)Component-wise subtraction (**)
x.mul(y)x.Mul(y)Geometric product of x and y (**)
x.lmul(y)y.Mul(x)Geometric product from the left (**)
x.div(y)x.Div(y)Geometric division from the right
x.ldiv(y)y.Inverse.Mul(x)Left inverse product
x.ldivs(y)x.Inverse.Mul(y)Geometric division from the left
x.wedge(y)x.Wedge(y)Wedge (outer) product. Metric independent (**)
x.lwedge(y)y.Wedge(x)Wedge product from the left (**)
x.vee(y)x.Vee(y)Vee (dual) product. Metric indepentend. x.vee(y) = y.dual().wedge(x.dual()).undual() (**)
x.lvee(y)y.Vee(x)Vee product from the left (**)
x.rotorMean(y)N/AGeometric mean of rotors x and y
x.contract(y, ctn)N/AContract x by y using criterion ctn
x.dot(y)x.Dot(y)Dot product. Symmetric criterion (**)
x.dotL(y)x.LDot(y)Left contraction of x by y (**)
x.ldotL(y)y.LDot(x)Left contraction of y by x (**)
x.dotR(y)N/ARight contraction of x by y
x.ldotR(y)N/ARight contraction of y by x
x.dotS(y)N/AScalar product. Nil criterion
x.imag()N/AFilter out grade 0
x.even()x.Even()Filter out odd grades
x.grade(n)x.Grade(n)Keep only grade n components
x.vector()x.VectorArray of vector components
x.vector(n)N/AArray of n-vector components
x.rotor()N/AArray of components of even grade
x.ganja()xArray of all components in lexicographic order
x.invScale(y, t?)N/ARatio of weights between coincident x and y. Returs NaN if non-coincidence exteeds threshold t.
x.grades(t?)N/AArray of grades present in x exceeding threshold t (default 0)
x.meetJoin(y, t?)N/ATrue (of threshold t) meet and join of blades x and y
x.star(y)N/AScalar product with number result
Cl.zero()Cl.Scalar(0)Zero element
Cl.scalar(a?)Cl.Scalar(a)Scalar element of size a (default 1)
Cl.pseudoscalar(a?)N/APseudoscalar element of size a (default 1)
Cl.basisBlade(...idx)N/AUnit basis blade given by the product of the given basis factors
Cl.fromVector(vs)Cl.Vector(...vs)Vector element with given components (from an array)
Cl.fromVector(vs, 2)Cl.Bivector(...vs)Bivector element with given components (lexicographic order)
Cl.fromVector(vs, 3)Cl.Trivector(...vs)Trivector element with given components
Cl.fromVector(vs, g)Cl.nVector(g, ...vs)g-vector element with given components
Cl.fromRotor(vs)N/AEven grade element with given components
Cl.fromGanja(vs)new Cl(vs)New element with components given in lexicographic order
Cl.dimensions-->Math.log(Cl.describe().basis.length)/Math.LN2 number of dimensions
Cl.size-->Cl.describe().basis.length algebra size
Cl.metric-->Cl.describe().metric.slice(1, n+1) basis vector metric
Cl.mulTable-->Similar to Cl.describe().mulTable but signs only
new Cl(vs)N/ANot recommended, use fromGanja instead. New element with components given in bit field order

(*) Only in degenerate metrics (**) Loop unrolled for maximum performance

Dual Zoo

Object orientedFunction OrientedGanja EquivalentExplanation
x.podge()podge(x)x.Mul(ps)Right-multiplication by Cl.pseudoscalar()
x.unpodge()unpodge(x)x.Div(ps)Right-division by Cl.pseudoscalar()
x.podgeL()podgeL(x)ps.Mul(x)Left-multiplication by Cl.pseudoscalar()
x.unpodgeL()unpodgeL(x)ps.Inverse.Mul(x)Left-division by Cl.pseudoscalar()
x.star()star(x)N/ANon-degenerate x.podge()
x.unstar()unstar(x)N/AInverse of x.star()
x.starL(x)starL(x)x.Dual (*)Non-degenerate x.podgeL()
x.unstarL(x)unstarL(x)N/AInverse of x.starL()
x.hodge()hodge(x)N/AHodge dual
x.unhodge()unhodge(x)N/AInverse of x.hodge()
x.hodgeL()hodgeL(x)N/ALeft Hodge dual
x.unhodgeL()unhodgeL(x)N/AInverse of x.hodgeL()

(*) Only in non-degenerate metrics

Rotor operation availability

Metric (pqr)Available operations
p+q+r <= 2(all)
400rotorSqrt, rotorNormalize
310rotorSqrt, rotorNormalize
301rotorLog, rotorSqrt, rotorNormalize
410rotorSqrt, rotorNormalize

Functions

Function OrientedGanja EquivalentExplanation
equals(x, y)N/AStrict equality
closeTo(x, y, tol?)N/AEquality within given tolerance
hasNaN(x)N/ACheck for Not-a-Numbers
hasInfinity(x)N/ACheck for (negative) infinity
isNil(x, tol?)N/AEqual or close to zero
isGrade(x, g, tol?)N/AOnly has components of grade g
norm(x)x.LengthConjugate norm (metric-aware)
vnorm(x)x.VLengthVector norm (ignores metric) {x.length is array length}
taxicabNorm(x)N/AL1 norm (ignores metric)
maxNorm(x)N/ALinfinity norm (ignores metric)
neg(x)N/ANegation (additive inverse)
cwAbs(x)N/AComponent-wise absolute value
involute(x)x.InvoluteNegation of basis factors
rev(x)x.ReverseReversal of basis factors {x.reverse is array reversal}
conjugate(x)x.ConjugateConjugation (combined involution and reversal)
adjugate(x)x.InverseUnscaled multiplicative inverse
inverse(x)x.InverseMultiplicative inverse
square(x)x.Mul(x)Multiplicative squaring (**)
normalize(x, a?)x.Normalizex with norm set to a (default 1)
rotorNormalize(x)N/ANormalize rotor x
sqrt(x)N/ASquare root. Currently reliable only in dimensions < 2
rotorSqrt(x)N/ARotor square root. Available in certain metrics.
exp(x)x.ExpExponential function
bivectorExp(x)x.ExpBivector exponential function (optimized)
log(x)x.Log(Motor) Logarithm. Generic exp inverse available only in dimensions < 2
rotorLog(x)x.LogRotor Logarithm
clone(x)x.Scale(1)Independent copy
dual(x)x.Dual (*)Metric independent dual: x.mul(x.dual()) = Cl.pseudoscalar()
undual(x)N/AInverse of x.dual()
scale(x, a)x.Scale(a)Scalar multiplication
pow(x, n)x.Pow(n)Multiply x with itself n times
applyWeights(x, ws)N/AReplace each basis factor with a weighted copy for every weight in ws
negateGrades(x, ...gs)x.Map(...gs)Negate the given grades
add(...args)x.Add(y)Component-wise addition (**)
sub(x, y)x.Sub(y)Component-wise subtraction (**)
mul(...args)x.Mul(y)Geometric product of x and y (**)
div(x, y)x.Div(y)Geometric division from the right
ldivs(x, y)x.Inverse.Mul(y)Geometric division from the left
wedge(...args)x.Wedge(y)Wedge (outer) product. Metric independent (**)
vee(...args)x.Vee(y)Vee (dual) product. Metric indepentend. vee(x, y) = undual(dual(y), dual(x)) (**)
rotorMean(x, y)N/AGeometric mean of rotors x and y
contract(x, y, ctn)N/AContract x by y using criterion ctn
dot(x, y)x.Dot(y)Dot product. Symmetric criterion (**)
dotL(x, y)x.LDot(y)Left contraction of x by y (**)
dotR(x, y)N/ARight contraction of x by y
dotS(x, y)N/AScalar product. Nil criterion
imag(x)N/AFilter out grade 0
even(x)x.Even()Filter out odd grades
grade(x, n)x.Grade(n)Keep only grade n components
invScale(x, y, t?)N/ARatio of weights between coincident x and y. Returs NaN if non-coincidence exteeds threshold t.
grades(x, t?)N/AArray of grades present in x exceeding threshold t (default 0)
meetJoin(x, y, t?)N/ATrue (of threshold t) meet and join of blades x and y
star(x, y)N/AScalar product with number result

(*) Only in degenerate metrics (**) Loop unrolled for maximum performance

The functions equals, closeTo, add, sub, mul, div, ldivs, wedge, vee also work on the number type.

Linear equation solver

You can solver equations of the form (for the moment pretending that javascript has scalar multiplication of arrays)

x = coeffs[0] * basis[0] + coeffs[1] * basis[1] + ... + coeffs[n-1] * basis[n-1]

for the unknown coefficients coeffs.

const coeffs = vLinSolve(x, basis);

This comes with the added cost of algebra creation on each call. If you need to do a lot of solving create your algebra beforehand.

import {Algebra, linSolve} from 'ts-geometric-algebra';
const Grassmann = Algebra(0, 0, 3);
const x = Grassmann.fromVector([1, 2, 3]);
const basis = [
  Grassmann.fromVector([1, 1, 1]),
  Grassmann.fromVector([0, 1, -1]),
  Grassmann.fromVector([-1, 2, -2])
];
const coeffs = linSolve(x, basis);  // [ 2.5, -3.5, 1.5 ]

Octonions

While all generated geometric algebras are associative it's possible to produce non-associative algebras using custom multiplication tables. This package comes with a pre-configured table for Octonions and monkey-patches conjugate, inverse, sqrt, exp and log to work correctly.

import {makeOctonion} from 'ts-geometric-algebra';
const O = makeOctonion();
const e1 = Octonion.basisBlade(0);
const e2 = Octonion.basisBlade(1);
const e4 = Octonion.basisBlade(2);

e1.mul(e2).mul(e4)  // [0, 0, 0, 0, 0, 0, +1]
e1.mul(e2.mul(e4))  // [0, 0, 0, 0, 0, 0, -1]
0.5.1

3 months ago

0.5.0

1 year ago

0.4.2

2 years ago

0.4.1

2 years ago

0.4.0

2 years ago

0.3.0

2 years ago

0.2.2

2 years ago

0.2.1

2 years ago

0.2.0

2 years ago

0.1.1

2 years ago