a collection of links and notes of varying quality.
see also the relatively straightforward software implementation sph-ga.
additional links
youtube
among the inner, geometric, and exterior products, the exterior product is the simplest to calculate.
exterior_product = (a, b) -> # multivector multivector -> mulivector result_components = {} for_each_component a, (coeff_a, blade_a) -> for_each_component b, (coeff_b, blade_b) -> continue if has_overlap blade_a.bases, blade_b.bases combined_bases = logical_or blade_a.bases, blade_b.bases continue unless combined_bases sign = if is_scalar(blade_b) then 1 else compute_sign(blade_a.bases, blade_b.bases) combined_coeff = sign * coeff_a * coeff_b combined_grade = blade_a.grade + blade_b.grade add_to_result result_components, combined_bases, combined_coeff, combined_grade assemble_multivector result_components
the geometric product is sometimes defined as a combination of the inner and exterior products. however, the fact that this is only valid under certain conditions can be misleading. there are cases where both the inner and extrerior product create results. while scalar multiplication rules can be adapted to be non-overlapping, merging more complex results is a challenge.
the geometric product is actually easier to calculate than the inner product.
it merges indices with the correct sign and metric factor. it yields the final basis monomial(s) with associated coefficients.
outdated
geometric_product = (a, b) -> result_components = {} for blade_a, coeff_a of a for blade_b, coeff_b of b combined = blade_a.bases.concat(blade_b.bases) combined, sign = canonical_sort_and_sign(combined) coeff = coeff_a * coeff_b * sign factor = 1 changed = true while changed changed = false i = 0 while i < combined.length j = i + 1 while j < combined.length v1 = combined[i] v2 = combined[j] metric_component = metric[v1][v2] if metric_component != 0 factor *= metric_component combined = remove_pair_from_list(combined, i, j) changed = true break j++ if changed then break i++ coeff *= factor continue if coeff == 0 add_to_result result_components, combined, coeff, grade(combined) assemble_multivector result_components
one obtains:
the easiest way to implement the inner product is to use the geometric product and extract only the b_grade minus a_grade blades from the result. its complexity arises mostly with cga; the purely euclidean, orthogonal, case is trivially solved in comparison.
here is a general outline for computing the left contraction clifford (geometric) inner product that explicitly depends on the metric and also handles null vectors like for the conformal model.
geometric_product = (a, b) -> # multivector multivector -> multivector result_terms = {} for_each_component a, (coeff_a, term_a) -> for_each_component b, (coeff_b, term_b) -> continue if term_b.grade < term_a.grade factor = metric_combination(term_a.id, term_b.id) combined_indices = sort concatenate(bit_indices(term_a.id), bit_indices(term_b.id)) grade_final = combined_indices.length coeff_final = coeff_a * coeff_b * factor continue if coeff_final == 0 add_to_result result_terms, combined_indices, coeff_final, grade_final assemble_multivector result_terms grade_reduction = (product_terms, desired_grade) -> # multivector int -> multivector result_terms = {} for_each_component product_terms, (coeff, term) -> continue unless term.grade == desired_grade add_to_result result_terms, term.id, coeff, term.grade assemble_multivector result_terms
then geometric and inner product of the pseudoscalar with itself can uncover flaws in null vector handling
e1_2_3_4_5 * e1_2_3_4_5
the conformal metric is a split-signature metric with two off-diagonal negative terms.
[1, 1, 1, 0, 0]
it aligns with the use of the no and ni null vector bases.
no * no = 0 ni * ni = 0 no * ni = -1 e_i * e_i = 1 e_i * e_j (where i != j) = 0
A -> R A R⁻¹
v -> -RvR⁻¹
[A, B] = AB - BA
{A, B} = AB + BA
in conformal geometric algebra (cga), a point in euclidean space is represented as a null vector in a higher-dimensional space. specifically, for an n-dimensional euclidean space, cga embeds this space into an (n + 2)-dimensional space with a signature (n + 1, 1). the point p with coordinates (x1, x2, ..., xn) is represented as:
p = x1 * e1 + x2 * e2 + ... + xn * en + e0 + 0.5 * (x1 ** 2 + x2 ** 2 + ... + xn ** 2) * e∞
where 'e1, e2, ..., en' are the basis vectors corresponding to the original euclidean space. e0 and e∞ are additional basis vectors with specific properties to facilitate the embedding, introduced to handle infinity and origin, and operations like translation, rotation, dilation, and reflection. e0 is often associated with the origin in the extended space. e∞ represents the "point at infinity," enabling the conformal model to handle infinite points, essential for representing directions and ideal points.
the null vector condition is given by:
dot_product(p, p) = 0
this condition ensures that the representation is a null vector in the conformal space, preserving the geometric properties of the original euclidean point.
rotor = e ** (-axis_orthogonal_plane * angle / 2)
where axis_orthogonal_plane is a unit bivector.
without exponentiation, the rotor can be constructed using the trigonometric functions that define the exponential form.
rotor = cos(angle / 2) + bivector * sin(angle / 2)
rotor = 1 + 1 / 2 * translation_vector * e∞
rotor = e ** (-axis * angle / 2) * (1 + 1 / 2 * translation_vector * e∞)
described in computing perspective projections in 3-dimensions using rotors in the homogeneous and conformal models of clifford algebra.
step 1: reflection
e ** ((angle / 2) * n * e4) = cos(angle / 2) + sin(angle / 2) * n * e4
step 2: inversion
e ** ((1 / (2 * d)) * n * e0) = exterior_product(1 + (1 / (2 * d) * n, e0))
result = rotor * point * reverse(rotor)