This module implements three-dimensional Euclidean geometry using the projective geometric algebra (PGA) model.
Points, lines, planes, and rigid-body transformations are encoded as multivectors, allowing geometric constructions to be expressed through algebraic operations such as the wedge product, meet, join, and sandwich product.
Cl(3,0,1)with signature:
{1,1,1,0} # e1*e1 = 1, e2*e2 = 1, e3*e3 = 1, e0*e0 = 0and basis:
e1, e2, e3, e0where e0 is the ideal (infinite) basis vector.
This module uses the dual representation of projective geometric algebra. In this representation, geometric objects are represented by their dual blades.
This duality is a property of the representation, not a change in the underlying geometry. In the dual representation:
- planes are vectors (1-blades)
- lines are bivectors (2-blades)
- points are trivectors (3-blades)
These are projective objects and should not be confused with Euclidean direction vectors.
join(a, b) = undual(wedge(dual(a), dual(b)))
meet(a, b) = wedge(a, b)With this module's basis convention, finite points are represented as:
P = e123 + x*e032 + y*e013 + z*e021where the coefficient of e123 is the homogeneous scale factor.
Ideal points have a zero e123 component:
P∞ = x*e032 + y*e013 + z*e021Ideal points represent directions and are points at infinity. They are distinct from Euclidean vectors, which are represented by grade-1 elements.
Motors
Euclidean rigid-body transformations are represented by motors.
This module supports:
- translations
- rotations around lines
- motor transformations using the sandwich product
- interpolation through motor logarithms and exponentials
A motor transformation is applied as:
M X M⁻¹Examples
iex> p = Galixir.Algebras.PGA3.point(1, 2, 3)
iex> Galixir.Algebras.PGA3.point_coordinates(p)
{1.0, 2.0, 3.0}
Summary
Functions
Adds two multivectors component-wise.
Computes the motor aligning corresponding geometric objects.
Checks whether a multivector is a blade.
Returns the mapping between blade names and storage indices.
Returns the canonical sign of a multivector.
Returns the coefficient of a basis blade.
Checks whether two homogeneous objects represent the same entity.
Returns the dimension of the algebra.
Returns the vector from point a to point b.
Returns the ideal point representing a line direction.
Extracts a Euclidean direction vector from a line.
Computes the Euclidean distance between two points.
Computes the dual of a multivector.
Checks whether a point is finite.
Computes the geometric product of two multivectors.
Returns the grade of a homogeneous multivector.
Extracts the grade-g component of a multivector.
Checks whether a multivector contains components of the given grade only.
Returns the grades present in a multivector.
Checks whether a line is ideal.
Creates the ideal point representing a direction.
Checks whether a point is ideal.
Tests whether two geometric objects are incident.
Computes the inner product of two multivectors.
Computes the inverse of a multivector.
Checks whether a multivector contains components of the given grade only.
A guard that matches multi vectors that are all zero.
Computes the join of two objects.
Computes the left contraction of two multivectors.
Creates the line through two points.
Returns the maximum absolute coefficient of a multivector.
Computes the meet of two objects.
Computes the exponential of a bivector motor logarithm.
Computes the logarithm of a motor.
Raises a motor to a scalar power.
Negates a multivector.
Returns the norm of a multivector.
Normalizes a multivector.
Normalizes a line motor axis.
Returns a normalized line direction vector.
Returns the normalized plane normal.
Returns the scalar identity element.
Returns the Euclidean origin point.
Checks whether two lines are parallel.
Creates a plane from coefficients.
Creates a plane from a normal vector and a point.
Extracts the normal vector from a plane.
Creates a finite point.
Returns Cartesian coordinates of a finite point.
Applies the reverse operation to a multivector.
Computes the right contraction of two multivectors.
Creates a rotation motor around an axis.
Computes the rotor that maps one frame to another.
Checks whether a multivector contains only a scalar component.
Returns the scalar coefficient of a multivector.
Computes the scalar product.
Creates a multivector from a string representation.
Returns the metric signature of the algebra.
Returns the number of coefficients stored by the algebra.
Returns the squared norm of a multivector.
Subtracts two multivectors component-wise.
Returns the multiplication table for the algebra.
Formats a multivector using standard geometric algebra notation.
Applies a motor transformation to an object.
Creates a translation motor from a vector.
Creates a translation motor.
Computes the inverse dual operation.
Creates a Euclidean direction vector.
Computes the outer product (wedge product) of two multivectors.
Computes the outer product of a list of multivectors.
Returns the zero multivector.
Checks whether all coefficients of a multivector are zero.
Functions
Adds two multivectors component-wise.
Examples
iex> a = new(scalar: 2)
iex> b = new(scalar: 3)
iex> add(a, b)
new(scalar: 5)
Computes the motor aligning corresponding geometric objects.
The constraints can be finite points or ideal points (directions). Each pair contributes a positional or rotational constraint.
Lines and planes are not directly supported; represent them using their defining points and directions.
The returned motor transforms the objects in the first list onto the corresponding objects in the second list.
An empty set of constraints returns the identity motor.
Uses an iterative PGA look-at style construction.
Examples
iex> align([], []) == one() true
iex> m = align([point(0,0,0)], [point(1,2,3)]) iex> point(0, 0, 0) ...> |> transform(m) ...> |> point_coordinates() {1.0, 2.0, 3.0}
iex> from = [ ...> point(0, 0, 0), ...> point(1, 0, 0) ...> ] iex> to = [ ...> point(0, 0, 0), ...> point(0, 1, 0) ...> ] iex> m = align(from, to) iex> point(1, 0, 0) ...> |> transform(m) ...> |> point_coordinates() {0.0, 1.0, 0.0}
iex> from = [ ...> point(0, 0, 0), ...> point(1, 0, 0), ...> point(0, 1, 0) ...> ] iex> to = [ ...> point(1, 2, 3), ...> point(1, 3, 3), ...> point(0, 2, 3) ...> ] iex> m = align(from, to) iex> point_coordinates(transform(point(1, 0, 0), m)) {1.0, 3.0, 3.0}
iex> l1 = line(point(0, 0, 0), point(1, 0, 0)) iex> l2 = line(point(0, 0, 0), point(0, 1, 0)) iex> m = align([l1], [l2]) iex> transformed = transform(l1, m) iex> coincident?(transformed, l2) true
iex> l1 = line(point(0, 0, 0), point(1, 0, 0)) iex> l2 = line(point(5, 6, 7), point(6, 6, 7)) iex> m = align([l1], [l2]) iex> coincident?(transform(l1, m), l2) true
iex> p1 = plane(0, 0, 1, 0) iex> p2 = plane(1, 0, 0, 0) iex> m = align([p1], [p2]) iex> coincident?(transform(p1, m), p2) true
iex> p1 = plane(0, 0, 1, 0) iex> p2 = plane(0, 0, 1, -5) iex> m = align([p1], [p2]) iex> coincident?(transform(p1, m), p2) true
iex> p = point(1, 2, 3) iex> m = align([p], [p]) iex> point_coordinates(transform(p, m)) {1.0, 2.0, 3.0}
iex> from = [ ...> point(0, 0, 0), ...> point(1, 0, 0) ...> ] iex> to = [ ...> point(3, 4, 5), ...> point(3, 5, 5) ...> ] iex> m = align(from, to) iex> inv = inverse(m) iex> point_coordinates(transform(transform(point(7, 8, 9), m), inv)) {7.0, 8.0, 9.0}
iex> l2 = line(point(10, 20, 30), point(10, 21, 30)) iex> from = [ ...> point(0,0,0), ...> point(1,0,0) ...> ] iex> to = [ ...> point(10,20,30), ...> point(10,21,30) ...> ] iex> m = align(from, to) iex> coincident?(transform(line(Enum.at(from,0), Enum.at(from,1)), m), l2) true
iex> l1 = line(point(0, 0, 0), point(0, 0, 1)) iex> l2 = line(point(5, 5, 5), point(5, 5, 6)) iex> m = align([l1], [l2]) iex> coincident?(transform(l1, m), l2) true
iex> align([point(0, 0, 0)], []) ** (ArgumentError) cannot align different numbers of objects
Checks whether a multivector is a blade.
A blade is a multivector containing components from at most one grade.
Scalars are considered blades.
Examples
iex> blade?(new(e1: 2))
true
iex> blade?(new(e12: 1))
true
iex> blade?(new(e1: 1, e2: 1))
true
iex> blade?(new(scalar: 2, e1: 2))
false
iex> blade?(new(e2: 2, e12: 2))
false
Returns the mapping between blade names and storage indices.
Blade coefficients are stored in a fixed-size tuple. This map translates canonical blade names into their corresponding tuple index.
Example
iex> blade_indices()[:e1]
1
Returns the canonical sign of a multivector.
The canonical sign is determined by the first non-zero coefficient in storage order.
Returns:
1if the first non-zero coefficient is positive-1if the first non-zero coefficient is negative0if all coefficients are zero
Examples
iex> canonical_sign(new(e1: 2))
1
iex> canonical_sign(new(e1: -2))
-1
iex> canonical_sign(new())
0
Returns the coefficient of a basis blade.
The requested blade can be given in canonical form or as any registered blade alias. Aliases are automatically converted to the canonical blade and the appropriate sign is applied.
## Examples
iex> coefficient( ...> new(e1: 3), ...> :e1 ...> ) 3.0
Checks whether two homogeneous objects represent the same entity.
Examples
iex> a = point(1, 2, 3, 1) iex> b = point(1, 2, 3, 2) iex> coincident?(a, b) true
Returns the dimension of the algebra.
This is the number of basis vectors defined by the signature.
Returns the vector from point a to point b.
Examples
iex> direction_between_points(point(1,2,3), point(4,6,8)) new(e1: 3, e2: 4, e3: 5)
Returns the ideal point representing a line direction.
Examples
iex> l = line(point(0,0,0), point(1,0,0)) iex> ideal_point?(direction_point(l)) true
Extracts a Euclidean direction vector from a line.
Examples
iex> l = line(point(1, 2, 3), point(2, 3, 4)) iex> direction_vector(l) new(e1: 1, e2: 1, e3: 1)
Computes the Euclidean distance between two points.
Examples
iex> distance(point(0, 0, 0), point(3, 4, 0))
5.0
Computes the dual of a multivector.
The dual maps each basis blade to its complementary blade with the appropriate orientation sign. The complement is determined by the full pseudoscalar of the algebra.
The operation is linear and applies independently to every coefficient.
Examples
iex> dual(new(e1: 1)) |> inspect
new(e230: 1.0) |> inspect
Checks whether a point is finite.
A finite point has a non-zero homogeneous component.
Examples
iex> finite_point?(point(1, 2, 3)) true
iex> finite_point?(ideal_point(1, 2, 3)) false
Computes the geometric product of two multivectors.
The geometric product is the fundamental multiplication operation of geometric algebra. It combines the outer product and metric-dependent inner product into a single associative operation.
The result depends on the algebra's metric signature.
Examples
iex> gp(
...> new(e1: 1),
...> new(e1: 1)
...> )
new(scalar: 1)
Returns the grade of a homogeneous multivector.
The zero multivector is considered grade 0.
Returns nil for mixed-grade multivectors.
iex> grade( ...> new(scalar: 1) ...> ) 0
iex> grade( ...> new(e1: 2) ...> ) 1
iex> grade( ...> new(scalar: 1, e1: 2) ...> ) nil
iex> grade( ...> new() ...> ) nil
Extracts the grade-g component of a multivector.
All coefficients whose basis blades are not of grade g are set to zero.
Raises ArgumentError if g is outside the range 0..dimension().
Examples
iex> grade(
...> new(scalar: 1, e1: 2),
...> 1
...> )
new(e1: 2)
iex> grade(
...> new(scalar: 1, e1: 2),
...> 0
...> )
new(scalar: 1)
Checks whether a multivector contains components of the given grade only.
A multivector is considered to have a grade if all non-zero components belong to that grade. The zero multivector is considered to have grade 0.
Examples
iex> grade?(new(e1: 1), 1)
true
iex> grade?(new(scalar: 1, e1: 2), 2)
false
iex> grade?(new(scalar: 1), 0)
true
iex> grade?(new(), 0)
trueSee is_grade/2
Returns the grades present in a multivector.
The returned list contains every grade with at least one non-zero coefficient, ordered from lowest to highest.
Examples
iex> grades(
...> new(scalar: 1)
...> )
[0]
iex> grades(
...> new(e1: 2)
...> )
[1]
iex> grades(
...> new(scalar: 1, e1: 2)
...> )
[0, 1]
iex> grades(
...> new()
...> )
[]
Checks whether a line is ideal.
An ideal line contains only directions and has no finite location.
Examples
iex> finite = line(point(0, 0, 0), point(1, 0, 0))
iex> ideal_line?(finite)
false
iex> offset = line(point(10, 5, 3), point(11, 5, 3))
iex> ideal_line?(offset)
false
iex> ideal = line(ideal_point(1, 0, 0), ideal_point(0, 1, 0))
iex> ideal_line?(ideal)
true
iex> ideal = line(ideal_point(1, 0, 0), ideal_point(0, 0, 1))
iex> ideal_line?(ideal)
true
iex> ideal = line(ideal_point(1, 0, 0), ideal_point(1, 0, 0))
iex> ideal_line?(ideal)
false
iex> zero?(line(ideal_point(1, 0, 0), ideal_point(1, 0, 0)))
true
Creates the ideal point representing a direction.
Do not use ideal points as direction vectors.
Use vector/3 when a Euclidean vector is required.
Examples
iex> ideal_point(1,2,3) new(e032: 1, e013: 2, e021: 3)
Checks whether a point is ideal.
An ideal point has no finite homogeneous component.
Examples
iex> ideal_point?(ideal_point(1,0,0)) true
iex> finite_point?(point(1,2,3)) true
Tests whether two geometric objects are incident.
Two objects are incident when they share a common geometric element. In the dual representation this is equivalent to their join being the zero multivector.
In this dual representation, incidence is tested using join. This is equivalent to the usual containment relation.
Examples
iex> p = point(1, 2, 3)
iex> l = line(point(0, 2, 3), point(5, 2, 3))
iex> incident?(p, l)
true
iex> p = plane(0, 0, 1, 0)
iex> incident?(p, point(1, 2, 0))
true
iex> p = plane(0, 0, 1, 0)
iex> incident?(p, point(1, 2, 3))
false
Computes the inner product of two multivectors.
The operation is generated from the geometric product and retains only terms satisfying the grade selection rule.
Example
iex> inner(
...> new(e1: 2),
...> new(e1: 3)
...> )
Computes the inverse of a multivector.
The inverse is computed using the reverse:
inverse(a) = reverse(a) / scalar_part(a * reverse(a))
This formula is valid when a * reverse(a) is a non-zero scalar.
Raises ArgumentError if the multivector is not invertible by this formula.
## Examples
iex> inverse(
...> new(e1: 2)
...> )|> inspect
new(e1: 0.5) |> inspect
Checks whether a multivector contains components of the given grade only.
A multivector is considered to have a grade if all non-zero components belong to that grade. The zero multivector is considered to have grade 0.
The is_grade(vector, grade) guard can be used in function guards:
def foo(mv) when is_grade(mv, 1) do
mv
endExamples
iex> grade?(new(e1: 1), 1)
true
iex> grade?(new(scalar: 1, e1: 2), 2)
false
iex> grade?(new(scalar: 1), 0)
true
iex> grade?(new(), 0)
trueSee grade?/2
A guard that matches multi vectors that are all zero.
Can be used in function guards:
def foo(x) when is_zero(x), do: x
Computes the join of two objects.
The join produces the smallest object containing both inputs.
Examples:
point ∨ point -> line
line ∨ point -> planeExamples
iex> a = point(0, 0, 0) iex> b = point(1, 0, 0) iex> line = join(a, b) iex> grade(line) 2
Computes the left contraction of two multivectors.
The operation is generated from the geometric product and retains only terms satisfying the grade selection rule.
Example
iex> left_contraction(
...> new(e1: 2),
...> new(e1: 3)
...> )
Creates the line through two points.
Examples
iex> a = point(0, 0, 0)
iex> b = point(1, 0, 0)
iex> l = line(a, b)
iex> grade(l)
2
Returns the maximum absolute coefficient of a multivector.
Accepts either a multivector struct or the internal coefficient tuple.
Example
iex> max_abs_component(new(e1: 2, scalar: 5))
5.0
iex> max_abs_component(new(e1: 5, scalar: 2))
5.0
Computes the meet of two objects.
The meet is the outer product. The meet operation does not imply that the result is a finite intersection. Parallel and skew objects may produce ideal elements or zero.
Examples:
plane ∧ plane -> line
line ∧ line -> pointExamples
iex> p1 = plane(1, 0, 0, 0)
iex> p2 = plane(0, 1, 0, 0)
iex> l = meet(p1, p2)
iex> grade(l)
2
Computes the exponential of a bivector motor logarithm.
Examples
iex> b = motor_log(translator(5,0,0)) iex> motor_exp(b) |> normalize() == normalize(translator(5,0,0)) true
Computes the logarithm of a motor.
Examples
iex> t = translator(10,0,0) iex> motor_exp(motor_log(t)) |> normalize() == normalize(t) true
Raises a motor to a scalar power.
Useful for motor interpolation.
Examples
iex> t = translator(10, 0, 0) iex> half = motor_pow(t, 0.5) iex> p = transform(origin(), half) iex> point_coordinates(p) {5.0, 0.0, 0.0}
Negates a multivector.
Examples
iex> negate(vector(1,2,3)).data new(e1: -1, e2: -2, e3: -3).data
Returns the norm of a multivector.
The norm is the square root of the absolute squared norm.
Example
iex> a = new(scalar: 3)
iex> norm(a)
3.0
Normalizes a multivector.
The result has unit norm while preserving the direction of the multivector.
Raises ArgumentError when attempting to normalize a null
multivector.
Example
iex> a = new(scalar: 2)
iex> norm(normalize(a))
1.0
Normalizes a line motor axis.
Examples
iex> l = line(point(0, 0, 0), point(0, 0, 1)) iex> n = normalize_line(l) iex> scalar_part(gp(n, n)) -1.0
Returns a normalized line direction vector.
Examples
iex> l = line(point(0,0,0), point(0,0,5)) iex> normalized_direction_vector(l) new(e3: 1.0)
Returns the normalized plane normal.
Examples
iex> normalized_plane_normal(plane(0, 0, 5, 0)) new(e3: 1.0)
Returns the scalar identity element.
Examples
iex> one() new(scalar: 1)
Returns the Euclidean origin point.
Examples
iex> point_coordinates(origin())
{0.0, 0.0, 0.0}
Checks whether two lines are parallel.
Two lines are parallel when they have the same ideal point (direction), including the case where they are identical.
Examples
iex> a = line(point(0, 0, 0), point(1, 0, 0))
iex> b = line(point(0, 1, 0), point(1, 1, 0))
iex> parallel?(a, b)
true
iex> a = line(point(0, 0, 0), point(1, 0, 0))
iex> b = line(point(0, 0, 0), point(0, 1, 0))
iex> parallel?(a, b)
false
iex> a = line(point(0, 0, 0), point(1, 0, 0))
iex> parallel?(a, a)
true
Creates a plane from coefficients.
Examples
iex> p = plane(0, 0, 1, 0)
iex> plane_normal(p)
new(e1: 0, e2: 0, e3: 1)
Creates a plane from a normal vector and a point.
Examples
iex> p = plane_from_normal_point(vector(0, 0, 1), point(1, 2, 3)) iex> incident?(p, point(10, -5, 3)) true
iex> p = plane_from_normal_point(vector(0, 0, 1), point(1, 2, 3)) iex> incident?(p, point(10, -5, 4)) false
Extracts the normal vector from a plane.
Examples
iex> plane_normal(plane(1, 2, 3, 4)) new(e1: 1, e2: 2, e3: 3)
Creates a finite point.
The homogeneous representation is:
P = e123 + x*e032 + y*e013 + z*e021Examples
iex> point_coordinates(point(1, 2, 3))
{1.0, 2.0, 3.0}
iex> finite_point?(point(1, 2, 3))
true
iex> ideal_point?(ideal_point(1, 0, 0))
true
Returns Cartesian coordinates of a finite point.
Examples
iex> point_coordinates(point(4,5,6)) {4.0, 5.0, 6.0}
Applies the reverse operation to a multivector.
Reverse (also called reversion) changes the sign of basis blades according to their grade:
grade 0: +
grade 1: +
grade 2: -
grade 3: -
grade 4: +
...For a blade with grade r, the sign is:
(-1)^(r(r-1)/2)Examples
iex> reverse(new(e1: 2))
new(e1: 2)
iex> reverse(new(e12: 2))
new(e12: -2)
iex> reverse(new(scalar: 3))
new(scalar: 3)
Computes the right contraction of two multivectors.
The operation is generated from the geometric product and retains only terms satisfying the grade selection rule.
Example
iex> right_contraction(
...> new(e1: 2),
...> new(e1: 3)
...> )
Creates a rotation motor around an axis.
Examples
iex> axis = line(point(0, 0, 0), point(0, 0, 1)) iex> r = rotor(axis, :math.pi()) iex> {x, y, z} = point(1, 0, 0) ...> |> transform(r) ...> |> point_coordinates() iex> abs(x + 1.0) < 1.0e-10 and abs(y) < 1.0e-10 and abs(z) < 1.0e-10
iex> axis = line(point(0, 0, 0), point(0, 0, 1)) iex> {x, y, z} = point(1, 0, 0) ...> |> transform(rotor(axis, :math.pi() / 2)) ...> |> point_coordinates() iex> {clean_zero(Float.round(x, 10)), clean_zero(Float.round(y, 10)), clean_zero(Float.round(z, 10))} {0.0, 1.0, 0.0}
iex> axis = line(point(0, 0, 0), point(1, 0, 0)) iex> {x, y, z} = point(0, 1, 0) ...> |> transform(rotor(axis, :math.pi() / 2)) ...> |> point_coordinates() iex> {clean_zero(Float.round(x, 10)), clean_zero(Float.round(y, 10)), clean_zero(Float.round(z, 10))} {0.0, 0.0, 1.0}
iex> axis = line(point(0, 0, 0), point(0, 1, 0)) iex> {x, y, z} = point(1, 0, 0) ...> |> transform(rotor(axis, :math.pi())) ...> |> point_coordinates() iex> {clean_zero(Float.round(x, 10)), clean_zero(Float.round(y, 10)), clean_zero(Float.round(z, 10))} {-1.0, 0.0, 0.0}
iex> axis = line(point(0, 0, 0), point(0, 0, 1)) iex> r = rotor(axis, :math.pi() / 3) iex> point(2, 3, 4) ...> |> transform(r) ...> |> transform(inverse(r)) ...> |> point_coordinates() {2.0, 3.0, 4.0}
Computes the rotor that maps one frame to another.
The function constructs blades from the source and target frames and computes the transformation rotor:
R = normalize(1 + T * S⁻¹)
where S is the source frame blade and T is the target frame blade.
The resulting rotor can be applied to multivectors to rotate the source frame into the target frame.
Checks whether a multivector contains only a scalar component.
Components with an absolute value smaller than eps are considered
zero.
Examples
iex> scalar?(new(scalar: 3))
true
iex> scalar?(new(e1: 3))
false
iex> scalar?(new())
true
Returns the scalar coefficient of a multivector.
This is equivalent to retrieving the coefficient of the scalar blade.
Examples
iex> scalar_part(new(scalar: 5.0, e1: 2.0))
5.0
Computes the scalar product.
Examples
iex> scalar_product(vector(1,2,3), vector(4,5,6)) 32.0
Creates a multivector from a string representation.
The ~G sigil provides a convenient syntax for constructing multivectors
using basis blades and coefficients.
Examples:
iex> ~G"e1 + e2"
new(e1: 1, e2: 1)
iex> ~G"2e1 - 0.5e12"
new(e1: 2, e12: -0.5)
iex> ~G"e12"
new(e12: 1)
iex> ~G"3"
new(scalar: 3)The parsed expression is converted into the same representation accepted by
new/1, so blade ordering and signs are handled by the algebra implementation.
Returns the metric signature of the algebra.
Example:
{1, 1, 1, 0}represents a projective geometric algebra with three Euclidean basis vectors and one null basis vector.
Returns the number of coefficients stored by the algebra.
A dimension n algebra contains 2^n basis blades.
Returns the squared norm of a multivector.
The squared norm is computed as:
scalar_part(a * reverse(a))The result may be negative for algebras with indefinite metrics.
Example
iex> a = new(scalar: 3)
iex> squared_norm(a)
9.0
Subtracts two multivectors component-wise.
Examples
iex> a = new(scalar: 5)
iex> b = new(scalar: 2)
iex> sub(a, b)
new(scalar: 3)
Returns the multiplication table for the algebra.
The table contains precomputed geometric products between basis blades.
Each entry maps {left_blade, right_blade} to {coefficient, result_blade}.
The blades are represented internally as bitmasks.
Example
iex> table() |> Map.has_key?({1, 1})
true
Formats a multivector using standard geometric algebra notation.
Zero coefficients are omitted. Coefficients of 1 and -1 are elided for
non-scalar basis blades.
Examples
iex> inspect(new())
"0"
iex> inspect(new(scalar: 2))
"2.0"
iex> inspect(new(e1: 1))
"e1"
iex> inspect(new(scalar: 1, e1: 2))
"1.0 + 2.0e1"
Applies a motor transformation to an object.
Examples
iex> origin() ...> |> transform(translator(1, 2, 3)) ...> |> point_coordinates() {1.0, 2.0, 3.0}
iex> m = translator(3, 4, 5) iex> origin() ...> |> transform(m) ...> |> point_coordinates() {3.0, 4.0, 5.0}
iex> m = translator(3, 4, 5) iex> point(1, 2, 3) ...> |> transform(m) ...> |> transform(inverse(m)) ...> |> point_coordinates() {1.0, 2.0, 3.0}
iex> m = gp(translator(1, 0, 0), translator(0, 2, 0)) iex> origin() ...> |> transform(m) ...> |> point_coordinates() {1.0, 2.0, 0.0}
Creates a translation motor from a vector.
Examples
iex> t1 = translator(1, 0, 0) iex> t2 = translator(0, 2, 0) iex> origin() ...> |> transform(gp(t2, t1)) ...> |> point_coordinates() {1.0, 2.0, 0.0}
Creates a translation motor.
Examples
iex> point_coordinates(transform(origin(), translator(1, 2, 3))) {1.0, 2.0, 3.0}
iex> point_coordinates(transform(point(1, 2, 3), translator(-1, -2, -3))) {0.0, 0.0, 0.0}
iex> p = point(4, 5, 6) iex> point_coordinates(transform(p, translator(1, 2, 3))) {5.0, 7.0, 9.0}
iex> point_coordinates(transform(origin(), translator(vector(1, 2, 3)))) {1.0, 2.0, 3.0}
iex> v = vector(-3, 4, 5) iex> point_coordinates(transform(origin(), translator(v))) {-3.0, 4.0, 5.0}
Computes the inverse dual operation.
undual/1 reverses the blade complement operation performed by
dual/1.
For non-degenerate Euclidean algebras this corresponds to applying the dual operation twice with the appropriate pseudoscalar factor. In degenerate algebras the result depends on the implemented dual convention.
Examples
iex> undual(dual(new(e1: 2)))
new(e1: 2)
Creates a Euclidean direction vector.
Examples
iex> vector(1, 2, 3)
new(e1: 1, e2: 2, e3: 3)
Computes the outer product (wedge product) of two multivectors.
The wedge product combines blades by joining their basis vectors. It is antisymmetric:
a ∧ b = -(b ∧ a)and vanishes when the operands share a basis vector.
Examples
iex> wedge(
...> new(e1: 1),
...> new(e2: 1)
...> )
new(e12: 1)
iex> wedge(
...> new(e2: 1),
...> new(e1: 1)
...> )
new(e12: -1)
iex> wedge(
...> new(e1: 1),
...> new(e1: 1)
...> )
new()
Computes the outer product of a list of multivectors.
The vectors are combined from left to right using the wedge product.
The result is a blade representing the subspace spanned by all input multivectors.
Returns the zero multivector.
Examples
iex> zero() new()
Checks whether all coefficients of a multivector are zero.
Examples
iex> zero?(new())
true
iex> zero?(new(e1: 1))
false