From 676bc9064093edaa07d1fd78a9e733191a373538 Mon Sep 17 00:00:00 2001 From: "Documenter.jl" Date: Fri, 17 May 2024 05:14:13 +0000 Subject: [PATCH] build based on d4aa7d4 --- dev/api/clifford.html | 17 +++++++++-------- dev/api/indexing.html | 12 ++++++------ dev/api/internal.html | 18 +++++++++--------- dev/api/math.html | 12 ++++++------ dev/api/metrics.html | 20 ++++++++++---------- dev/home.html | 2 +- dev/indexing.html | 2 +- dev/metrics.html | 2 +- dev/numeric.html | 2 +- dev/operations.html | 2 +- dev/search.html | 2 +- dev/search_index.js | 2 +- 12 files changed, 47 insertions(+), 46 deletions(-) diff --git a/dev/api/clifford.html b/dev/api/clifford.html index 8df4e74..b386c69 100644 --- a/dev/api/clifford.html +++ b/dev/api/clifford.html @@ -1,18 +1,19 @@ -CliffordNumbers · CliffordNumbers.jl

Clifford numbers

Supertype and associated functions

CliffordNumbers.AbstractCliffordNumberType
AbstractCliffordNumber{Q,T} <: Number

An element of a Clifford algebra, often referred to as a multivector, with quadratic form Q and element type T.

Interface

Required implementation

All subtypes C of AbstractCliffordNumber{Q} must implement the following functions:

  • Base.length(x::C) should return the number of nonzero basis elements represented by x.
  • CliffordNumbers.similar_type(::Type{C}, ::Type{T}, ::Type{Q}) where {C,T,Q} should construct a

new type similar to C which subtypes AbstractCliffordNumber{Q,T} that may serve as a constructor.

  • Base.getindex(x::C, b::BitIndex{Q}) should allow one to recover the coefficients associated

with each basis blade represented by C.

Required implementation for static types

  • Base.length(::Type{C}) should be defined, with Base.length(x::C) = length(typeof(x)).
  • Base.Tuple(x::C) should return the tuple used to construct x. The fallback is

getfield(x, :data)::Tuple, so any type declared with a NTuple field named data should have this defined automatically.

source
CliffordNumbers.scalar_typeFunction
scalar_type(::Type{<:AbstractCliffordNumber{Q,T}}) = T
+CliffordNumbers · CliffordNumbers.jl

Clifford numbers

Supertype and associated functions

CliffordNumbers.AbstractCliffordNumberType
AbstractCliffordNumber{Q,T} <: Number

An element of a Clifford algebra, often referred to as a multivector, with quadratic form Q and element type T. These are statically size and therefore should be able to be stored inline in arrays or other data structures,

Interface

Required implementation

All subtypes C of AbstractCliffordNumber{Q} must implement the following functions:

  • CliffordNumbers.similar_type(::Type{C}, ::Type{T}, ::Type{Q}) where {C,T,Q} should construct a

new type similar to C which subtypes AbstractCliffordNumber{Q,T} that may serve as a constructor.

  • Base.getindex(x::C, b::BitIndex{Q}) should allow one to recover the coefficients associated

with each basis blade represented by C.

  • nblades(::Type{C}) should be defined to return the number of basis blades represented by the

type. By default, nblades(x::AbstractCliffordNumber) = nblades(typeof(x)).

  • Base.Tuple(x::C) should return the tuple used to construct x. The fallback is

getfield(x, :data)::Tuple, so any type declared with a NTuple field named data should have this defined automatically.

source
CliffordNumbers.nbladesFunction
nblades(::Type{<:Number}) -> Int
+nblades(x::Number)

Returns the number of blades represented by a Number subtype or instance. For subtypes of Number that are not AbstractCliffordNumber, this is always 1.

This function is separate from Base.length since AbstractCliffordNumber is a scalar type for which collect() returns a zero-dimensional array. For consistency, length(x) should always equal length(collect(x)).

source
CliffordNumbers.scalar_typeFunction
scalar_type(::Type{<:AbstractCliffordNumber{Q,T}}) = T
 scalar_type(T::Type{<:Union{Real,Complex}}) = T
-scalar_type(x) = scalar_type(typeof(x))

Returns the numeric type associated with an AbstractCliffordNumber instance. For subtypes of Real and Complex, or their instances, this simply returns the input type or instance type.

Why not define eltype?

AbstractCliffordNumber instances behave like numbers, not arrays. If collect() is called on a Clifford number of type T, it should not construct a vector of coefficients; instead it should return an Array{T,0}. Similarly, a broadcasted multiplication should return the same result as normal multiplication, as is the case with complex numbers.

For subtypes T of Number, eltype(T) === T, and this is true for AbstractCliffordNumber.

source
CliffordNumbers.similar_typeFunction
CliffordNumbers.similar_type(
+scalar_type(x) = scalar_type(typeof(x))

Returns the numeric type associated with an AbstractCliffordNumber instance. For subtypes of Real and Complex, or their instances, this simply returns the input type or instance type.

Why not define eltype?

AbstractCliffordNumber instances behave like numbers, not arrays. If collect() is called on a Clifford number of type T, it should not construct a vector of coefficients; instead it should return an Array{T,0}. Similarly, a broadcasted multiplication should return the same result as normal multiplication, as is the case with complex numbers.

For subtypes T of Number, eltype(T) === T, and this is true for AbstractCliffordNumber.

source
CliffordNumbers.similar_typeFunction
CliffordNumbers.similar_type(
     C::Type{<:AbstractCliffordNumber},
     [N::Type{<:BaseNumber} = scalar_type(C)],
     [Q::Val = Val(signature(C))]
-) -> Type{<:AbstractCliffordNumber{Q,N}}

Constructs a type similar to T but with numeric type N and quadratic form Q. The quadratic form must be wrapped in a Val to preserve type stability.

This function must be defined with all its arguments for each concrete type subtyping AbstractCliffordNumber.

source

Concrete types

CliffordNumbers.CliffordNumberType
CliffordNumber{Q,T,L} <: AbstractCliffordNumber{Q,T}

A dense multivector (or Clifford number), with quadratic form Q, element type T, and length L (which depends entirely on Q).

The coefficients are ordered by taking advantage of the natural binary structure of the basis. The grade of an element is given by the Hamming weight of its index. For the algebra of physical space, the order is: 1, e₁, e₂, e₁₂, e₃, e₁₃, e₂₃, e₁₂₃ = i. This order allows for more aggressive SIMD optimization when calculating the geometric product.

source
CliffordNumbers.Z2CliffordNumberType
CliffordNumbers.Z2CliffordNumber{P,Q,T,L} <: AbstractCliffordNumber{Q,T}

A Clifford number whose only nonzero grades are even or odd. Clifford numbers of this form naturally arise as versors, the geometric product of 1-vectors.

The type parameter P is constrained to be a Bool: true for odd grade Clifford numbers, and false for even grade Clifford numbers, corresponding to the Boolean result of each grade modulo 2.

Type aliases

This type is not exported, and usually you will want to refer to the following aliases:

const EvenCliffordNumber{Q,T,L} = Z2CliffordNumber{false,Q,T,L}
-const OddCliffordNumber{Q,T,L} = Z2CliffordNumber{true,Q,T,L}
source
CliffordNumbers.EvenCliffordNumberType
EvenCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{false,Q,T,L})

A Clifford number whose only nonzero grades are even. These are the natural choice of representation for rotors and motors (Euclidean isometries preserving orientation, or "proper" isometries), as well as their composition with dilations.

source
CliffordNumbers.OddCliffordNumberType
OddCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{true,Q,T,L})

A Clifford number whose only nonzero grades are odd. These are the natural choice of representation for reflections, as well as their compositions with rotors and motors (Euclidean isometries preserving orientation, or "proper" isometries), as well as their composition with dilations.

source
CliffordNumbers.KVectorType
KVector{K,Q,T,L} <: AbstractCliffordNumber{Q,T}

A multivector consisting only linear combinations of basis blades of grade K - in other words, a k-vector.

k-vectors have binomial(dimension(Q), K) components.

source
CliffordNumbers.gradeMethod
grade(::Type{<:KVector{K}}) = K
-grade(x::KVector{K}) = k

Returns the grade represented by a KVector{K}, which is K.

source

Promotion and conversion

CliffordNumbers.scalar_convertFunction
scalar_convert(T::Type{<:Union{Real,Complex}}, x::AbstractCliffordNumber) -> T
+) -> Type{<:AbstractCliffordNumber{Q,N}}

Constructs a type similar to T but with numeric type N and quadratic form Q. The quadratic form must be wrapped in a Val to preserve type stability.

This function must be defined with all its arguments for each concrete type subtyping AbstractCliffordNumber.

source

Concrete types

CliffordNumbers.CliffordNumberType
CliffordNumber{Q,T,L} <: AbstractCliffordNumber{Q,T}

A dense multivector (or Clifford number), with quadratic form Q, element type T, and length L (which depends entirely on Q).

The coefficients are ordered by taking advantage of the natural binary structure of the basis. The grade of an element is given by the Hamming weight of its index. For the algebra of physical space, the order is: 1, e₁, e₂, e₁₂, e₃, e₁₃, e₂₃, e₁₂₃ = i. This order allows for more aggressive SIMD optimization when calculating the geometric product.

source
CliffordNumbers.Z2CliffordNumberType
CliffordNumbers.Z2CliffordNumber{P,Q,T,L} <: AbstractCliffordNumber{Q,T}

A Clifford number whose only nonzero grades are even or odd. Clifford numbers of this form naturally arise as versors, the geometric product of 1-vectors.

The type parameter P is constrained to be a Bool: true for odd grade Clifford numbers, and false for even grade Clifford numbers, corresponding to the Boolean result of each grade modulo 2.

Type aliases

This type is not exported, and usually you will want to refer to the following aliases:

const EvenCliffordNumber{Q,T,L} = Z2CliffordNumber{false,Q,T,L}
+const OddCliffordNumber{Q,T,L} = Z2CliffordNumber{true,Q,T,L}
source
CliffordNumbers.EvenCliffordNumberType
EvenCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{false,Q,T,L})

A Clifford number whose only nonzero grades are even. These are the natural choice of representation for rotors and motors (Euclidean isometries preserving orientation, or "proper" isometries), as well as their composition with dilations.

source
CliffordNumbers.OddCliffordNumberType
OddCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{true,Q,T,L})

A Clifford number whose only nonzero grades are odd. These are the natural choice of representation for reflections, as well as their compositions with rotors and motors (Euclidean isometries preserving orientation, or "proper" isometries), as well as their composition with dilations.

source
CliffordNumbers.KVectorType
KVector{K,Q,T,L} <: AbstractCliffordNumber{Q,T}

A multivector consisting only linear combinations of basis blades of grade K - in other words, a k-vector.

k-vectors have binomial(dimension(Q), K) components.

source
CliffordNumbers.gradeMethod
grade(::Type{<:KVector{K}}) = K
+grade(x::KVector{K}) = k

Returns the grade represented by a KVector{K}, which is K.

source

Promotion and conversion

CliffordNumbers.scalar_convertFunction
scalar_convert(T::Type{<:Union{Real,Complex}}, x::AbstractCliffordNumber) -> T
 scalar_convert(T::Type{<:Union{Real,Complex}}, x::Union{Real,Complex}) -> T

If x is an AbstractCliffordNumber, converts the scalars of x to type T.

If x is a Real or Complex, converts x to T.

Examples

julia> scalar_convert(Float32, KVector{1,APS}(1, 2, 3))
 3-element KVector{1, VGA(3), Float32}:
 1.0σ₁ + 2.0σ₂ + 3.0σ
 
 julia> scalar_convert(Float32, 2)
-2.0f0
source
CliffordNumbers.scalar_promoteFunction
scalar_promote(x::AbstractCliffordNumber, y::AbstractCliffordNumber)

Promotes the scalar types of x and y to a common type. This does not increase the number of represented grades of either x or y.

source
Base.widenMethod
widen(C::Type{<:AbstractCliffordNumber})
-widen(x::AbstractCliffordNumber)

Construct a new type whose scalar type is widened. This behavior matches that of widen(C::Type{Complex{T}}), which results in widening of its scalar type T.

For obtaining a representation of a Clifford number with an increased number of nonzero grades, use widen_grade(T).

source
CliffordNumbers.widen_gradeFunction
widen_grade(C::Type{<:AbstractCliffordNumber})
-widen_grade(x::AbstractCliffordNumber)

For type arguments, construct the next largest type that can hold all of the grades of C. KVector{K,Q,T} widens to EvenCliffordNumber{Q,T} or OddCliffordNumber{Q,T}, and EvenCliffordNumber{Q,T} and OddCliffordNumber{Q,T} widen to CliffordNumber{Q,T}, which is the widest type.

For AbstractCliffordNumber arguments, the argument is converted to the result of widen_grade(typeof(x)).

For widening the scalar type of an AbstractCliffordNumber, use Base.widen(T).

source

Real and complex algebras

Base.realMethod
real(x::AbstractCliffordNumber{Q,T})

Gets the real portion of each coefficient of x. For T<:Real this operation does nothing; for T<:Complex{S} this an AbstractCliffordNumber{Q,S}.

Note that this does not return the scalar (grade 0) coefficient of x. Use real(scalar(x)) to obtain this result.

source
Base.complexMethod
complex(x::AbstractCliffordNumber, [y::AbstractCliffordNumber = zero(typeof(x))])

For a single argument x, converts the type of each coefficient to a suitable complex type.

For two arguments x and y, which are both real Clifford numbers, performs the sum x + y*im, constructing a complex Clifford number.

Note that this operation does not isolate a scalar (grade 0) coefficient of x or y. Use complex(scalar(x), [scalar(y)]) to obtain this result.

source

Scalar and pseudoscalar components

CliffordNumbers.isscalarFunction
isscalar(x::AbstractCliffordNumber)

Determines whether the Clifford number x is a scalar, meaning that all of its blades of nonzero grade are zero.

source
CliffordNumbers.ispseudoscalarFunction
ispseudoscalar(m::AbstractCliffordNumber)

Determines whether the Clifford number x is a pseudoscalar, meaning that all of its blades with grades below the dimension of the space are zero.

source
CliffordNumbers.scalarFunction
scalar(x::AbstractCliffordNumber{Q,T}) -> T

Returns the scalar portion of x as its scalar type. This is equivalent to x[scalar_index(x)].

To retain Clifford number semantics, use the KVector{0} constructor.

source
+2.0f0
source
CliffordNumbers.scalar_promoteFunction
scalar_promote(x::AbstractCliffordNumber, y::AbstractCliffordNumber)

Promotes the scalar types of x and y to a common type. This does not increase the number of represented grades of either x or y.

source
Base.widenMethod
widen(C::Type{<:AbstractCliffordNumber})
+widen(x::AbstractCliffordNumber)

Construct a new type whose scalar type is widened. This behavior matches that of widen(C::Type{Complex{T}}), which results in widening of its scalar type T.

For obtaining a representation of a Clifford number with an increased number of nonzero grades, use widen_grade(T).

source
CliffordNumbers.widen_gradeFunction
widen_grade(C::Type{<:AbstractCliffordNumber})
+widen_grade(x::AbstractCliffordNumber)

For type arguments, construct the next largest type that can hold all of the grades of C. KVector{K,Q,T} widens to EvenCliffordNumber{Q,T} or OddCliffordNumber{Q,T}, and EvenCliffordNumber{Q,T} and OddCliffordNumber{Q,T} widen to CliffordNumber{Q,T}, which is the widest type.

For AbstractCliffordNumber arguments, the argument is converted to the result of widen_grade(typeof(x)).

For widening the scalar type of an AbstractCliffordNumber, use Base.widen(T).

source

Real and complex algebras

Base.realMethod
real(x::AbstractCliffordNumber{Q,T})

Gets the real portion of each coefficient of x. For T<:Real this operation does nothing; for T<:Complex{S} this an AbstractCliffordNumber{Q,S}.

Note that this does not return the scalar (grade 0) coefficient of x. Use real(scalar(x)) to obtain this result.

source
Base.complexMethod
complex(x::AbstractCliffordNumber, [y::AbstractCliffordNumber = zero(typeof(x))])

For a single argument x, converts the type of each coefficient to a suitable complex type.

For two arguments x and y, which are both real Clifford numbers, performs the sum x + y*im, constructing a complex Clifford number.

Note that this operation does not isolate a scalar (grade 0) coefficient of x or y. Use complex(scalar(x), [scalar(y)]) to obtain this result.

source

Scalar and pseudoscalar components

CliffordNumbers.isscalarFunction
isscalar(x::AbstractCliffordNumber)

Determines whether the Clifford number x is a scalar, meaning that all of its blades of nonzero grade are zero.

source
CliffordNumbers.ispseudoscalarFunction
ispseudoscalar(m::AbstractCliffordNumber)

Determines whether the Clifford number x is a pseudoscalar, meaning that all of its blades with grades below the dimension of the space are zero.

source
CliffordNumbers.scalarFunction
scalar(x::AbstractCliffordNumber{Q,T}) -> T

Returns the scalar portion of x as its scalar type. This is equivalent to x[scalar_index(x)].

To retain Clifford number semantics, use the KVector{0} constructor.

source
diff --git a/dev/api/indexing.html b/dev/api/indexing.html index c831d04..4f24eab 100644 --- a/dev/api/indexing.html +++ b/dev/api/indexing.html @@ -4,9 +4,9 @@ 0:3 julia> CliffordNumbers.nonzero_grades(KVector{2,APS}) -2:2source
CliffordNumbers.has_grades_ofFunction
has_grades_of(S::Type{<:AbstractCliffordNumber}, T::Type{<:AbstractCliffordNumber}) -> Bool
-has_grades_of(x::AbstractCliffordNumber, y::AbstractCliffordNumber) -> Bool

Returns true if the grades represented in S are also represented in T; false otherwise.

source

BitIndex

CliffordNumbers.BitIndexType
BitIndex{Q}

A representation of an index corresponding to a basis blade of the geometric algebra with quadratic form Q.

source
CliffordNumbers.is_same_bladeFunction
CliffordNumbers.is_same_blade(a::BitIndex{Q}, b::BitIndex{Q})

Checks if a and b perform identical indexing up to sign.

source

Special indices

CliffordNumbers.scalar_indexFunction
scalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}

Constructs the BitIndex used to obtain the scalar (grade zero) portion of x.

source
CliffordNumbers.pseudoscalar_indexFunction
pseudoscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}

Constructs the BitIndex used to obtain the pseudoscalar (highest grade) portion of x.

source

Tools for implementing mathematical operations

Base.reverseMethod
adjoint(i::BitIndex) = reverse(i::BitIndex) = i' -> BitIndex
-adjoint(x::AbstractCliffordNumber) = reverse(x::AbstractCliffordNumber) = x' -> typeof(x)

Performs the reverse operation on the basis blade indexed by b or the Clifford number x. The sign of the reverse depends on the grade of the basis blade g, and is positive for g % 4 in 0:1 and negative for g % 4 in 2:3.

source
CliffordNumbers.grade_involutionMethod
grade_involution(i::BitIndex) -> BitIndex
-grade_involution(x::AbstractCliffordNumber) -> typeof(x)

Calculates the grade involution of the basis blade indexed by b or the Clifford number x. This effectively reflects all of the basis vectors of the space along their own mirror operation, which makes elements of odd grade flip sign.

source
Base.conjMethod
conj(i::BitIndex) -> BitIndex
-conj(x::AbstractCliffordNumber) -> typeof(x)

Calculates the Clifford conjugate of the basis blade indexed by b or the Clifford number x. This is equal to grade_involution(reverse(x)).

source
CliffordNumbers.gradeMethod
grade(i::BitIndex) -> Int

Returns the grade of the basis blade represented by i, which ranges from 0 to the dimension of the space represented by i (equal to dimension(signature(i))).

source
CliffordNumbers.sign_of_squareFunction
CliffordNumbers.sign_of_square(b::BitIndex) -> Int8

Returns the sign associated with squaring the basis blade indexed by b using an Int8 as proxy: positive signs return Int8(1), negative signs return Int8(-1), and zeros from degenerate components return Int8(0).

source
CliffordNumbers.signbit_of_squareFunction
CliffordNumbers.signbit_of_square(b::BitIndex) -> Bool

Returns the signbit associated with squaring the basis blade indexed by b.

source
CliffordNumbers.nondegenerate_squareFunction
CliffordNumbers.nondegenerate_square(b::BitIndex) -> Bool

Returns false if squaring the basis blade b is zero due to a degenerate component, true otherwise. For a nondegenerate metric, this is always true.

source
CliffordNumbers.sign_of_multFunction
CliffordNumbers.sign_of_mult(a::T, b::T) where T<:BitIndex -> Int8

Returns an Int8 that carries the sign associated with the multiplication of two basis blades of Clifford/geometric algebras of the same quadratic form.

source
CliffordNumbers.signbit_of_multFunction
CliffordNumbers.signbit_of_mult(a::Integer, [b::Integer]) -> Bool
-CliffordNumbers.signbit_of_mult(a::BitIndex, [b::BitIndex]) -> Bool

Calculates the sign bit associated with multiplying basis elements indexed with bit indices supplied as either integers or BitIndex instances. The sign bit flips when the order of a and b are reversed, unless a === b.

As with Base.signbit(), true represents a negative sign and false a positive sign. However, in degenerate metrics (such as those of projective geometric algebras) the sign bit may be irrelevant as the multiplication of those basis blades would result in zero.

source
CliffordNumbers.nondegenerate_multFunction
CliffordNumbers.nondegenerate_mult(a::T, b::T) where T<:BitIndex -> Bool

Returns false if the product of a and b is zero due to the squaring of a degenerate component, true otherwise. This function always returns true if R === 0.

source
Base.:*Method
*(a::BitIndex{Q}, b::BitIndex{Q}) -> BitIndex{Q}

Returns the BitIndex corresponding to the basis blade resulting from the geometric product of the basis blades indexed by a and b.

source
CliffordNumbers.has_wedgeFunction
CliffordNumbers.has_wedge(a::BitIndex{Q}, b::BitIndex{Q}, [c::BitIndex{Q}...]) -> Bool

Returns true if the basis blades indexed by a, b, or any other blades c... have a nonzero wedge product; false otherwise. This is determined by comparing all bits of the arguments (except the sign bit) to identify any matching basis blades using bitwise AND.

source
CliffordNumbers.AbstractBitIndicesType
AbstractBitIndices{Q,C<:AbstractCliffordNumber{Q}} <: AbstractVector{BitIndex{Q}}

Supertype for vectors containing all valid BitIndex{Q} objects for the basis elements represented by C.

source
CliffordNumbers.BitIndicesType
BitIndices{Q,C<:AbstractCliffordNumber{Q,<:Any}} <: AbstractVector{BitIndex{Q}}

Represents a range of valid BitIndex objects for the nonzero components of a given multivector of algebra Q.

For a generic AbstractCliffordNumber{Q}, this returns BitIndices{Q,CliffordNumber{Q}}, which contains all possible indices for a multivector associated with the algebra parameter Q. For sparser representations, such as KVector{K,Q}, the object only contains the indices of the nonzero elements of the multivector.

Construction

BitIndices can be constructed by calling the type constructor with the Clifford number or its type. This will automatically strip some type parameters so that identical BitIndices objects are constructed regardless of the scalar type.

For this reason, you should not use BitIndices{Q,C}(); instead use BitIndices(C).

Indexing

BitIndices always uses one-based indexing like most Julia arrays. Although it is more natural in the dense case to use zero-based indexing, as the basis blades are naturally encoded in the indices for the dense representation of CliffordNumber, one-based indexing is used by the tuples which contain the data associated with this package's implementations of Clifford numbers.

Broadcasting

Because BitIndices(x) only lazily references the indices of x, we define a new type, TransformedBitIndices, which allows for a function f to be lazily associated with the BitIndices object, and this type is constructed when a f.(BitIndices(x)) is called.

Interfaces for new subtypes of AbstractCliffordNumber

When defining the behavior of BitIndices for new subtypes T of AbstractCliffordNumber, Base.getindex(::BitIndices{Q,T}, i::Integer) should be defined so that all indices of T that are not constrained to be zero are returned.

You should also define CliffordNumbers.bitindices_type(::Type{T}) so that type parameters that do not affect the construction of the BitIndices object are stripped.

source
CliffordNumbers.TransformedBitIndicesType
TransformedBitIndices{Q,C,F} <: AbstractBitIndices{Q,C}

Lazy representation of BitIndices{Q,C} with some function of type f applied to each element. These objects can be used to perform common operations which act on basis blades or grades, such as the reverse or grade involution.

source
+2:2source
CliffordNumbers.has_grades_ofFunction
has_grades_of(S::Type{<:AbstractCliffordNumber}, T::Type{<:AbstractCliffordNumber}) -> Bool
+has_grades_of(x::AbstractCliffordNumber, y::AbstractCliffordNumber) -> Bool

Returns true if the grades represented in S are also represented in T; false otherwise.

source

BitIndex

CliffordNumbers.BitIndexType
BitIndex{Q}

A representation of an index corresponding to a basis blade of the geometric algebra with quadratic form Q.

source
CliffordNumbers.is_same_bladeFunction
CliffordNumbers.is_same_blade(a::BitIndex{Q}, b::BitIndex{Q})

Checks if a and b perform identical indexing up to sign.

source

Special indices

CliffordNumbers.scalar_indexFunction
scalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}

Constructs the BitIndex used to obtain the scalar (grade zero) portion of x.

source
CliffordNumbers.pseudoscalar_indexFunction
pseudoscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}

Constructs the BitIndex used to obtain the pseudoscalar (highest grade) portion of x.

source

Tools for implementing mathematical operations

Base.reverseMethod
adjoint(i::BitIndex) = reverse(i::BitIndex) = i' -> BitIndex
+adjoint(x::AbstractCliffordNumber) = reverse(x::AbstractCliffordNumber) = x' -> typeof(x)

Performs the reverse operation on the basis blade indexed by b or the Clifford number x. The sign of the reverse depends on the grade of the basis blade g, and is positive for g % 4 in 0:1 and negative for g % 4 in 2:3.

source
CliffordNumbers.grade_involutionMethod
grade_involution(i::BitIndex) -> BitIndex
+grade_involution(x::AbstractCliffordNumber) -> typeof(x)

Calculates the grade involution of the basis blade indexed by b or the Clifford number x. This effectively reflects all of the basis vectors of the space along their own mirror operation, which makes elements of odd grade flip sign.

source
Base.conjMethod
conj(i::BitIndex) -> BitIndex
+conj(x::AbstractCliffordNumber) -> typeof(x)

Calculates the Clifford conjugate of the basis blade indexed by b or the Clifford number x. This is equal to grade_involution(reverse(x)).

source
CliffordNumbers.gradeMethod
grade(i::BitIndex) -> Int

Returns the grade of the basis blade represented by i, which ranges from 0 to the dimension of the space represented by i (equal to dimension(signature(i))).

source
CliffordNumbers.sign_of_squareFunction
CliffordNumbers.sign_of_square(b::BitIndex) -> Int8

Returns the sign associated with squaring the basis blade indexed by b using an Int8 as proxy: positive signs return Int8(1), negative signs return Int8(-1), and zeros from degenerate components return Int8(0).

source
CliffordNumbers.signbit_of_squareFunction
CliffordNumbers.signbit_of_square(b::BitIndex) -> Bool

Returns the signbit associated with squaring the basis blade indexed by b.

source
CliffordNumbers.nondegenerate_squareFunction
CliffordNumbers.nondegenerate_square(b::BitIndex) -> Bool

Returns false if squaring the basis blade b is zero due to a degenerate component, true otherwise. For a nondegenerate metric, this is always true.

source
CliffordNumbers.sign_of_multFunction
CliffordNumbers.sign_of_mult(a::T, b::T) where T<:BitIndex -> Int8

Returns an Int8 that carries the sign associated with the multiplication of two basis blades of Clifford/geometric algebras of the same quadratic form.

source
CliffordNumbers.signbit_of_multFunction
CliffordNumbers.signbit_of_mult(a::Integer, [b::Integer]) -> Bool
+CliffordNumbers.signbit_of_mult(a::BitIndex, [b::BitIndex]) -> Bool

Calculates the sign bit associated with multiplying basis elements indexed with bit indices supplied as either integers or BitIndex instances. The sign bit flips when the order of a and b are reversed, unless a === b.

As with Base.signbit(), true represents a negative sign and false a positive sign. However, in degenerate metrics (such as those of projective geometric algebras) the sign bit may be irrelevant as the multiplication of those basis blades would result in zero.

source
CliffordNumbers.nondegenerate_multFunction
CliffordNumbers.nondegenerate_mult(a::T, b::T) where T<:BitIndex -> Bool

Returns false if the product of a and b is zero due to the squaring of a degenerate component, true otherwise. This function always returns true if R === 0.

source
Base.:*Method
*(a::BitIndex{Q}, b::BitIndex{Q}) -> BitIndex{Q}

Returns the BitIndex corresponding to the basis blade resulting from the geometric product of the basis blades indexed by a and b.

source
CliffordNumbers.has_wedgeFunction
CliffordNumbers.has_wedge(a::BitIndex{Q}, b::BitIndex{Q}, [c::BitIndex{Q}...]) -> Bool

Returns true if the basis blades indexed by a, b, or any other blades c... have a nonzero wedge product; false otherwise. This is determined by comparing all bits of the arguments (except the sign bit) to identify any matching basis blades using bitwise AND.

source
CliffordNumbers.AbstractBitIndicesType
AbstractBitIndices{Q,C<:AbstractCliffordNumber{Q}} <: AbstractVector{BitIndex{Q}}

Supertype for vectors containing all valid BitIndex{Q} objects for the basis elements represented by C.

source
CliffordNumbers.BitIndicesType
BitIndices{Q,C<:AbstractCliffordNumber{Q,<:Any}} <: AbstractVector{BitIndex{Q}}

Represents a range of valid BitIndex objects for the nonzero components of a given multivector of algebra Q.

For a generic AbstractCliffordNumber{Q}, this returns BitIndices{Q,CliffordNumber{Q}}, which contains all possible indices for a multivector associated with the algebra parameter Q. For sparser representations, such as KVector{K,Q}, the object only contains the indices of the nonzero elements of the multivector.

Construction

BitIndices can be constructed by calling the type constructor with the Clifford number or its type. This will automatically strip some type parameters so that identical BitIndices objects are constructed regardless of the scalar type.

For this reason, you should not use BitIndices{Q,C}(); instead use BitIndices(C).

Indexing

BitIndices always uses one-based indexing like most Julia arrays. Although it is more natural in the dense case to use zero-based indexing, as the basis blades are naturally encoded in the indices for the dense representation of CliffordNumber, one-based indexing is used by the tuples which contain the data associated with this package's implementations of Clifford numbers.

Broadcasting

Because BitIndices(x) only lazily references the indices of x, we define a new type, TransformedBitIndices, which allows for a function f to be lazily associated with the BitIndices object, and this type is constructed when a f.(BitIndices(x)) is called.

Interfaces for new subtypes of AbstractCliffordNumber

When defining the behavior of BitIndices for new subtypes T of AbstractCliffordNumber, Base.getindex(::BitIndices{Q,T}, i::Integer) should be defined so that all indices of T that are not constrained to be zero are returned.

You should also define CliffordNumbers.bitindices_type(::Type{T}) so that type parameters that do not affect the construction of the BitIndices object are stripped.

source
CliffordNumbers.TransformedBitIndicesType
TransformedBitIndices{Q,C,F} <: AbstractBitIndices{Q,C}

Lazy representation of BitIndices{Q,C} with some function of type f applied to each element. These objects can be used to perform common operations which act on basis blades or grades, such as the reverse or grade involution.

source
diff --git a/dev/api/internal.html b/dev/api/internal.html index b435507..c11d1f0 100644 --- a/dev/api/internal.html +++ b/dev/api/internal.html @@ -1,25 +1,25 @@ -Internals · CliffordNumbers.jl

Internal methods

CliffordNumbers.HammingModule
CliffordNumbers.Hamming

A submodule containing methods for working with the sum of binary digits contained in an integer. This is essential to representing the basis blades of a geometric algebra, as the presence or absence of each possible basis vector in a blade can be represented by a binary 1 or 0. Operations that require knowledge of the grade of a basis blade will need the operations in this submodule.

source
CliffordNumbers.Hamming.isevilFunction
CliffordNumbers.Hamming.isevil(i::Integer) -> Bool

Determines whether a number is evil, meaning that its Hamming weight (sum of its binary digits) is even.

source
CliffordNumbers.Hamming.isodiousFunction
CliffordNumbers.Hamming.isodious(i::Integer) -> Bool

Determines whether a number is odious, meaning that its Hamming weight (sum of its binary digits) is odd.

source
CliffordNumbers.Hamming.evil_numberFunction
CliffordNumbers.Hamming.evil_number(n::Integer)

Returns the nth evil number, with the first evil number (n == 1) defined to be 0.

Evil numbers are numbers which have an even Hamming weight (sum of its binary digits).

source
CliffordNumbers.Hamming.odious_numberFunction
CliffordNumbers.Hamming.odious_number(n::Integer)

Returns the nth odious number, with the first odious number (n == 1) defined to be 1.

Odious numbers are numbers which have an odd Hamming weight (sum of its binary digits).

source
CliffordNumbers.Hamming.hamming_numberFunction
CliffordNumbers.Hamming.hamming_number(w::Integer, n::Integer)

Gets the nth number with Hamming weight w. The first number with this Hamming weight (n = 1) is 2^w - 1.

Example

julia> CliffordNumbers.hamming_number(3, 2)
-11
source

Indexing

CliffordNumbers.signmaskFunction
CliffordNumbers.signmask([T::Type{<:Integer} = UInt], [signbit::Bool = true]) -> T

Generates a signmask, or a string of bits where the only 1 bit is the sign bit. If signbit is set to false, this returns zero (or whatever value is represented by all bits being 0).

source
CliffordNumbers._sort_with_parity!Function
CliffordNumbers._sort_with_parity!(v::AbstractVector{<:Real}) -> Tuple{typeof(v),Bool}

Performs a parity-tracking insertion sort of v, which modifies v in place. The function returns a tuple containing v and the parity, which is true for an odd permutation and false for an even permutation. This is implemented with a modified insertion sort algorithm.

source
CliffordNumbers.bitindices_typeFunction
CliffordNumbers.bitindices_type(C::Type{<:AbstractCliffordNumber{Q,T}})

Removes extraneous type parameters from C, converting it to the least parameterized type that can be used to parameterize an AbstractBitIndices{Q,C} object. This is to avoid issues with the proliferation of type parameters that would construct identical BitIndices objects otherwise: for instance, BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Float32,4}}() and BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Int}}() have identical elements, and are equal when compared with ==, but are not the same object.

For types defined in this package, this strips the scalar type parameter T and any length parameters present.

Examples

julia> CliffordNumbers.bitindices_type(CliffordNumber{VGA(3),Float32,8})
+Internals · CliffordNumbers.jl

Internal methods

CliffordNumbers.HammingModule
CliffordNumbers.Hamming

A submodule containing methods for working with the sum of binary digits contained in an integer. This is essential to representing the basis blades of a geometric algebra, as the presence or absence of each possible basis vector in a blade can be represented by a binary 1 or 0. Operations that require knowledge of the grade of a basis blade will need the operations in this submodule.

source
CliffordNumbers.Hamming.isevilFunction
CliffordNumbers.Hamming.isevil(i::Integer) -> Bool

Determines whether a number is evil, meaning that its Hamming weight (sum of its binary digits) is even.

source
CliffordNumbers.Hamming.isodiousFunction
CliffordNumbers.Hamming.isodious(i::Integer) -> Bool

Determines whether a number is odious, meaning that its Hamming weight (sum of its binary digits) is odd.

source
CliffordNumbers.Hamming.evil_numberFunction
CliffordNumbers.Hamming.evil_number(n::Integer)

Returns the nth evil number, with the first evil number (n == 1) defined to be 0.

Evil numbers are numbers which have an even Hamming weight (sum of its binary digits).

source
CliffordNumbers.Hamming.odious_numberFunction
CliffordNumbers.Hamming.odious_number(n::Integer)

Returns the nth odious number, with the first odious number (n == 1) defined to be 1.

Odious numbers are numbers which have an odd Hamming weight (sum of its binary digits).

source
CliffordNumbers.Hamming.hamming_numberFunction
CliffordNumbers.Hamming.hamming_number(w::Integer, n::Integer)

Gets the nth number with Hamming weight w. The first number with this Hamming weight (n = 1) is 2^w - 1.

Example

julia> CliffordNumbers.hamming_number(3, 2)
+11
source

Indexing

CliffordNumbers.signmaskFunction
CliffordNumbers.signmask([T::Type{<:Integer} = UInt], [signbit::Bool = true]) -> T

Generates a signmask, or a string of bits where the only 1 bit is the sign bit. If signbit is set to false, this returns zero (or whatever value is represented by all bits being 0).

source
CliffordNumbers._sort_with_parity!Function
CliffordNumbers._sort_with_parity!(v::AbstractVector{<:Real}) -> Tuple{typeof(v),Bool}

Performs a parity-tracking insertion sort of v, which modifies v in place. The function returns a tuple containing v and the parity, which is true for an odd permutation and false for an even permutation. This is implemented with a modified insertion sort algorithm.

source
CliffordNumbers.bitindices_typeFunction
CliffordNumbers.bitindices_type(C::Type{<:AbstractCliffordNumber{Q,T}})

Removes extraneous type parameters from C, converting it to the least parameterized type that can be used to parameterize an AbstractBitIndices{Q,C} object. This is to avoid issues with the proliferation of type parameters that would construct identical BitIndices objects otherwise: for instance, BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Float32,4}}() and BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Int}}() have identical elements, and are equal when compared with ==, but are not the same object.

For types defined in this package, this strips the scalar type parameter T and any length parameters present.

Examples

julia> CliffordNumbers.bitindices_type(CliffordNumber{VGA(3),Float32,8})
 CliffordNumber{VGA(3)}
 
 julia> CliffordNumbers.bitindices_type(KVector{2,STA,Bool})
-KVector{2,STA}
source

Construction

CliffordNumbers.zero_tupleFunction
CliffordNumbers.zero_tuple(::Type{T}, ::Val{L}) -> NTuple{L,T}

Generates a Tuple of length L with all elements being zero(T).

source
CliffordNumbers.zero_tuple(::Type{C<:AbstractCliffordNumber})
-    -> NTuple{length(C),scalar_type(C)}

Generates a Tuple that can be used to construct zero(C).

source
CliffordNumbers.check_element_countFunction
CliffordNumbers.check_element_count(sz, [L], data)

Ensures that the number of elements in data is the same as the result of f(Q), where f is a function that generates the expected number of elements for the type. This function is used in the inner constructors of subtypes of AbstractCliffordNumber{Q} to ensure that the input has the correct length.

If provided, the length type parameter L can be included as an argument, and it will be checked for type (must be an Int) and value (must be equal to sz).

This function returns nothing, but throws an AssertionError for failed checks.

source

Multiplication kernels

Construction

CliffordNumbers.zero_tupleFunction
CliffordNumbers.zero_tuple(::Type{T}, ::Val{L}) -> NTuple{L,T}

Generates a Tuple of length L with all elements being zero(T).

source
CliffordNumbers.zero_tuple(::Type{C<:AbstractCliffordNumber})
+    -> NTuple{nblades(C),scalar_type(C)}

Generates a Tuple that can be used to construct zero(C).

source
CliffordNumbers.check_element_countFunction
CliffordNumbers.check_element_count(sz, [L], data)

Ensures that the number of elements in data is the same as the result of f(Q), where f is a function that generates the expected number of elements for the type. This function is used in the inner constructors of subtypes of AbstractCliffordNumber{Q} to ensure that the input has the correct length.

If provided, the length type parameter L can be included as an argument, and it will be checked for type (must be an Int) and value (must be equal to sz).

This function returns nothing, but throws an AssertionError for failed checks.

source

Multiplication kernels

CliffordNumbers.mulFunction
CliffordNumbers.mul(
     x::AbstractCliffordNumber{Q},
     y::AbstractCliffordNumber{Q},
     [F::GradeFilter = GradeFilter{:*}()]
-)

A fast geometric product implementation using generated functions for specific cases, and generic methods which either convert the arguments or fall back to other methods.

The arguments to this function should all agree in scalar type T. The * function, which exposes the fast geometric product implementation, promotes the scalar types of the arguments before utilizing this kernel. The scalar multiplication operations are implemented using muladd, allowing for hardware fma operations to be used when available.

The GradeFilter F allows for some blade multiplications to be excluded if they meet certain criteria. This is useful for implementing products besides the geometric product, such as the wedge product, which excludes multiplications between blades with shared vectors. Without a filter, this kernel just returns the geometric product.

source
CliffordNumbers.GradeFilterType
CliffordNumbers.GradeFilter{S}

A type that can be used to filter certain products of blades in a geometric product multiplication. The type parameter S must be a Symbol. The single instance of GradeFilter{S} is a callable object which implements a function that takes two or more BitIndex{Q} objects a and b and returns false if the product of the blades indexed is zero.

To implement a grade filter for a product function f, define the following method: (::GradeFilter{:f})(::BitIndex{Q}, ::BitIndex{Q}) # Or if the definition allows for more arguments (::GradeFilter{:f})(::BitIndex{Q}...) where Q

source
CliffordNumbers.nondegenerate_maskFunction
CliffordNumbers.nondegenerate_mask(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})

Constructs a Boolean mask which is false for any multiplication that squares a degenerate blade; true otherwise.

source
CliffordNumbers.mul_maskFunction
CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})
+)

A fast geometric product implementation using generated functions for specific cases, and generic methods which either convert the arguments or fall back to other methods.

The arguments to this function should all agree in scalar type T. The * function, which exposes the fast geometric product implementation, promotes the scalar types of the arguments before utilizing this kernel. The scalar multiplication operations are implemented using muladd, allowing for hardware fma operations to be used when available.

The GradeFilter F allows for some blade multiplications to be excluded if they meet certain criteria. This is useful for implementing products besides the geometric product, such as the wedge product, which excludes multiplications between blades with shared vectors. Without a filter, this kernel just returns the geometric product.

source
CliffordNumbers.GradeFilterType
CliffordNumbers.GradeFilter{S}

A type that can be used to filter certain products of blades in a geometric product multiplication. The type parameter S must be a Symbol. The single instance of GradeFilter{S} is a callable object which implements a function that takes two or more BitIndex{Q} objects a and b and returns false if the product of the blades indexed is zero.

To implement a grade filter for a product function f, define the following method: (::GradeFilter{:f})(::BitIndex{Q}, ::BitIndex{Q}) # Or if the definition allows for more arguments (::GradeFilter{:f})(::BitIndex{Q}...) where Q

source
CliffordNumbers.nondegenerate_maskFunction
CliffordNumbers.nondegenerate_mask(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})

Constructs a Boolean mask which is false for any multiplication that squares a degenerate blade; true otherwise.

source
CliffordNumbers.mul_maskFunction
CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})
 CliffordNumbers.mul_mask(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})
 
 CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})
-CliffordNumbers.mul_mask(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates a NTuple{L,Bool} which is true whenever the multiplication of the blade indexed by a and blades indexed by B is nonzero. false is returned if the grades multiply to zero due to the squaring of a degenerate component, or if they are filtered by F.

source
CliffordNumbers.mul_signsFunction
CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})
+CliffordNumbers.mul_mask(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates a NTuple{L,Bool} which is true whenever the multiplication of the blade indexed by a and blades indexed by B is nonzero. false is returned if the grades multiply to zero due to the squaring of a degenerate component, or if they are filtered by F.

source
CliffordNumbers.mul_signsFunction
CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})
 CliffordNumbers.mul_signs(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})
 
 CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})
-CliffordNumbers.mul_signs(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates an NTuple{L,Int8} which represents the sign associated with the multiplication needed to calculate components of a multiplication result.

This is equivalent to sign.(B) unless F === CliffordNumbers.GradeFilter{:dot}().

source
CliffordNumbers.bitindex_shuffleFunction
CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})
+CliffordNumbers.mul_signs(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})

Generates an NTuple{L,Int8} which represents the sign associated with the multiplication needed to calculate components of a multiplication result.

This is equivalent to sign.(B) unless F === CliffordNumbers.GradeFilter{:dot}().

source
CliffordNumbers.bitindex_shuffleFunction
CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})
 CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::BitIndices{Q})
 
 CliffordNumbers.bitindex_shuffle(B::NTuple{L,BitIndex{Q}}, a::BitIndex{Q})
-CliffordNumbers.bitindex_shuffle(B::BitIndices{Q}, a::BitIndex{Q})

Performs the multiplication -a * b for each element of B for the above ordering, or -b * a for the below ordering, generating a reordered NTuple of BitIndex{Q} objects suitable for implementing a geometric product.

source
Missing docstring.

Missing docstring for CliffordNumbers.widen_grade_for_mul. Check Documenter's build log for details.

Taylor series exponential

CliffordNumbers.exp_taylorFunction
CliffordNumbers.exp_taylor(x::AbstractCliffordNumber, order = Val(16))

Calculates the exponential of x using a Taylor expansion up to the specified order. In most cases, 12 is as sufficient number.

Notes

16 iterations is currently used because the number of loop iterations is not currently a performance bottleneck.

source

Return types for operations

CliffordNumbers.product_return_typeFunction
CliffordNumbers.product_return_type(::Type{X}, ::Type{Y}, [::GradeFilter{S}])

Returns a suitable type for representing the product of Clifford numbers of types X and Y. The GradeFilter{S} argument allows for the return type to be changed depending on the type of product. Without specialization on S, a type suitable for the geometric product is returned.

source
CliffordNumbers.exponential_typeFunction
CliffordNumbers.exponential_type(::Type{<:AbstractCliffordNumber})
-CliffordNumbers.exponential_type(x::AbstractCliffordNumber)

Returns the type expected when exponentiating a Clifford number. This is an EvenCliffordNumber if the nonzero grades of the input are even, a CliffordNumber otherwise.

source
+CliffordNumbers.bitindex_shuffle(B::BitIndices{Q}, a::BitIndex{Q})

Performs the multiplication -a * b for each element of B for the above ordering, or -b * a for the below ordering, generating a reordered NTuple of BitIndex{Q} objects suitable for implementing a geometric product.

source
Missing docstring.

Missing docstring for CliffordNumbers.widen_grade_for_mul. Check Documenter's build log for details.

Taylor series exponential

CliffordNumbers.exp_taylorFunction
CliffordNumbers.exp_taylor(x::AbstractCliffordNumber, order = Val(16))

Calculates the exponential of x using a Taylor expansion up to the specified order. In most cases, 12 is as sufficient number.

Notes

16 iterations is currently used because the number of loop iterations is not currently a performance bottleneck.

source

Return types for operations

CliffordNumbers.product_return_typeFunction
CliffordNumbers.product_return_type(::Type{X}, ::Type{Y}, [::GradeFilter{S}])

Returns a suitable type for representing the product of Clifford numbers of types X and Y. The GradeFilter{S} argument allows for the return type to be changed depending on the type of product. Without specialization on S, a type suitable for the geometric product is returned.

source
CliffordNumbers.exponential_typeFunction
CliffordNumbers.exponential_type(::Type{<:AbstractCliffordNumber})
+CliffordNumbers.exponential_type(x::AbstractCliffordNumber)

Returns the type expected when exponentiating a Clifford number. This is an EvenCliffordNumber if the nonzero grades of the input are even, a CliffordNumber otherwise.

source
diff --git a/dev/api/math.html b/dev/api/math.html index 56ac26e..07f9afd 100644 --- a/dev/api/math.html +++ b/dev/api/math.html @@ -1,9 +1,9 @@ Math · CliffordNumbers.jl

Mathematical operations

Grade automorphisms

Base.reverse(::BitIndex)
 CliffordNumbers.grade_involution(::BitIndex)
-Base.conj(::BitIndex)

Duals and inverses

CliffordNumbers.versor_inverseFunction
CliffordNumbers.versor_inverse(x::AbstractCliffordNumber)

Calculates the versor inverse of x, equal to x' / abs2(x).

The versor inverse is only guaranteed to be an inverse for versors. Not all Clifford numbers have a well-defined inverse, (for instance, in algebras with 2 or more positive-squaring, dimensions, 1 + e₁ has no inverse). To validate the result, use inv(x) instead.

source
Base.invMethod
inv(x::AbstractCliffordNumber) -> AbstractCliffordNumber

Calculates the inverse of x, if it exists, using the versor inverse formula x' / abs2(x). The result is tested to check if its left and right products with x are approximately 1, and a CliffordNumbers.InverseException is thrown if this test does not pass.

source

Addition and subtraction

Addition and subtraction integrate seamlessly with those of the Julia Base number types, and no special documentation is included here.

Products

Products with scalars

The standard multiplication and division operations (*, /, //) between Clifford numbers and scalars behave as expected. Base.muladd has been overloaded to take advantage of fma instructions available on some hardware platforms.

Base.muladdMethod
muladd(x::Union{Real,Complex}, y::AbstractCliffordNumber{Q}, z::AbstractCliffordNumber{Q})
-muladd(x::AbstractCliffordNumber{Q}, y::Union{Real,Complex}, z::AbstractCliffordNumber{Q})

Multiplies a scalar with a Clifford number and adds another Clifford number, utilizing optimizations made available with scalar muladd, such as fma if hardware support is available.

source

Geometric products

Missing docstring.

Missing docstring for Base.:*(::AbstractCliffordNumber{Q}, ::AbstractCliffordNumber{Q}) where Q. Check Documenter's build log for details.

CliffordNumbers.left_contractionFunction
left_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
-⨼(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the left contraction of x and y.

For basis blades A of grade m and B of grade n, the left contraction is zero if n < m, otherwise it is KVector{n-m,Q}(A*B).

source
CliffordNumbers.right_contractionFunction
right_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
-⨽(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the right contraction of x and y.

For basis blades A of grade m and B of grade n, the right contraction is zero if m < n, otherwise it is KVector{m-n,Q}(A*B).

source
CliffordNumbers.dotFunction
CliffordNumbers.dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the dot product of x and y.

For basis blades A of grade m and B of grade n, the dot product is equal to the left contraction when m >= n and is equal to the right contraction (up to sign) when n >= m.

Why is this function not exported?

The LinearAlgebra package also defines a dot function, and if both packages are used together, this will cause a name conflict if CliffordNumbers.dot is exported. In the future, we will try to resolve this without requiring a LinearAlgebra dependency.

Additionally, there is reason to prefer the use of the left and right contractions over the dot product because the contractions require fewer exceptions in their definitions and properties.

source
CliffordNumbers.hestenes_dotFunction
CliffordNumbers.hestenes_dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Returns the Hestenes product: this is equal to the dot product given by dot(x, y) but is equal to to zero when either x or y is a scalar.

Why is this function not exported?

In almost every case, left and right contractions are preferable - the dot product and the Hestenes product are less regular in algebraic sense, and the conditionals present in its implementation slow it down relative to contractions. It is provided for the sake of exact reproducibility of results which use it.

source
Missing docstring.

Missing docstring for CliffordNumbers.wedge(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q}) where Q. Check Documenter's build log for details.

CliffordNumbers.commutatorFunction
×(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
-commutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the commutator (or antisymmetric) product, equal to 1//2 * (x*y - y*x).

Note that the commutator product, in general, is not equal to the wedge product, which may be invoked with the wedge function or the operator.

Type promotion

Because of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.

source
CliffordNumbers.anticommutatorFunction
⨰(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
-anticommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the anticommutator (or symmetric) product, equal to 1//2 * (x*y + y*x).

Note that the dot product, in general, is not equal to the anticommutator product, which may be invoked with dot. In some cases, the preferred operators might be the left and right contractions, which use infix operators and respectively.

Type promotion

Because of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.

source

Scalar products and normalization

CliffordNumbers.scalar_productFunction
scalar_product(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the scalar product of two Clifford numbers with quadratic form Q. The result is a Real or Complex number. This can be converted back to an AbstractCliffordNumber.

source
Base.abs2Method
abs2(x::AbstractCliffordNumber{Q,T}) -> T

Calculates the squared norm of x, equal to scalar_product(x, x').

source
Base.absMethod
abs2(x::AbstractCliffordNumber{Q,T}) -> Union{Real,Complex}

Calculates the norm of x, equal to sqrt(scalar_product(x, x')).

source
CliffordNumbers.normalizeFunction
normalize(x::AbstractCliffordNumber{Q}) -> AbstractCliffordNumber{Q}

Normalizes x so that its magnitude (as calculated by abs2(x)) is 1.

source

Exponentiation

Base.expMethod
exp(x::AbstractCliffordNumber{Q})

Returns the natural exponential of a Clifford number.

For special cases where m squares to a scalar, the following shortcuts can be used to calculate exp(x):

  • When x^2 < 0: exp(x) === cos(abs(x)) + x * sin(abs(x)) / abs(x)
  • When x^2 > 0: exp(x) === cosh(abs(x)) + x * sinh(abs(x)) / abs(x)
  • When x^2 == 0: exp(x) == 1 + x

See also: exppi, exptau.

source
CliffordNumbers.exppiFunction
exppi(x::AbstractCliffordNumber)

Returns the natural exponential of π * x with greater accuracy than exp(π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).

See also: exp, exptau.

source
CliffordNumbers.exptauFunction
exptau(x::AbstractCliffordNumber)

Returns the natural exponential of 2π * x with greater accuracy than exp(2π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).

See also: exp, exppi.

source
+Base.conj(::BitIndex)

Duals and inverses

CliffordNumbers.versor_inverseFunction
CliffordNumbers.versor_inverse(x::AbstractCliffordNumber)

Calculates the versor inverse of x, equal to x' / abs2(x).

The versor inverse is only guaranteed to be an inverse for versors. Not all Clifford numbers have a well-defined inverse, (for instance, in algebras with 2 or more positive-squaring, dimensions, 1 + e₁ has no inverse). To validate the result, use inv(x) instead.

source
Base.invMethod
inv(x::AbstractCliffordNumber) -> AbstractCliffordNumber

Calculates the inverse of x, if it exists, using the versor inverse formula x' / abs2(x). The result is tested to check if its left and right products with x are approximately 1, and a CliffordNumbers.InverseException is thrown if this test does not pass.

source

Addition and subtraction

Addition and subtraction integrate seamlessly with those of the Julia Base number types, and no special documentation is included here.

Products

Products with scalars

The standard multiplication and division operations (*, /, //) between Clifford numbers and scalars behave as expected. Base.muladd has been overloaded to take advantage of fma instructions available on some hardware platforms.

Base.muladdMethod
muladd(x::Union{Real,Complex}, y::AbstractCliffordNumber{Q}, z::AbstractCliffordNumber{Q})
+muladd(x::AbstractCliffordNumber{Q}, y::Union{Real,Complex}, z::AbstractCliffordNumber{Q})

Multiplies a scalar with a Clifford number and adds another Clifford number, utilizing optimizations made available with scalar muladd, such as fma if hardware support is available.

source

Geometric products

Missing docstring.

Missing docstring for Base.:*(::AbstractCliffordNumber{Q}, ::AbstractCliffordNumber{Q}) where Q. Check Documenter's build log for details.

CliffordNumbers.left_contractionFunction
left_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
+⨼(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the left contraction of x and y.

For basis blades A of grade m and B of grade n, the left contraction is zero if n < m, otherwise it is KVector{n-m,Q}(A*B).

source
CliffordNumbers.right_contractionFunction
right_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
+⨽(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the right contraction of x and y.

For basis blades A of grade m and B of grade n, the right contraction is zero if m < n, otherwise it is KVector{m-n,Q}(A*B).

source
CliffordNumbers.dotFunction
CliffordNumbers.dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the dot product of x and y.

For basis blades A of grade m and B of grade n, the dot product is equal to the left contraction when m >= n and is equal to the right contraction (up to sign) when n >= m.

Why is this function not exported?

The LinearAlgebra package also defines a dot function, and if both packages are used together, this will cause a name conflict if CliffordNumbers.dot is exported. In the future, we will try to resolve this without requiring a LinearAlgebra dependency.

Additionally, there is reason to prefer the use of the left and right contractions over the dot product because the contractions require fewer exceptions in their definitions and properties.

source
CliffordNumbers.hestenes_dotFunction
CliffordNumbers.hestenes_dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Returns the Hestenes product: this is equal to the dot product given by dot(x, y) but is equal to to zero when either x or y is a scalar.

Why is this function not exported?

In almost every case, left and right contractions are preferable - the dot product and the Hestenes product are less regular in algebraic sense, and the conditionals present in its implementation slow it down relative to contractions. It is provided for the sake of exact reproducibility of results which use it.

source
Missing docstring.

Missing docstring for CliffordNumbers.wedge(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q}) where Q. Check Documenter's build log for details.

CliffordNumbers.commutatorFunction
×(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
+commutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the commutator (or antisymmetric) product, equal to 1//2 * (x*y - y*x).

Note that the commutator product, in general, is not equal to the wedge product, which may be invoked with the wedge function or the operator.

Type promotion

Because of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.

source
CliffordNumbers.anticommutatorFunction
⨰(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})
+anticommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the anticommutator (or symmetric) product, equal to 1//2 * (x*y + y*x).

Note that the dot product, in general, is not equal to the anticommutator product, which may be invoked with dot. In some cases, the preferred operators might be the left and right contractions, which use infix operators and respectively.

Type promotion

Because of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.

source

Scalar products and normalization

CliffordNumbers.scalar_productFunction
scalar_product(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})

Calculates the scalar product of two Clifford numbers with quadratic form Q. The result is a Real or Complex number. This can be converted back to an AbstractCliffordNumber.

source
Base.abs2Method
abs2(x::AbstractCliffordNumber{Q,T}) -> T

Calculates the squared norm of x, equal to scalar_product(x, x').

source
Base.absMethod
abs2(x::AbstractCliffordNumber{Q,T}) -> Union{Real,Complex}

Calculates the norm of x, equal to sqrt(scalar_product(x, x')).

source
CliffordNumbers.normalizeFunction
normalize(x::AbstractCliffordNumber{Q}) -> AbstractCliffordNumber{Q}

Normalizes x so that its magnitude (as calculated by abs2(x)) is 1.

source

Exponentiation

Base.expMethod
exp(x::AbstractCliffordNumber{Q})

Returns the natural exponential of a Clifford number.

For special cases where m squares to a scalar, the following shortcuts can be used to calculate exp(x):

  • When x^2 < 0: exp(x) === cos(abs(x)) + x * sin(abs(x)) / abs(x)
  • When x^2 > 0: exp(x) === cosh(abs(x)) + x * sinh(abs(x)) / abs(x)
  • When x^2 == 0: exp(x) == 1 + x

See also: exppi, exptau.

source
CliffordNumbers.exppiFunction
exppi(x::AbstractCliffordNumber)

Returns the natural exponential of π * x with greater accuracy than exp(π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).

See also: exp, exptau.

source
CliffordNumbers.exptauFunction
exptau(x::AbstractCliffordNumber)

Returns the natural exponential of 2π * x with greater accuracy than exp(2π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).

See also: exp, exppi.

source
diff --git a/dev/api/metrics.html b/dev/api/metrics.html index 2bce77f..162c6f4 100644 --- a/dev/api/metrics.html +++ b/dev/api/metrics.html @@ -1,16 +1,16 @@ -Metric signatures · CliffordNumbers.jl

Metric signatures

Signature types

CliffordNumbers.Metrics.AbstractSignatureType
Metrics.AbstractSignature <: AbstractVector{Int8}

Supertype for all data types that represent metric signatures. This includes the generic Signature type as well as other specialized types.

Metric signatures can be interpreted as the signs of the diagonal elements of the metric tensor. All elements are either -1, 0, or 1. All nondegenerate Clifford algebras admit an orthonormal basis corresponding to the metric.

Aside from the generic Metrics.Signature subtype, types for commonly used algebras are available, including Metrics.VGA, Metrics.PGA, and Metrics.CGA. Custom signatures with firmer bounds on their behavior can be implemented by subtyping this type.

source
CliffordNumbers.Metrics.SignatureType
Metrics.Signature <: Metrics.AbstractSignature
+Metric signatures · CliffordNumbers.jl

Metric signatures

Signature types

CliffordNumbers.Metrics.AbstractSignatureType
Metrics.AbstractSignature <: AbstractVector{Int8}

Supertype for all data types that represent metric signatures. This includes the generic Signature type as well as other specialized types.

Metric signatures can be interpreted as the signs of the diagonal elements of the metric tensor. All elements are either -1, 0, or 1. All nondegenerate Clifford algebras admit an orthonormal basis corresponding to the metric.

Aside from the generic Metrics.Signature subtype, types for commonly used algebras are available, including Metrics.VGA, Metrics.PGA, and Metrics.CGA. Custom signatures with firmer bounds on their behavior can be implemented by subtyping this type.

source
CliffordNumbers.Metrics.SignatureType
Metrics.Signature <: Metrics.AbstractSignature
 Metrics.Signature(
     dimensions::Integer,
     negative::UInt,
     degenerate::UInt,
     [first_index::Integer = 1]
-)

Contains information about the metric associated with a Clifford algebra or Clifford number. This type is constructed to be as generic as possible; other subtypes of Metrics.AbstractSignature may provide firmer guarantees on behavior, such as VGA.

The number which the dimensions square to is stored in a pair of UInt fields. The negative field consists of 1 bits for dimensions that square to a negative number, and 0 bits for those squaring to a positive number, matching the convention of sign bits in signed numbers.

The degenerate field consists of 1 bits for degenerate dimensions (dimensions that square to zero) and 0 bits for nondegenerate dimensions.

The numerical index of the first basis vector is first_index, which defaults to 1. Some algebras conventionally use 0 as the first index, such as projective geometric algebras and Lorentzian geometric algebras, and in some cases it may be useful to start with a negative index if there are a larger number of modeling dimensions.

source
CliffordNumbers.Metrics.VGAType
VGA <: Metrics.AbstractSignature

Represents the signature associated with a vanilla geometric algebra (VGA), a positive-definite geometric algebra which models space without any projective dimensions.

source
CliffordNumbers.Metrics.PGAType
PGA <: Metrics.AbstractSignature

Represents the signature associated with a PGA (projective geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one degenerate (zero-squaring) dimension represented by e₀. This degenerate dimension corresponds with the n∞ null vector in CGA (conformal geometric algebra).

source
CliffordNumbers.Metrics.CGAType
CGA <: Metrics.AbstractSignature

Represents the signature of a CGA (conformal geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one positive-squaring dimension and one negative-squaring dimension.

There are two common choices of vector basis for the extra dimensions added when working with CGA. The most straightforward one is e₊ and e₋, which square to +1 and -1, respectively, and this is what is used internally, with the negative-squaring dimension being the first one.

However, there is another commonly used basis: define null vectors n₀ = (e₋ - e₊)/2 and n∞ = e₋ - e₊, which represent the origin point and the point at infinity, respectively. n∞ corresponds to e₀ in PGA (projective geometric algebra).

source
CliffordNumbers.Metrics.LGAType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
-const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.LGAEastType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
-const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.LGAWestType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
-const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.ExteriorType
Exterior <: Metrics.AbstractSignature

Represents a signature corresponding to an exterior algebra. In an exterior algebra, all 1-blades square to 0, and the geometric product is equivalent ot the wedge product.

Unlike VGA, PGA, CGA, and LGA, the first index is not assumed when constructing this object, and can be manually specified. If it is not specified, it defaults to 1.

source

Aliases for common signatures

CliffordNumbers.Metrics.VGA2DConstant
VGA2D (alias for VGA(2))

The algebra of 2D space. The even subalgebra of this algebra is isomorphic to ℂ, the complex numbers.

source
CliffordNumbers.Metrics.VGA3DConstant
VGA3D (alias for VGA(3))
-const APS = VGA3D

The algebra of physical space, a 3D VGA which is commonly used (explicitly and implicitly) to model non-relativistic physics. It also serves as the subalgebra of both signature conventions of the spacetime algebra (available as STAEast and STAWest).

The even subalgebra of this algebra is isomorphic to ℍ, the quaternions.

source
CliffordNumbers.Metrics.PGA3DConstant
PGA3D (alias for PGA(3))

The projective geometric algebra of 3D space, which represents points, lines, and planes in a 3D space.

source
CliffordNumbers.Metrics.CGA2DConstant
CGA2D (alias for CGA(2))

The conformal geometric algebra of 2D space, which represents points, lines, and circles on the plane. This algebra constitutes a framework for compass and straightedge constructions.

This algebra is isomorphic to STAEast, and this isomorphism is the reason why the default convention for spacetime algebras in this package is the West Coast (mostly negative) convention.

source
CliffordNumbers.Metrics.CGA3DConstant
CGA3D (alias for CGA(3))

The conformal geometric algebra of 3D space, which represents points, lines, and planes, as well as circles and spheres. This algebra constitutes a framework for extending compass and straightedge constructions to 3 dimensions.

source
CliffordNumbers.Metrics.STAEastConstant
STAEast (alias for LGAEast(3))

The spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative), with the temporal dimension at index 0.

This convention is not the default STA convention, since this signature is identical to that of the 2D conformal geometric algebra.

source
CliffordNumbers.Metrics.STAPEastConstant
STAPEast (alias for Signature(5, 0b00010, 0b00001, -1))

The projective spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source
CliffordNumbers.Metrics.STAPWestConstant
STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))
-const STAP = STAPWest

The projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source
CliffordNumbers.Metrics.STAPConstant
STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))
-const STAP = STAPWest

The projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source

Associated methods

CliffordNumbers.Metrics.dimensionFunction
dimension(s::AbstractSignature) -> Int8

Returns the total number of dimensions associated with s. The default implementation returns signed(s.dimensions).

The total number of basis blades is equal to to the size of the power set of all basis vectors, and is equal to 2^dimension(s).

source
CliffordNumbers.Metrics.gradesFunction
grades(s::AbstractSignature) -> UnitRange{Int8}

Returns the total number of grades associated with s, which is equal to 0:dimension(s).

source
CliffordNumbers.Metrics.is_degenerateFunction
is_degenerate(s::AbstractSignature)

Returns true if any basis elements of s square to 0.

This does not imply that no elements of the associated Clifford algebra square to 0.

source
+)

Contains information about the metric associated with a Clifford algebra or Clifford number. This type is constructed to be as generic as possible; other subtypes of Metrics.AbstractSignature may provide firmer guarantees on behavior, such as VGA.

The number which the dimensions square to is stored in a pair of UInt fields. The negative field consists of 1 bits for dimensions that square to a negative number, and 0 bits for those squaring to a positive number, matching the convention of sign bits in signed numbers.

The degenerate field consists of 1 bits for degenerate dimensions (dimensions that square to zero) and 0 bits for nondegenerate dimensions.

The numerical index of the first basis vector is first_index, which defaults to 1. Some algebras conventionally use 0 as the first index, such as projective geometric algebras and Lorentzian geometric algebras, and in some cases it may be useful to start with a negative index if there are a larger number of modeling dimensions.

source
CliffordNumbers.Metrics.VGAType
VGA <: Metrics.AbstractSignature

Represents the signature associated with a vanilla geometric algebra (VGA), a positive-definite geometric algebra which models space without any projective dimensions.

source
CliffordNumbers.Metrics.PGAType
PGA <: Metrics.AbstractSignature

Represents the signature associated with a PGA (projective geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one degenerate (zero-squaring) dimension represented by e₀. This degenerate dimension corresponds with the n∞ null vector in CGA (conformal geometric algebra).

source
CliffordNumbers.Metrics.CGAType
CGA <: Metrics.AbstractSignature

Represents the signature of a CGA (conformal geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one positive-squaring dimension and one negative-squaring dimension.

There are two common choices of vector basis for the extra dimensions added when working with CGA. The most straightforward one is e₊ and e₋, which square to +1 and -1, respectively, and this is what is used internally, with the negative-squaring dimension being the first one.

However, there is another commonly used basis: define null vectors n₀ = (e₋ - e₊)/2 and n∞ = e₋ - e₊, which represent the origin point and the point at infinity, respectively. n∞ corresponds to e₀ in PGA (projective geometric algebra).

source
CliffordNumbers.Metrics.LGAType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
+const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.LGAEastType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
+const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.LGAWestType
LGA{C} <: Metrics.AbstractSignature

Represents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.

The type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:

const LGAEast = LGA{false}
+const LGAWest = LGA{true}

The names correspond to the "East Coast" and "West Coast" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.

source
CliffordNumbers.Metrics.ExteriorType
Exterior <: Metrics.AbstractSignature

Represents a signature corresponding to an exterior algebra. In an exterior algebra, all 1-blades square to 0, and the geometric product is equivalent ot the wedge product.

Unlike VGA, PGA, CGA, and LGA, the first index is not assumed when constructing this object, and can be manually specified. If it is not specified, it defaults to 1.

source

Aliases for common signatures

CliffordNumbers.Metrics.VGA2DConstant
VGA2D (alias for VGA(2))

The algebra of 2D space. The even subalgebra of this algebra is isomorphic to ℂ, the complex numbers.

source
CliffordNumbers.Metrics.VGA3DConstant
VGA3D (alias for VGA(3))
+const APS = VGA3D

The algebra of physical space, a 3D VGA which is commonly used (explicitly and implicitly) to model non-relativistic physics. It also serves as the subalgebra of both signature conventions of the spacetime algebra (available as STAEast and STAWest).

The even subalgebra of this algebra is isomorphic to ℍ, the quaternions.

source
CliffordNumbers.Metrics.PGA3DConstant
PGA3D (alias for PGA(3))

The projective geometric algebra of 3D space, which represents points, lines, and planes in a 3D space.

source
CliffordNumbers.Metrics.CGA2DConstant
CGA2D (alias for CGA(2))

The conformal geometric algebra of 2D space, which represents points, lines, and circles on the plane. This algebra constitutes a framework for compass and straightedge constructions.

This algebra is isomorphic to STAEast, and this isomorphism is the reason why the default convention for spacetime algebras in this package is the West Coast (mostly negative) convention.

source
CliffordNumbers.Metrics.CGA3DConstant
CGA3D (alias for CGA(3))

The conformal geometric algebra of 3D space, which represents points, lines, and planes, as well as circles and spheres. This algebra constitutes a framework for extending compass and straightedge constructions to 3 dimensions.

source
CliffordNumbers.Metrics.STAEastConstant
STAEast (alias for LGAEast(3))

The spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative), with the temporal dimension at index 0.

This convention is not the default STA convention, since this signature is identical to that of the 2D conformal geometric algebra.

source
CliffordNumbers.Metrics.STAPEastConstant
STAPEast (alias for Signature(5, 0b00010, 0b00001, -1))

The projective spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source
CliffordNumbers.Metrics.STAPWestConstant
STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))
+const STAP = STAPWest

The projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source
CliffordNumbers.Metrics.STAPConstant
STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))
+const STAP = STAPWest

The projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.

As with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.

source

Associated methods

CliffordNumbers.Metrics.dimensionFunction
dimension(s::AbstractSignature) -> Int8

Returns the total number of dimensions associated with s. The default implementation returns signed(s.dimensions).

The total number of basis blades is equal to to the size of the power set of all basis vectors, and is equal to 2^dimension(s).

source
CliffordNumbers.Metrics.gradesFunction
grades(s::AbstractSignature) -> UnitRange{Int8}

Returns the total number of grades associated with s, which is equal to 0:dimension(s).

source
CliffordNumbers.Metrics.is_degenerateFunction
is_degenerate(s::AbstractSignature)

Returns true if any basis elements of s square to 0.

This does not imply that no elements of the associated Clifford algebra square to 0.

source
diff --git a/dev/home.html b/dev/home.html index e8021a4..0df3fd3 100644 --- a/dev/home.html +++ b/dev/home.html @@ -1,2 +1,2 @@ -Home · CliffordNumbers.jl

CliffordNumbers

CliffordNumbers.jl is a package that provides fully static multivectors (Clifford numbers) in arbitrary dimensions and metrics. While in many cases, sparse representations of multivectors are more efficient, for spaces of low dimension, dense static representations may provide a performance and convenience advantage.

Design goals

The goal of this package is to provide a multivector implementation that:

  • Allows for the construction of multivectors in arbitrary metrics, with coefficients that subtype any instance of Julia's base numeric types, Real or Complex.
  • Provides data structures of fixed sizes that represent multivectors. This allows for instances to be allocated on the stack or stored inline in an Array rather than as pointers to individually allocated instances.
  • Provides dense representations of multivectors, as well as convenient sparse representations, which can be constructed from each other, converted in a way that guarantees representability, and allows for promotion between instances.
  • Subtypes Number: The term "Clifford number" emphasizes the perspective of multivectors as an extension of the real numbers, in the same way that complex numbers and quaternions extend them. (It should be noted that both complex numbers and quaternions are Clifford algebras themselves!)
  • Aggressively optimizes all mathematical operations, utilizing fma operations and SIMD instructions whenever possible.
  • Interoperates with automatic differentiation tools and other packages which allow for the implementation of operations from geometric calculus.
+Home · CliffordNumbers.jl

CliffordNumbers

CliffordNumbers.jl is a package that provides fully static multivectors (Clifford numbers) in arbitrary dimensions and metrics. While in many cases, sparse representations of multivectors are more efficient, for spaces of low dimension, dense static representations may provide a performance and convenience advantage.

Design goals

The goal of this package is to provide a multivector implementation that:

  • Allows for the construction of multivectors in arbitrary metrics, with coefficients that subtype any instance of Julia's base numeric types, Real or Complex.
  • Provides data structures of fixed sizes that represent multivectors. This allows for instances to be allocated on the stack or stored inline in an Array rather than as pointers to individually allocated instances.
  • Provides dense representations of multivectors, as well as convenient sparse representations, which can be constructed from each other, converted in a way that guarantees representability, and allows for promotion between instances.
  • Subtypes Number: The term "Clifford number" emphasizes the perspective of multivectors as an extension of the real numbers, in the same way that complex numbers and quaternions extend them. (It should be noted that both complex numbers and quaternions are Clifford algebras themselves!)
  • Aggressively optimizes all mathematical operations, utilizing fma operations and SIMD instructions whenever possible.
  • Interoperates with automatic differentiation tools and other packages which allow for the implementation of operations from geometric calculus.
diff --git a/dev/indexing.html b/dev/indexing.html index e53bd8c..56cafff 100644 --- a/dev/indexing.html +++ b/dev/indexing.html @@ -37,4 +37,4 @@ true julia> BitIndices{STA,CliffordNumber{STA}}() == BitIndices{STA,CliffordNumber{STA,Float32,8}}() -true

For this reason, you should call BitIndices(x) or BitIndices(C) instead of directly constructing BitIndices{Q,C}().

TransformedBitIndices{Q,C,F}

If we want to perform a transformation on all elements of a BitIndices instance, we may use dot syntax and broadcast an operation: for instance, reverse.(BitIndices(x)) to obtain the reverse of all indices. Without any explicit specification of behavior, this will return a Vector, and for the sake of performance we'd like to avoid returning types without statically known lengths.

We could solve this by converting BitIndices to a Tuple internally as part of the broadcasting implementation, but doing this will cause its own set of problems: indexing an AbstractCliffordNumber with a Tuple returns a Tuple. This may be fine internally, if we know to call the constructor, but this is potentially confusing for new users. For this reason, we provide TransformedBitIndices{Q,C,F}, which is a lazy representation of a function applied to every element of BitIndices(C).

For convenience, we provide a few aliases for operations which are commonly used with BitIndices:

In the future, we may override some broadcast implementations to ensure that all of these types are interconvertible with each other and with BitIndices{Q,C}.

+true

For this reason, you should call BitIndices(x) or BitIndices(C) instead of directly constructing BitIndices{Q,C}().

TransformedBitIndices{Q,C,F}

If we want to perform a transformation on all elements of a BitIndices instance, we may use dot syntax and broadcast an operation: for instance, reverse.(BitIndices(x)) to obtain the reverse of all indices. Without any explicit specification of behavior, this will return a Vector, and for the sake of performance we'd like to avoid returning types without statically known lengths.

We could solve this by converting BitIndices to a Tuple internally as part of the broadcasting implementation, but doing this will cause its own set of problems: indexing an AbstractCliffordNumber with a Tuple returns a Tuple. This may be fine internally, if we know to call the constructor, but this is potentially confusing for new users. For this reason, we provide TransformedBitIndices{Q,C,F}, which is a lazy representation of a function applied to every element of BitIndices(C).

For convenience, we provide a few aliases for operations which are commonly used with BitIndices:

In the future, we may override some broadcast implementations to ensure that all of these types are interconvertible with each other and with BitIndices{Q,C}.

diff --git a/dev/metrics.html b/dev/metrics.html index 5d3bc8b..a6888f0 100644 --- a/dev/metrics.html +++ b/dev/metrics.html @@ -1,2 +1,2 @@ -Metric signatures · CliffordNumbers.jl

Metric signatures

Clifford algebras are characterized by the metric signatures of the spaces they represent. Some are very commonly used, such as the algebra of physical space (APS), or are generated as part of a family, such as the projective geometric algebras (PGAs), but in other cases you may need the flexibility to work with custom metric signatures.

The CliffordNumbers.Metrics submodule provides tools for working with metric signatures.

Interface

The type parameter Q of AbstractCliffordNumber{Q,T} is not constrained in any way, which means that any type or data consisting of pure bits may reside there. However, for the sake of correctness and fully defined behavior, Q must satisfy an informal interface.

Metric signature objects are treated like AbstractVector{Int8} instances, but with the elements constrained to be equal to +1, 0, or -1, corresponding to basis 1-blades squaring to positive values, negative values, or zero. In the future, we may support arbitrary values for this type.

This array is not constrained to be a 1-based array, and the values of eachindex for the array correspond to the indices of the basis 1-blades of the algebra.

The Metrics.AbstractSignature type

We define a type, Metrics.AbstractSignature <: AbstractVector{Int8}, for which this interface is already partially implemented.

Pre-defined signatures

There are many commonly used families of algebras, and for the sake of convenience, we provide four subtypes of Metrics.AbstractSignature to handles these cases:

  • Metrics.VGA represents vanilla geometric algebras.
  • Metrics.PGA represents projective geometric algebras.
  • Metrics.CGA represents conformal geometric algebras.
  • Metrics.LGA{C} represents Lorentzian geometric algebras:
    • Metrics.LGAEast uses the East Coast convention (timelike dimensions square to -1).
    • Metrics.LGAWest uses the West Coast convention (timelike dimensions square to +1).

To construct an instance of one of these types, call it with the number of modeled spatial dimensions:

  • Metrics.VGA(3) models 3 spatial dimensions with no extra dimensions.
  • Metrics.PGA(3) models 3 spatial dimensions with 1 degenerate (zero-squaring) dimension.
  • Metrics.CGA(3) models 3 spatial dimensions with 2 extra dimensions.
  • Metrics.LGAEast(3) models 3 spatial dimensions with an extra negative-squaring time dimension.
+Metric signatures · CliffordNumbers.jl

Metric signatures

Clifford algebras are characterized by the metric signatures of the spaces they represent. Some are very commonly used, such as the algebra of physical space (APS), or are generated as part of a family, such as the projective geometric algebras (PGAs), but in other cases you may need the flexibility to work with custom metric signatures.

The CliffordNumbers.Metrics submodule provides tools for working with metric signatures.

Interface

The type parameter Q of AbstractCliffordNumber{Q,T} is not constrained in any way, which means that any type or data consisting of pure bits may reside there. However, for the sake of correctness and fully defined behavior, Q must satisfy an informal interface.

Metric signature objects are treated like AbstractVector{Int8} instances, but with the elements constrained to be equal to +1, 0, or -1, corresponding to basis 1-blades squaring to positive values, negative values, or zero. In the future, we may support arbitrary values for this type.

This array is not constrained to be a 1-based array, and the values of eachindex for the array correspond to the indices of the basis 1-blades of the algebra.

The Metrics.AbstractSignature type

We define a type, Metrics.AbstractSignature <: AbstractVector{Int8}, for which this interface is already partially implemented.

Pre-defined signatures

There are many commonly used families of algebras, and for the sake of convenience, we provide four subtypes of Metrics.AbstractSignature to handles these cases:

  • Metrics.VGA represents vanilla geometric algebras.
  • Metrics.PGA represents projective geometric algebras.
  • Metrics.CGA represents conformal geometric algebras.
  • Metrics.LGA{C} represents Lorentzian geometric algebras:
    • Metrics.LGAEast uses the East Coast convention (timelike dimensions square to -1).
    • Metrics.LGAWest uses the West Coast convention (timelike dimensions square to +1).

To construct an instance of one of these types, call it with the number of modeled spatial dimensions:

  • Metrics.VGA(3) models 3 spatial dimensions with no extra dimensions.
  • Metrics.PGA(3) models 3 spatial dimensions with 1 degenerate (zero-squaring) dimension.
  • Metrics.CGA(3) models 3 spatial dimensions with 2 extra dimensions.
  • Metrics.LGAEast(3) models 3 spatial dimensions with an extra negative-squaring time dimension.
diff --git a/dev/numeric.html b/dev/numeric.html index 19c1cff..1ea49cb 100644 --- a/dev/numeric.html +++ b/dev/numeric.html @@ -8,4 +8,4 @@ 1 + 4σ₁σ₂ + 6σ₁σ₃ + 7σ₂σ₃ julia> convert(EvenCliffordNumber, test) -ERROR: InexactError: ...
Danger

This is an extremely important point: construction of a Clifford number type with fewer grades than the input performs a grade projection operation without throwing an error. However, conversion will throw an error if the grades of the input value are not present in the input type.

This is not how other subtypes of Number defined by Julia Base behave, as their conversion operations are generally defined to be identical to the constructor, and always throw the same error for a given pair of type and value.

If converting an AbstractCliffordNumber to any other numeric type, construction and conversion behave identically, as expected.

Construction and conversion of Clifford numbers from other Clifford numbers the only time that the quadratic form type parameter can be omitted, as it can be inferred directly from the input. In the case of CliffordNumbers.Z2CliffordNumber, the parity type parameter can also be inferred from a KVector input.

Scalar conversion

It may be desirable to convert the scalar type of a Clifford number without having to specify the full typename of the desired output type. The function scalar_convert(T, x) takes a type T<:Union{Real,Complex} and any Clifford number x and converts its scalar type to T. If x is a Real or Complex, it just converts x to an instance of T.

+ERROR: InexactError: ...
Danger

This is an extremely important point: construction of a Clifford number type with fewer grades than the input performs a grade projection operation without throwing an error. However, conversion will throw an error if the grades of the input value are not present in the input type.

This is not how other subtypes of Number defined by Julia Base behave, as their conversion operations are generally defined to be identical to the constructor, and always throw the same error for a given pair of type and value.

If converting an AbstractCliffordNumber to any other numeric type, construction and conversion behave identically, as expected.

Construction and conversion of Clifford numbers from other Clifford numbers the only time that the quadratic form type parameter can be omitted, as it can be inferred directly from the input. In the case of CliffordNumbers.Z2CliffordNumber, the parity type parameter can also be inferred from a KVector input.

Scalar conversion

It may be desirable to convert the scalar type of a Clifford number without having to specify the full typename of the desired output type. The function scalar_convert(T, x) takes a type T<:Union{Real,Complex} and any Clifford number x and converts its scalar type to T. If x is a Real or Complex, it just converts x to an instance of T.

diff --git a/dev/operations.html b/dev/operations.html index 1ff5d64..f292e8c 100644 --- a/dev/operations.html +++ b/dev/operations.html @@ -1,2 +1,2 @@ -Operations · CliffordNumbers.jl

Operations

Like with other numbers, standard mathematical operations are supported that relate Clifford numbers to elements of their scalar field and to each other.

Unary operations

Grade automorphisms

Grade automorphisms are operations which preserves the grades of each basis blade, but changes their sign depending on the grade. All of these operations are their own inverse.

All grade automorphisms are applicable to BitIndex objects, and the way they are implemented is through constructors that use TransformedBitIndices objects to alter each grade.

Reverse

The reverse is an operation which reverses the order of the wedge product that constructed each basis blade. This is implemented with methods for Base.reverse and Base.:~.

Syntax changes

In the future, Base.:~ will no longer be used for this operation; instead Base.adjoint will be overloaded, providing ' as a syntax for the reverse.

This is the most commonly used automorphism, and in a sense can be thought of as equivalent to complex conjugation. When working with even elements of the algebras of 2D or 3D space, this behaves identically to complex conjugation and quaternion conjugation. However, this is not the case when working in the even subalgebras.

Base.reverse(::BitIndex)

Grade involution

Grade involution changes the sign of all odd grades, an operation equivalent to mirroring every basis vector of the space. This can be acheived with the grade_involution function.

When interpreting even multivectors as elements of the even subalgebra of the algebra of interest, the grade involution in the even subalgebra is equivalent to the reverse in the algebra of interest.

Grade involution is equivalent to complex conjugation in when dealing with the even subalgebra of 2D space, which is isomorphic to the complex numbers, but this is not true for quaternion conjugation. Instead, use the Clifford conjugate (described below).

CliffordNumbers.grade_involution(::BitIndex)

Clifford conjugation

The Clifford conjugate is the combination of the reverse and grade involution. This is available via an overload of Base.conj.

Warning

conj(::AbstractCliffordNumber) implements the Clifford conjugate, not the reverse!

When dealing with the even subalgebras of 2D and 3D VGAs, which are isomorphic to the complex numbers and quaternions, respectively, the Clifford conjugate is equivalent to complex conjugation or quaternion conjugation. Otherwise, this is a less widely used operation than the above two.

Base.conj(::BitIndex)

Binary operations

Addition and subtraction

Addition and subtraction work as expected for Clifford numbers just as they do for other numbers. The promotion system handles all cases where objects of mixed type are added.

Products

Clifford algebras admit a variety of products. Common ones are implemented with infix operators.

Geometric product

The geometric product, or Clifford product, is the defining product of the Clifford algebra. This is implemented with the usual multiplication operator *, but it is also possible to use parenthetical notation as it is with real numbers.

Wedge product

The wedge product is the defining product of the exterior algebra. This is available with the wedge() function, or with the infix operator.

Tip

You can define elements of exterior algebras directly by using Metrics.Exterior(D), whose geometric product is equivalent to the wedge product.

Contractions and dot products

The contraction operations generalize the dot product of vectors to Clifford numbers. While it is possible to define a symmetric dot product (and one is provided in this package), the generalization of the dot product to Clifford numbers is naturally asymmetric in cases where the grade of one input blade is not equal to that of the other.

For Clifford numbers x and y, the left contraction x ⨼ y describes the result of projecting x onto the space spanned by y. If x and y are homogeneous in grade, this product is equal to the geometric product if grade(y) ≥ grade(x), and zero otherwise. For general multivectors, the left contraction can be calculated by applying this rule to the products of their basis blades.

The analogous right contraction is only nonzero if grade(x) ≥ grade(y), and it can be calculated with .

The dot product is a symmetric variation of the left and right contractions, and provides a looser constraint on the basis blades: grade(CliffordNumbers.dot(x,y)) must equal abs(grade(x) - grade(y)). The Hestenes dot product is equivalent to the dot product above, but is zero if either x or y is a scalar.

Note

Currently, the dot product is implemented with the unexported function CliffordNumbers.dot. This package does not depend on LinearAlgebra, so there would be a name conflict if this method were exported and both this package and LinearAlgebra were loaded.

Contractions are generally favored over the dot products due to their nicer implementations and properties, which have fewer exceptions. It is generally recommended that the Hestenes dot product be avoided, though it is included in this library for the sake of completeness as CliffordNumber.hestenes_dot, which is also not exported.

Commutator and anticommutator products

The commutator product (or antisymmetric product) of Clifford numbers x and y, denoted x × y, is equal to 1//2 * (x*y - y*x). This product is nonzero if the geometric product of x and y does not commute, and the value represents the degree to which they fail to commute.

The commutator product is the building block of Lie algebras; in particular, the commutator products of bivectors, which are also bivectors. With the bivectors of 3D space, the Lie algebra is equivalent to that generated by the cross product, hence the × notation.

The analogous anticommutator product (or symmetric product) is 1//2 * (x*y + y*x). This uses the operator, which is not an operator generally used for this purpose, but was selected as it looks similar to the commutator product, with the dot indicating the similarity with the dot product, which is also symmetric.

Defining new products: Multiplication internals

Products are implemented with the fast multiplication kernel CliffordNumbers.mul, which accepts two Clifford numbers with the same scalar type and a CliffordNumbers.GradeFilter object. This GradeFilter object defines a method that takes two or more BitIndex objects and returns false if their product is constrained to be zero.

CliffordNumbers.mul requires that the coefficient types of the numbers being multiplied are the same. Methods which leverage CliffordNumbers.mul should promote the coefficient types of the arguments to a common type using scalar_promote before passing them to the kernel. Any further promotion needed to return the final result is handled by the kernel.

In general, it is also strongly recommended to promote the types of the arguments to CliffordNumbers.Z2CliffordNumber or CliffordNumber for higher performance. Currently, the implementation of CliffordNumbers.mul is asymmetric, and does not consider which input is longer. Even in the preferred order, we find that KVector incurs a significant performance penalty.

+Operations · CliffordNumbers.jl

Operations

Like with other numbers, standard mathematical operations are supported that relate Clifford numbers to elements of their scalar field and to each other.

Unary operations

Grade automorphisms

Grade automorphisms are operations which preserves the grades of each basis blade, but changes their sign depending on the grade. All of these operations are their own inverse.

All grade automorphisms are applicable to BitIndex objects, and the way they are implemented is through constructors that use TransformedBitIndices objects to alter each grade.

Reverse

The reverse is an operation which reverses the order of the wedge product that constructed each basis blade. This is implemented with methods for Base.reverse and Base.:~.

Syntax changes

In the future, Base.:~ will no longer be used for this operation; instead Base.adjoint will be overloaded, providing ' as a syntax for the reverse.

This is the most commonly used automorphism, and in a sense can be thought of as equivalent to complex conjugation. When working with even elements of the algebras of 2D or 3D space, this behaves identically to complex conjugation and quaternion conjugation. However, this is not the case when working in the even subalgebras.

Base.reverse(::BitIndex)

Grade involution

Grade involution changes the sign of all odd grades, an operation equivalent to mirroring every basis vector of the space. This can be acheived with the grade_involution function.

When interpreting even multivectors as elements of the even subalgebra of the algebra of interest, the grade involution in the even subalgebra is equivalent to the reverse in the algebra of interest.

Grade involution is equivalent to complex conjugation in when dealing with the even subalgebra of 2D space, which is isomorphic to the complex numbers, but this is not true for quaternion conjugation. Instead, use the Clifford conjugate (described below).

CliffordNumbers.grade_involution(::BitIndex)

Clifford conjugation

The Clifford conjugate is the combination of the reverse and grade involution. This is available via an overload of Base.conj.

Warning

conj(::AbstractCliffordNumber) implements the Clifford conjugate, not the reverse!

When dealing with the even subalgebras of 2D and 3D VGAs, which are isomorphic to the complex numbers and quaternions, respectively, the Clifford conjugate is equivalent to complex conjugation or quaternion conjugation. Otherwise, this is a less widely used operation than the above two.

Base.conj(::BitIndex)

Binary operations

Addition and subtraction

Addition and subtraction work as expected for Clifford numbers just as they do for other numbers. The promotion system handles all cases where objects of mixed type are added.

Products

Clifford algebras admit a variety of products. Common ones are implemented with infix operators.

Geometric product

The geometric product, or Clifford product, is the defining product of the Clifford algebra. This is implemented with the usual multiplication operator *, but it is also possible to use parenthetical notation as it is with real numbers.

Wedge product

The wedge product is the defining product of the exterior algebra. This is available with the wedge() function, or with the infix operator.

Tip

You can define elements of exterior algebras directly by using Metrics.Exterior(D), whose geometric product is equivalent to the wedge product.

Contractions and dot products

The contraction operations generalize the dot product of vectors to Clifford numbers. While it is possible to define a symmetric dot product (and one is provided in this package), the generalization of the dot product to Clifford numbers is naturally asymmetric in cases where the grade of one input blade is not equal to that of the other.

For Clifford numbers x and y, the left contraction x ⨼ y describes the result of projecting x onto the space spanned by y. If x and y are homogeneous in grade, this product is equal to the geometric product if grade(y) ≥ grade(x), and zero otherwise. For general multivectors, the left contraction can be calculated by applying this rule to the products of their basis blades.

The analogous right contraction is only nonzero if grade(x) ≥ grade(y), and it can be calculated with .

The dot product is a symmetric variation of the left and right contractions, and provides a looser constraint on the basis blades: grade(CliffordNumbers.dot(x,y)) must equal abs(grade(x) - grade(y)). The Hestenes dot product is equivalent to the dot product above, but is zero if either x or y is a scalar.

Note

Currently, the dot product is implemented with the unexported function CliffordNumbers.dot. This package does not depend on LinearAlgebra, so there would be a name conflict if this method were exported and both this package and LinearAlgebra were loaded.

Contractions are generally favored over the dot products due to their nicer implementations and properties, which have fewer exceptions. It is generally recommended that the Hestenes dot product be avoided, though it is included in this library for the sake of completeness as CliffordNumber.hestenes_dot, which is also not exported.

Commutator and anticommutator products

The commutator product (or antisymmetric product) of Clifford numbers x and y, denoted x × y, is equal to 1//2 * (x*y - y*x). This product is nonzero if the geometric product of x and y does not commute, and the value represents the degree to which they fail to commute.

The commutator product is the building block of Lie algebras; in particular, the commutator products of bivectors, which are also bivectors. With the bivectors of 3D space, the Lie algebra is equivalent to that generated by the cross product, hence the × notation.

The analogous anticommutator product (or symmetric product) is 1//2 * (x*y + y*x). This uses the operator, which is not an operator generally used for this purpose, but was selected as it looks similar to the commutator product, with the dot indicating the similarity with the dot product, which is also symmetric.

Defining new products: Multiplication internals

Products are implemented with the fast multiplication kernel CliffordNumbers.mul, which accepts two Clifford numbers with the same scalar type and a CliffordNumbers.GradeFilter object. This GradeFilter object defines a method that takes two or more BitIndex objects and returns false if their product is constrained to be zero.

CliffordNumbers.mul requires that the coefficient types of the numbers being multiplied are the same. Methods which leverage CliffordNumbers.mul should promote the coefficient types of the arguments to a common type using scalar_promote before passing them to the kernel. Any further promotion needed to return the final result is handled by the kernel.

In general, it is also strongly recommended to promote the types of the arguments to CliffordNumbers.Z2CliffordNumber or CliffordNumber for higher performance. Currently, the implementation of CliffordNumbers.mul is asymmetric, and does not consider which input is longer. Even in the preferred order, we find that KVector incurs a significant performance penalty.

diff --git a/dev/search.html b/dev/search.html index 712f790..5bcfdff 100644 --- a/dev/search.html +++ b/dev/search.html @@ -1,2 +1,2 @@ -Search · CliffordNumbers.jl

Loading search...

    +Search · CliffordNumbers.jl

    Loading search...

      diff --git a/dev/search_index.js b/dev/search_index.js index db596e6..d3d8b9d 100644 --- a/dev/search_index.js +++ b/dev/search_index.js @@ -1,3 +1,3 @@ var documenterSearchIndex = {"docs": -[{"location":"metrics.html#Metric-signatures","page":"Metric signatures","title":"Metric signatures","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Clifford algebras are characterized by the metric signatures of the spaces they represent. Some are very commonly used, such as the algebra of physical space (APS), or are generated as part of a family, such as the projective geometric algebras (PGAs), but in other cases you may need the flexibility to work with custom metric signatures.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"The CliffordNumbers.Metrics submodule provides tools for working with metric signatures.","category":"page"},{"location":"metrics.html#Interface","page":"Metric signatures","title":"Interface","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"The type parameter Q of AbstractCliffordNumber{Q,T} is not constrained in any way, which means that any type or data consisting of pure bits may reside there. However, for the sake of correctness and fully defined behavior, Q must satisfy an informal interface.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metric signature objects are treated like AbstractVector{Int8} instances, but with the elements constrained to be equal to +1, 0, or -1, corresponding to basis 1-blades squaring to positive values, negative values, or zero. In the future, we may support arbitrary values for this type.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"This array is not constrained to be a 1-based array, and the values of eachindex for the array correspond to the indices of the basis 1-blades of the algebra.","category":"page"},{"location":"metrics.html#The-Metrics.AbstractSignature-type","page":"Metric signatures","title":"The Metrics.AbstractSignature type","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"We define a type, Metrics.AbstractSignature <: AbstractVector{Int8}, for which this interface is already partially implemented.","category":"page"},{"location":"metrics.html#Pre-defined-signatures","page":"Metric signatures","title":"Pre-defined signatures","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"There are many commonly used families of algebras, and for the sake of convenience, we provide four subtypes of Metrics.AbstractSignature to handles these cases:","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metrics.VGA represents vanilla geometric algebras.\nMetrics.PGA represents projective geometric algebras.\nMetrics.CGA represents conformal geometric algebras.\nMetrics.LGA{C} represents Lorentzian geometric algebras:\nMetrics.LGAEast uses the East Coast convention (timelike dimensions square to -1).\nMetrics.LGAWest uses the West Coast convention (timelike dimensions square to +1).","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"To construct an instance of one of these types, call it with the number of modeled spatial dimensions:","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metrics.VGA(3) models 3 spatial dimensions with no extra dimensions.\nMetrics.PGA(3) models 3 spatial dimensions with 1 degenerate (zero-squaring) dimension.\nMetrics.CGA(3) models 3 spatial dimensions with 2 extra dimensions.\nMetrics.LGAEast(3) models 3 spatial dimensions with an extra negative-squaring time dimension.","category":"page"},{"location":"home.html","page":"Home","title":"Home","text":"CurrentModule = CliffordNumbers","category":"page"},{"location":"home.html#CliffordNumbers","page":"Home","title":"CliffordNumbers","text":"","category":"section"},{"location":"home.html","page":"Home","title":"Home","text":"CliffordNumbers.jl is a package that provides fully static multivectors (Clifford numbers) in arbitrary dimensions and metrics. While in many cases, sparse representations of multivectors are more efficient, for spaces of low dimension, dense static representations may provide a performance and convenience advantage.","category":"page"},{"location":"home.html#Design-goals","page":"Home","title":"Design goals","text":"","category":"section"},{"location":"home.html","page":"Home","title":"Home","text":"The goal of this package is to provide a multivector implementation that:","category":"page"},{"location":"home.html","page":"Home","title":"Home","text":"Allows for the construction of multivectors in arbitrary metrics, with coefficients that subtype any instance of Julia's base numeric types, Real or Complex.\nProvides data structures of fixed sizes that represent multivectors. This allows for instances to be allocated on the stack or stored inline in an Array rather than as pointers to individually allocated instances.\nProvides dense representations of multivectors, as well as convenient sparse representations, which can be constructed from each other, converted in a way that guarantees representability, and allows for promotion between instances.\nSubtypes Number: The term \"Clifford number\" emphasizes the perspective of multivectors as an extension of the real numbers, in the same way that complex numbers and quaternions extend them. (It should be noted that both complex numbers and quaternions are Clifford algebras themselves!)\nAggressively optimizes all mathematical operations, utilizing fma operations and SIMD instructions whenever possible.\nInteroperates with automatic differentiation tools and other packages which allow for the implementation of operations from geometric calculus.","category":"page"},{"location":"api/math.html#Mathematical-operations","page":"Math","title":"Mathematical operations","text":"","category":"section"},{"location":"api/math.html#Grade-automorphisms","page":"Math","title":"Grade automorphisms","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.reverse(::BitIndex)\nCliffordNumbers.grade_involution(::BitIndex)\nBase.conj(::BitIndex)","category":"page"},{"location":"api/math.html#Duals-and-inverses","page":"Math","title":"Duals and inverses","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"CliffordNumbers.versor_inverse\nBase.inv(::AbstractCliffordNumber)","category":"page"},{"location":"api/math.html#CliffordNumbers.versor_inverse","page":"Math","title":"CliffordNumbers.versor_inverse","text":"CliffordNumbers.versor_inverse(x::AbstractCliffordNumber)\n\nCalculates the versor inverse of x, equal to x' / abs2(x).\n\nThe versor inverse is only guaranteed to be an inverse for versors. Not all Clifford numbers have a well-defined inverse, (for instance, in algebras with 2 or more positive-squaring, dimensions, 1 + e₁ has no inverse). To validate the result, use inv(x) instead.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Base.inv-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.inv","text":"inv(x::AbstractCliffordNumber) -> AbstractCliffordNumber\n\nCalculates the inverse of x, if it exists, using the versor inverse formula x' / abs2(x). The result is tested to check if its left and right products with x are approximately 1, and a CliffordNumbers.InverseException is thrown if this test does not pass.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Addition-and-subtraction","page":"Math","title":"Addition and subtraction","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Addition and subtraction integrate seamlessly with those of the Julia Base number types, and no special documentation is included here.","category":"page"},{"location":"api/math.html#Products","page":"Math","title":"Products","text":"","category":"section"},{"location":"api/math.html#Products-with-scalars","page":"Math","title":"Products with scalars","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"The standard multiplication and division operations (*, /, //) between Clifford numbers and scalars behave as expected. Base.muladd has been overloaded to take advantage of fma instructions available on some hardware platforms.","category":"page"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.muladd(x::BaseNumber, y::T, z::T) where T<:AbstractCliffordNumber","category":"page"},{"location":"api/math.html#Base.muladd-Union{Tuple{T}, Tuple{Union{Real, Complex}, T, T}} where T<:AbstractCliffordNumber","page":"Math","title":"Base.muladd","text":"muladd(x::Union{Real,Complex}, y::AbstractCliffordNumber{Q}, z::AbstractCliffordNumber{Q})\nmuladd(x::AbstractCliffordNumber{Q}, y::Union{Real,Complex}, z::AbstractCliffordNumber{Q})\n\nMultiplies a scalar with a Clifford number and adds another Clifford number, utilizing optimizations made available with scalar muladd, such as fma if hardware support is available.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Geometric-products","page":"Math","title":"Geometric products","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.:*(::AbstractCliffordNumber{Q}, ::AbstractCliffordNumber{Q}) where Q\nCliffordNumbers.left_contraction\nCliffordNumbers.right_contraction\nCliffordNumbers.dot\nCliffordNumbers.hestenes_dot\nCliffordNumbers.wedge(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q}) where Q\nCliffordNumbers.commutator\nCliffordNumbers.anticommutator","category":"page"},{"location":"api/math.html#CliffordNumbers.left_contraction","page":"Math","title":"CliffordNumbers.left_contraction","text":"left_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n⨼(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the left contraction of x and y.\n\nFor basis blades A of grade m and B of grade n, the left contraction is zero if n < m, otherwise it is KVector{n-m,Q}(A*B).\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.right_contraction","page":"Math","title":"CliffordNumbers.right_contraction","text":"right_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n⨽(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the right contraction of x and y.\n\nFor basis blades A of grade m and B of grade n, the right contraction is zero if m < n, otherwise it is KVector{m-n,Q}(A*B).\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.dot","page":"Math","title":"CliffordNumbers.dot","text":"CliffordNumbers.dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the dot product of x and y.\n\nFor basis blades A of grade m and B of grade n, the dot product is equal to the left contraction when m >= n and is equal to the right contraction (up to sign) when n >= m.\n\nWhy is this function not exported?\n\nThe LinearAlgebra package also defines a dot function, and if both packages are used together, this will cause a name conflict if CliffordNumbers.dot is exported. In the future, we will try to resolve this without requiring a LinearAlgebra dependency.\n\nAdditionally, there is reason to prefer the use of the left and right contractions over the dot product because the contractions require fewer exceptions in their definitions and properties.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.hestenes_dot","page":"Math","title":"CliffordNumbers.hestenes_dot","text":"CliffordNumbers.hestenes_dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nReturns the Hestenes product: this is equal to the dot product given by dot(x, y) but is equal to to zero when either x or y is a scalar.\n\nWhy is this function not exported?\n\nIn almost every case, left and right contractions are preferable - the dot product and the Hestenes product are less regular in algebraic sense, and the conditionals present in its implementation slow it down relative to contractions. It is provided for the sake of exact reproducibility of results which use it.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.commutator","page":"Math","title":"CliffordNumbers.commutator","text":"×(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\ncommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the commutator (or antisymmetric) product, equal to 1//2 * (x*y - y*x).\n\nNote that the commutator product, in general, is not equal to the wedge product, which may be invoked with the wedge function or the ∧ operator.\n\nType promotion\n\nBecause of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.anticommutator","page":"Math","title":"CliffordNumbers.anticommutator","text":"⨰(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\nanticommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the anticommutator (or symmetric) product, equal to 1//2 * (x*y + y*x).\n\nNote that the dot product, in general, is not equal to the anticommutator product, which may be invoked with dot. In some cases, the preferred operators might be the left and right contractions, which use infix operators ⨼ and ⨽ respectively.\n\nType promotion\n\nBecause of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Scalar-products-and-normalization","page":"Math","title":"Scalar products and normalization","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"CliffordNumbers.scalar_product\nBase.abs2(::AbstractCliffordNumber)\nBase.abs(::AbstractCliffordNumber)\nCliffordNumbers.normalize","category":"page"},{"location":"api/math.html#CliffordNumbers.scalar_product","page":"Math","title":"CliffordNumbers.scalar_product","text":"scalar_product(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the scalar product of two Clifford numbers with quadratic form Q. The result is a Real or Complex number. This can be converted back to an AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Base.abs2-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.abs2","text":"abs2(x::AbstractCliffordNumber{Q,T}) -> T\n\nCalculates the squared norm of x, equal to scalar_product(x, x').\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Base.abs-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.abs","text":"abs2(x::AbstractCliffordNumber{Q,T}) -> Union{Real,Complex}\n\nCalculates the norm of x, equal to sqrt(scalar_product(x, x')).\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#CliffordNumbers.normalize","page":"Math","title":"CliffordNumbers.normalize","text":"normalize(x::AbstractCliffordNumber{Q}) -> AbstractCliffordNumber{Q}\n\nNormalizes x so that its magnitude (as calculated by abs2(x)) is 1.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Exponentiation","page":"Math","title":"Exponentiation","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.exp(::AbstractCliffordNumber)\nCliffordNumbers.exppi\nCliffordNumbers.exptau","category":"page"},{"location":"api/math.html#Base.exp-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.exp","text":"exp(x::AbstractCliffordNumber{Q})\n\nReturns the natural exponential of a Clifford number.\n\nFor special cases where m squares to a scalar, the following shortcuts can be used to calculate exp(x):\n\nWhen x^2 < 0: exp(x) === cos(abs(x)) + x * sin(abs(x)) / abs(x)\nWhen x^2 > 0: exp(x) === cosh(abs(x)) + x * sinh(abs(x)) / abs(x)\nWhen x^2 == 0: exp(x) == 1 + x\n\nSee also: exppi, exptau.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#CliffordNumbers.exppi","page":"Math","title":"CliffordNumbers.exppi","text":"exppi(x::AbstractCliffordNumber)\n\nReturns the natural exponential of π * x with greater accuracy than exp(π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).\n\nSee also: exp, exptau.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.exptau","page":"Math","title":"CliffordNumbers.exptau","text":"exptau(x::AbstractCliffordNumber)\n\nReturns the natural exponential of 2π * x with greater accuracy than exp(2π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).\n\nSee also: exp, exppi.\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#Metric-signatures","page":"Metric signatures","title":"Metric signatures","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics","page":"Metric signatures","title":"CliffordNumbers.Metrics","text":"CliffordNumbers.Metrics\n\nContains tools for working with metric signatures associated with AbstractCliffordNumber subtypes and instances. This includes the Metrics.AbstractSignature type and its subtypes.\n\n\n\n\n\n","category":"module"},{"location":"api/metrics.html#Signature-types","page":"Metric signatures","title":"Signature types","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics.AbstractSignature\nCliffordNumbers.Metrics.Signature\nCliffordNumbers.Metrics.VGA\nCliffordNumbers.Metrics.PGA\nCliffordNumbers.Metrics.CGA\nCliffordNumbers.Metrics.LGA\nCliffordNumbers.Metrics.LGAEast\nCliffordNumbers.Metrics.LGAWest\nCliffordNumbers.Metrics.Exterior","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.AbstractSignature","page":"Metric signatures","title":"CliffordNumbers.Metrics.AbstractSignature","text":"Metrics.AbstractSignature <: AbstractVector{Int8}\n\nSupertype for all data types that represent metric signatures. This includes the generic Signature type as well as other specialized types.\n\nMetric signatures can be interpreted as the signs of the diagonal elements of the metric tensor. All elements are either -1, 0, or 1. All nondegenerate Clifford algebras admit an orthonormal basis corresponding to the metric.\n\nAside from the generic Metrics.Signature subtype, types for commonly used algebras are available, including Metrics.VGA, Metrics.PGA, and Metrics.CGA. Custom signatures with firmer bounds on their behavior can be implemented by subtyping this type.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.Signature","page":"Metric signatures","title":"CliffordNumbers.Metrics.Signature","text":"Metrics.Signature <: Metrics.AbstractSignature\nMetrics.Signature(\n dimensions::Integer,\n negative::UInt,\n degenerate::UInt,\n [first_index::Integer = 1]\n)\n\nContains information about the metric associated with a Clifford algebra or Clifford number. This type is constructed to be as generic as possible; other subtypes of Metrics.AbstractSignature may provide firmer guarantees on behavior, such as VGA.\n\nThe number which the dimensions square to is stored in a pair of UInt fields. The negative field consists of 1 bits for dimensions that square to a negative number, and 0 bits for those squaring to a positive number, matching the convention of sign bits in signed numbers.\n\nThe degenerate field consists of 1 bits for degenerate dimensions (dimensions that square to zero) and 0 bits for nondegenerate dimensions.\n\nThe numerical index of the first basis vector is first_index, which defaults to 1. Some algebras conventionally use 0 as the first index, such as projective geometric algebras and Lorentzian geometric algebras, and in some cases it may be useful to start with a negative index if there are a larger number of modeling dimensions.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA","text":"VGA <: Metrics.AbstractSignature\n\nRepresents the signature associated with a vanilla geometric algebra (VGA), a positive-definite geometric algebra which models space without any projective dimensions.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA","text":"PGA <: Metrics.AbstractSignature\n\nRepresents the signature associated with a PGA (projective geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one degenerate (zero-squaring) dimension represented by e₀. This degenerate dimension corresponds with the n∞ null vector in CGA (conformal geometric algebra).\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA","text":"CGA <: Metrics.AbstractSignature\n\nRepresents the signature of a CGA (conformal geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one positive-squaring dimension and one negative-squaring dimension.\n\nThere are two common choices of vector basis for the extra dimensions added when working with CGA. The most straightforward one is e₊ and e₋, which square to +1 and -1, respectively, and this is what is used internally, with the negative-squaring dimension being the first one.\n\nHowever, there is another commonly used basis: define null vectors n₀ = (e₋ - e₊)/2 and n∞ = e₋ - e₊, which represent the origin point and the point at infinity, respectively. n∞ corresponds to e₀ in PGA (projective geometric algebra).\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGA","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGAEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGAEast","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGAWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGAWest","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.Exterior","page":"Metric signatures","title":"CliffordNumbers.Metrics.Exterior","text":"Exterior <: Metrics.AbstractSignature\n\nRepresents a signature corresponding to an exterior algebra. In an exterior algebra, all 1-blades square to 0, and the geometric product is equivalent ot the wedge product.\n\nUnlike VGA, PGA, CGA, and LGA, the first index is not assumed when constructing this object, and can be manually specified. If it is not specified, it defaults to 1.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#Aliases-for-common-signatures","page":"Metric signatures","title":"Aliases for common signatures","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics.VGA2D\nCliffordNumbers.Metrics.VGA3D\nCliffordNumbers.Metrics.PGA2D\nCliffordNumbers.Metrics.PGA3D\nCliffordNumbers.Metrics.CGA2D\nCliffordNumbers.Metrics.CGA3D\nCliffordNumbers.Metrics.STAEast\nCliffordNumbers.Metrics.STAWest\nCliffordNumbers.Metrics.STA\nCliffordNumbers.Metrics.STAPEast\nCliffordNumbers.Metrics.STAPWest\nCliffordNumbers.Metrics.STAP","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA2D","text":"VGA2D (alias for VGA(2))\n\nThe algebra of 2D space. The even subalgebra of this algebra is isomorphic to ℂ, the complex numbers.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA3D","text":"VGA3D (alias for VGA(3))\nconst APS = VGA3D\n\nThe algebra of physical space, a 3D VGA which is commonly used (explicitly and implicitly) to model non-relativistic physics. It also serves as the subalgebra of both signature conventions of the spacetime algebra (available as STAEast and STAWest).\n\nThe even subalgebra of this algebra is isomorphic to ℍ, the quaternions.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA2D","text":"PGA2D (alias for PGA(2))\n\nThe projective geometric algebra of 2D space, which represents points and lines on the plane.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA3D","text":"PGA3D (alias for PGA(3))\n\nThe projective geometric algebra of 3D space, which represents points, lines, and planes in a 3D space.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA2D","text":"CGA2D (alias for CGA(2))\n\nThe conformal geometric algebra of 2D space, which represents points, lines, and circles on the plane. This algebra constitutes a framework for compass and straightedge constructions.\n\nThis algebra is isomorphic to STAEast, and this isomorphism is the reason why the default convention for spacetime algebras in this package is the West Coast (mostly negative) convention.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA3D","text":"CGA3D (alias for CGA(3))\n\nThe conformal geometric algebra of 3D space, which represents points, lines, and planes, as well as circles and spheres. This algebra constitutes a framework for extending compass and straightedge constructions to 3 dimensions.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAEast","text":"STAEast (alias for LGAEast(3))\n\nThe spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative), with the temporal dimension at index 0.\n\nThis convention is not the default STA convention, since this signature is identical to that of the 2D conformal geometric algebra.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAWest","text":"STAWest (alias for LGAWest(3))\nconst STA = STAWest\n\nThe spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive), with the temporal dimension at index 0.\n\nThis convention is the default STA convention in this package, since the signature for the East Coast convention can be interpreted as that of the 2D conformal geometric algebra.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STA","page":"Metric signatures","title":"CliffordNumbers.Metrics.STA","text":"STAWest (alias for LGAWest(3))\nconst STA = STAWest\n\nThe spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive), with the temporal dimension at index 0.\n\nThis convention is the default STA convention in this package, since the signature for the East Coast convention can be interpreted as that of the 2D conformal geometric algebra.\n\n\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAPEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAPEast","text":"STAPEast (alias for Signature(5, 0b00010, 0b00001, -1))\n\nThe projective spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAPWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAPWest","text":"STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))\nconst STAP = STAPWest\n\nThe projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAP","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAP","text":"STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))\nconst STAP = STAPWest\n\nThe projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#Associated-methods","page":"Metric signatures","title":"Associated methods","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.dimension\nCliffordNumbers.blade_count\nCliffordNumbers.grades\nCliffordNumbers.is_degenerate\nCliffordNumbers.is_positive_definite","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.dimension","page":"Metric signatures","title":"CliffordNumbers.Metrics.dimension","text":"dimension(s::AbstractSignature) -> Int8\n\nReturns the total number of dimensions associated with s. The default implementation returns signed(s.dimensions).\n\nThe total number of basis blades is equal to to the size of the power set of all basis vectors, and is equal to 2^dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.blade_count","page":"Metric signatures","title":"CliffordNumbers.Metrics.blade_count","text":"blade_count(s) -> Int\n\nReturns the total number of blades associated with metric signature s, which is equal to 2^dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.grades","page":"Metric signatures","title":"CliffordNumbers.Metrics.grades","text":"grades(s::AbstractSignature) -> UnitRange{Int8}\n\nReturns the total number of grades associated with s, which is equal to 0:dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.is_degenerate","page":"Metric signatures","title":"CliffordNumbers.Metrics.is_degenerate","text":"is_degenerate(s::AbstractSignature)\n\nReturns true if any basis elements of s square to 0.\n\nThis does not imply that no elements of the associated Clifford algebra square to 0.\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.is_positive_definite","page":"Metric signatures","title":"CliffordNumbers.Metrics.is_positive_definite","text":"is_positive_definite(s::AbstractSignature)\n\nReturns true if all basis 1-blades of s square to a positive value.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Grades-and-indices","page":"Indexing","title":"Grades and indices","text":"","category":"section"},{"location":"api/indexing.html#Grades","page":"Indexing","title":"Grades","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.nonzero_grades\nCliffordNumbers.has_grades_of","category":"page"},{"location":"api/indexing.html#CliffordNumbers.nonzero_grades","page":"Indexing","title":"CliffordNumbers.nonzero_grades","text":"nonzero_grades(::Type{<:AbstractCliffordNumber})\nnonzero_grades(::AbstractCliffordNumber)\n\nA function returning an indexable object representing all nonzero grades of a Clifford number representation.\n\nThis function is used to define the indexing of RepresentedGrades, and should be defined for any subtypes of AbstractCliffordNumber.\n\nExamples\n\njulia> CliffordNumbers.nonzero_grades(CliffordNumber{APS})\n0:3\n\njulia> CliffordNumbers.nonzero_grades(KVector{2,APS})\n2:2\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.has_grades_of","page":"Indexing","title":"CliffordNumbers.has_grades_of","text":"has_grades_of(S::Type{<:AbstractCliffordNumber}, T::Type{<:AbstractCliffordNumber}) -> Bool\nhas_grades_of(x::AbstractCliffordNumber, y::AbstractCliffordNumber) -> Bool\n\nReturns true if the grades represented in S are also represented in T; false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#BitIndex","page":"Indexing","title":"BitIndex","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.BitIndex\nCliffordNumbers.is_same_blade","category":"page"},{"location":"api/indexing.html#CliffordNumbers.BitIndex","page":"Indexing","title":"CliffordNumbers.BitIndex","text":"BitIndex{Q}\n\nA representation of an index corresponding to a basis blade of the geometric algebra with quadratic form Q.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.is_same_blade","page":"Indexing","title":"CliffordNumbers.is_same_blade","text":"CliffordNumbers.is_same_blade(a::BitIndex{Q}, b::BitIndex{Q})\n\nChecks if a and b perform identical indexing up to sign.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Special-indices","page":"Indexing","title":"Special indices","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.scalar_index\nCliffordNumbers.pseudoscalar_index","category":"page"},{"location":"api/indexing.html#CliffordNumbers.scalar_index","page":"Indexing","title":"CliffordNumbers.scalar_index","text":"scalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}\n\nConstructs the BitIndex used to obtain the scalar (grade zero) portion of x.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.pseudoscalar_index","page":"Indexing","title":"CliffordNumbers.pseudoscalar_index","text":"pseudoscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}\n\nConstructs the BitIndex used to obtain the pseudoscalar (highest grade) portion of x.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Tools-for-implementing-mathematical-operations","page":"Indexing","title":"Tools for implementing mathematical operations","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"Base.reverse(::BitIndex)\nCliffordNumbers.grade_involution(::BitIndex)\nBase.conj(::BitIndex)","category":"page"},{"location":"api/indexing.html#Base.reverse-Tuple{BitIndex}","page":"Indexing","title":"Base.reverse","text":"adjoint(i::BitIndex) = reverse(i::BitIndex) = i' -> BitIndex\nadjoint(x::AbstractCliffordNumber) = reverse(x::AbstractCliffordNumber) = x' -> typeof(x)\n\nPerforms the reverse operation on the basis blade indexed by b or the Clifford number x. The sign of the reverse depends on the grade of the basis blade g, and is positive for g % 4 in 0:1 and negative for g % 4 in 2:3.\n\n\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.grade_involution-Tuple{BitIndex}","page":"Indexing","title":"CliffordNumbers.grade_involution","text":"grade_involution(i::BitIndex) -> BitIndex\ngrade_involution(x::AbstractCliffordNumber) -> typeof(x)\n\nCalculates the grade involution of the basis blade indexed by b or the Clifford number x. This effectively reflects all of the basis vectors of the space along their own mirror operation, which makes elements of odd grade flip sign.\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#Base.conj-Tuple{BitIndex}","page":"Indexing","title":"Base.conj","text":"conj(i::BitIndex) -> BitIndex\nconj(x::AbstractCliffordNumber) -> typeof(x)\n\nCalculates the Clifford conjugate of the basis blade indexed by b or the Clifford number x. This is equal to grade_involution(reverse(x)).\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.grade(::BitIndex)\nCliffordNumbers.sign_of_square\nCliffordNumbers.signbit_of_square\nCliffordNumbers.nondegenerate_square\nCliffordNumbers.sign_of_mult\nCliffordNumbers.signbit_of_mult\nCliffordNumbers.nondegenerate_mult\nBase.:*(::T, ::T) where T<:BitIndex\nCliffordNumbers.has_wedge","category":"page"},{"location":"api/indexing.html#CliffordNumbers.grade-Tuple{BitIndex}","page":"Indexing","title":"CliffordNumbers.grade","text":"grade(i::BitIndex) -> Int\n\nReturns the grade of the basis blade represented by i, which ranges from 0 to the dimension of the space represented by i (equal to dimension(signature(i))).\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.sign_of_square","page":"Indexing","title":"CliffordNumbers.sign_of_square","text":"CliffordNumbers.sign_of_square(b::BitIndex) -> Int8\n\nReturns the sign associated with squaring the basis blade indexed by b using an Int8 as proxy: positive signs return Int8(1), negative signs return Int8(-1), and zeros from degenerate components return Int8(0).\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.signbit_of_square","page":"Indexing","title":"CliffordNumbers.signbit_of_square","text":"CliffordNumbers.signbit_of_square(b::BitIndex) -> Bool\n\nReturns the signbit associated with squaring the basis blade indexed by b.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.nondegenerate_square","page":"Indexing","title":"CliffordNumbers.nondegenerate_square","text":"CliffordNumbers.nondegenerate_square(b::BitIndex) -> Bool\n\nReturns false if squaring the basis blade b is zero due to a degenerate component, true otherwise. For a nondegenerate metric, this is always true.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.sign_of_mult","page":"Indexing","title":"CliffordNumbers.sign_of_mult","text":"CliffordNumbers.sign_of_mult(a::T, b::T) where T<:BitIndex -> Int8\n\nReturns an Int8 that carries the sign associated with the multiplication of two basis blades of Clifford/geometric algebras of the same quadratic form.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.signbit_of_mult","page":"Indexing","title":"CliffordNumbers.signbit_of_mult","text":"CliffordNumbers.signbit_of_mult(a::Integer, [b::Integer]) -> Bool\nCliffordNumbers.signbit_of_mult(a::BitIndex, [b::BitIndex]) -> Bool\n\nCalculates the sign bit associated with multiplying basis elements indexed with bit indices supplied as either integers or BitIndex instances. The sign bit flips when the order of a and b are reversed, unless a === b. \n\nAs with Base.signbit(), true represents a negative sign and false a positive sign. However, in degenerate metrics (such as those of projective geometric algebras) the sign bit may be irrelevant as the multiplication of those basis blades would result in zero.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.nondegenerate_mult","page":"Indexing","title":"CliffordNumbers.nondegenerate_mult","text":"CliffordNumbers.nondegenerate_mult(a::T, b::T) where T<:BitIndex -> Bool\n\nReturns false if the product of a and b is zero due to the squaring of a degenerate component, true otherwise. This function always returns true if R === 0.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Base.:*-Union{Tuple{T}, Tuple{T, T}} where T<:BitIndex","page":"Indexing","title":"Base.:*","text":"*(a::BitIndex{Q}, b::BitIndex{Q}) -> BitIndex{Q}\n\nReturns the BitIndex corresponding to the basis blade resulting from the geometric product of the basis blades indexed by a and b.\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.has_wedge","page":"Indexing","title":"CliffordNumbers.has_wedge","text":"CliffordNumbers.has_wedge(a::BitIndex{Q}, b::BitIndex{Q}, [c::BitIndex{Q}...]) -> Bool\n\nReturns true if the basis blades indexed by a, b, or any other blades c... have a nonzero wedge product; false otherwise. This is determined by comparing all bits of the arguments (except the sign bit) to identify any matching basis blades using bitwise AND.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#BitIndices-and-related-types","page":"Indexing","title":"BitIndices and related types","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.AbstractBitIndices\nCliffordNumbers.BitIndices\nCliffordNumbers.TransformedBitIndices","category":"page"},{"location":"api/indexing.html#CliffordNumbers.AbstractBitIndices","page":"Indexing","title":"CliffordNumbers.AbstractBitIndices","text":"AbstractBitIndices{Q,C<:AbstractCliffordNumber{Q}} <: AbstractVector{BitIndex{Q}}\n\nSupertype for vectors containing all valid BitIndex{Q} objects for the basis elements represented by C.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.BitIndices","page":"Indexing","title":"CliffordNumbers.BitIndices","text":"BitIndices{Q,C<:AbstractCliffordNumber{Q,<:Any}} <: AbstractVector{BitIndex{Q}}\n\nRepresents a range of valid BitIndex objects for the nonzero components of a given multivector of algebra Q.\n\nFor a generic AbstractCliffordNumber{Q}, this returns BitIndices{Q,CliffordNumber{Q}}, which contains all possible indices for a multivector associated with the algebra parameter Q. For sparser representations, such as KVector{K,Q}, the object only contains the indices of the nonzero elements of the multivector.\n\nConstruction\n\nBitIndices can be constructed by calling the type constructor with the Clifford number or its type. This will automatically strip some type parameters so that identical BitIndices objects are constructed regardless of the scalar type.\n\nFor this reason, you should not use BitIndices{Q,C}(); instead use BitIndices(C).\n\nIndexing\n\nBitIndices always uses one-based indexing like most Julia arrays. Although it is more natural in the dense case to use zero-based indexing, as the basis blades are naturally encoded in the indices for the dense representation of CliffordNumber, one-based indexing is used by the tuples which contain the data associated with this package's implementations of Clifford numbers.\n\nBroadcasting\n\nBecause BitIndices(x) only lazily references the indices of x, we define a new type, TransformedBitIndices, which allows for a function f to be lazily associated with the BitIndices object, and this type is constructed when a f.(BitIndices(x)) is called.\n\nInterfaces for new subtypes of AbstractCliffordNumber\n\nWhen defining the behavior of BitIndices for new subtypes T of AbstractCliffordNumber, Base.getindex(::BitIndices{Q,T}, i::Integer) should be defined so that all indices of T that are not constrained to be zero are returned.\n\nYou should also define CliffordNumbers.bitindices_type(::Type{T}) so that type parameters that do not affect the construction of the BitIndices object are stripped.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.TransformedBitIndices","page":"Indexing","title":"CliffordNumbers.TransformedBitIndices","text":"TransformedBitIndices{Q,C,F} <: AbstractBitIndices{Q,C}\n\nLazy representation of BitIndices{Q,C} with some function of type f applied to each element. These objects can be used to perform common operations which act on basis blades or grades, such as the reverse or grade involution.\n\n\n\n\n\n","category":"type"},{"location":"api/internal.html#Internal-methods","page":"Internals","title":"Internal methods","text":"","category":"section"},{"location":"api/internal.html#Hamming-weights-and-related-operations","page":"Internals","title":"Hamming weights and related operations","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.Hamming\nCliffordNumbers.Hamming.isevil\nCliffordNumbers.Hamming.isodious\nCliffordNumbers.Hamming.number_of_parity\nCliffordNumbers.Hamming.evil_number\nCliffordNumbers.Hamming.odious_number\nCliffordNumbers.Hamming.next_of_hamming_weight\nCliffordNumbers.Hamming.hamming_number","category":"page"},{"location":"api/internal.html#CliffordNumbers.Hamming","page":"Internals","title":"CliffordNumbers.Hamming","text":"CliffordNumbers.Hamming\n\nA submodule containing methods for working with the sum of binary digits contained in an integer. This is essential to representing the basis blades of a geometric algebra, as the presence or absence of each possible basis vector in a blade can be represented by a binary 1 or 0. Operations that require knowledge of the grade of a basis blade will need the operations in this submodule.\n\n\n\n\n\n","category":"module"},{"location":"api/internal.html#CliffordNumbers.Hamming.isevil","page":"Internals","title":"CliffordNumbers.Hamming.isevil","text":"CliffordNumbers.Hamming.isevil(i::Integer) -> Bool\n\nDetermines whether a number is evil, meaning that its Hamming weight (sum of its binary digits) is even.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.isodious","page":"Internals","title":"CliffordNumbers.Hamming.isodious","text":"CliffordNumbers.Hamming.isodious(i::Integer) -> Bool\n\nDetermines whether a number is odious, meaning that its Hamming weight (sum of its binary digits) is odd.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.number_of_parity","page":"Internals","title":"CliffordNumbers.Hamming.number_of_parity","text":"CliffordNumbers.Hamming.number_of_parity(n::Integer, modulo::Bool)\n\nReturns the nth number whose Hamming weight is even (for modulo = false) or odd (for modulo = true).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.evil_number","page":"Internals","title":"CliffordNumbers.Hamming.evil_number","text":"CliffordNumbers.Hamming.evil_number(n::Integer)\n\nReturns the nth evil number, with the first evil number (n == 1) defined to be 0.\n\nEvil numbers are numbers which have an even Hamming weight (sum of its binary digits).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.odious_number","page":"Internals","title":"CliffordNumbers.Hamming.odious_number","text":"CliffordNumbers.Hamming.odious_number(n::Integer)\n\nReturns the nth odious number, with the first odious number (n == 1) defined to be 1.\n\nOdious numbers are numbers which have an odd Hamming weight (sum of its binary digits).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.next_of_hamming_weight","page":"Internals","title":"CliffordNumbers.Hamming.next_of_hamming_weight","text":"CliffordNumbers.Hamming.next_of_hamming_weight(n::Integer)\n\nReturns the next integer with the same Hamming weight as n.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.hamming_number","page":"Internals","title":"CliffordNumbers.Hamming.hamming_number","text":"CliffordNumbers.Hamming.hamming_number(w::Integer, n::Integer)\n\nGets the nth number with Hamming weight w. The first number with this Hamming weight (n = 1) is 2^w - 1.\n\nExample\n\njulia> CliffordNumbers.hamming_number(3, 2)\n11\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Indexing","page":"Internals","title":"Indexing","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.signmask\nCliffordNumbers._sort_with_parity!\nCliffordNumbers.bitindices_type","category":"page"},{"location":"api/internal.html#CliffordNumbers.signmask","page":"Internals","title":"CliffordNumbers.signmask","text":"CliffordNumbers.signmask([T::Type{<:Integer} = UInt], [signbit::Bool = true]) -> T\n\nGenerates a signmask, or a string of bits where the only 1 bit is the sign bit. If signbit is set to false, this returns zero (or whatever value is represented by all bits being 0).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers._sort_with_parity!","page":"Internals","title":"CliffordNumbers._sort_with_parity!","text":"CliffordNumbers._sort_with_parity!(v::AbstractVector{<:Real}) -> Tuple{typeof(v),Bool}\n\nPerforms a parity-tracking insertion sort of v, which modifies v in place. The function returns a tuple containing v and the parity, which is true for an odd permutation and false for an even permutation. This is implemented with a modified insertion sort algorithm.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.bitindices_type","page":"Internals","title":"CliffordNumbers.bitindices_type","text":"CliffordNumbers.bitindices_type(C::Type{<:AbstractCliffordNumber{Q,T}})\n\nRemoves extraneous type parameters from C, converting it to the least parameterized type that can be used to parameterize an AbstractBitIndices{Q,C} object. This is to avoid issues with the proliferation of type parameters that would construct identical BitIndices objects otherwise: for instance, BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Float32,4}}() and BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Int}}() have identical elements, and are equal when compared with ==, but are not the same object.\n\nFor types defined in this package, this strips the scalar type parameter T and any length parameters present.\n\nExamples\n\njulia> CliffordNumbers.bitindices_type(CliffordNumber{VGA(3),Float32,8})\nCliffordNumber{VGA(3)}\n\njulia> CliffordNumbers.bitindices_type(KVector{2,STA,Bool})\nKVector{2,STA}\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Construction","page":"Internals","title":"Construction","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.zero_tuple\nCliffordNumbers.check_element_count","category":"page"},{"location":"api/internal.html#CliffordNumbers.zero_tuple","page":"Internals","title":"CliffordNumbers.zero_tuple","text":"CliffordNumbers.zero_tuple(::Type{T}, ::Val{L}) -> NTuple{L,T}\n\nGenerates a Tuple of length L with all elements being zero(T).\n\n\n\n\n\nCliffordNumbers.zero_tuple(::Type{C<:AbstractCliffordNumber})\n -> NTuple{length(C),scalar_type(C)}\n\nGenerates a Tuple that can be used to construct zero(C).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.check_element_count","page":"Internals","title":"CliffordNumbers.check_element_count","text":"CliffordNumbers.check_element_count(sz, [L], data)\n\nEnsures that the number of elements in data is the same as the result of f(Q), where f is a function that generates the expected number of elements for the type. This function is used in the inner constructors of subtypes of AbstractCliffordNumber{Q} to ensure that the input has the correct length.\n\nIf provided, the length type parameter L can be included as an argument, and it will be checked for type (must be an Int) and value (must be equal to sz).\n\nThis function returns nothing, but throws an AssertionError for failed checks.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Multiplication-kernels","page":"Internals","title":"Multiplication kernels","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.mul\nCliffordNumbers.GradeFilter\nCliffordNumbers.nondegenerate_mask\nCliffordNumbers.mul_mask\nCliffordNumbers.mul_signs\nCliffordNumbers.bitindex_shuffle\nCliffordNumbers.widen_grade_for_mul","category":"page"},{"location":"api/internal.html#CliffordNumbers.mul","page":"Internals","title":"CliffordNumbers.mul","text":"CliffordNumbers.mul(\n x::AbstractCliffordNumber{Q},\n y::AbstractCliffordNumber{Q},\n [F::GradeFilter = GradeFilter{:*}()]\n)\n\nA fast geometric product implementation using generated functions for specific cases, and generic methods which either convert the arguments or fall back to other methods.\n\nThe arguments to this function should all agree in scalar type T. The * function, which exposes the fast geometric product implementation, promotes the scalar types of the arguments before utilizing this kernel. The scalar multiplication operations are implemented using muladd, allowing for hardware fma operations to be used when available.\n\nThe GradeFilter F allows for some blade multiplications to be excluded if they meet certain criteria. This is useful for implementing products besides the geometric product, such as the wedge product, which excludes multiplications between blades with shared vectors. Without a filter, this kernel just returns the geometric product.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.GradeFilter","page":"Internals","title":"CliffordNumbers.GradeFilter","text":"CliffordNumbers.GradeFilter{S}\n\nA type that can be used to filter certain products of blades in a geometric product multiplication. The type parameter S must be a Symbol. The single instance of GradeFilter{S} is a callable object which implements a function that takes two or more BitIndex{Q} objects a and b and returns false if the product of the blades indexed is zero.\n\nTo implement a grade filter for a product function f, define the following method: (::GradeFilter{:f})(::BitIndex{Q}, ::BitIndex{Q}) # Or if the definition allows for more arguments (::GradeFilter{:f})(::BitIndex{Q}...) where Q\n\n\n\n\n\n","category":"type"},{"location":"api/internal.html#CliffordNumbers.nondegenerate_mask","page":"Internals","title":"CliffordNumbers.nondegenerate_mask","text":"CliffordNumbers.nondegenerate_mask(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})\n\nConstructs a Boolean mask which is false for any multiplication that squares a degenerate blade; true otherwise.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.mul_mask","page":"Internals","title":"CliffordNumbers.mul_mask","text":"CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})\nCliffordNumbers.mul_mask(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})\n\nCliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})\nCliffordNumbers.mul_mask(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})\n\nGenerates a NTuple{L,Bool} which is true whenever the multiplication of the blade indexed by a and blades indexed by B is nonzero. false is returned if the grades multiply to zero due to the squaring of a degenerate component, or if they are filtered by F.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.mul_signs","page":"Internals","title":"CliffordNumbers.mul_signs","text":"CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})\nCliffordNumbers.mul_signs(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})\n\nCliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})\nCliffordNumbers.mul_signs(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})\n\nGenerates an NTuple{L,Int8} which represents the sign associated with the multiplication needed to calculate components of a multiplication result.\n\nThis is equivalent to sign.(B) unless F === CliffordNumbers.GradeFilter{:dot}().\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.bitindex_shuffle","page":"Internals","title":"CliffordNumbers.bitindex_shuffle","text":"CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})\nCliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::BitIndices{Q})\n\nCliffordNumbers.bitindex_shuffle(B::NTuple{L,BitIndex{Q}}, a::BitIndex{Q})\nCliffordNumbers.bitindex_shuffle(B::BitIndices{Q}, a::BitIndex{Q})\n\nPerforms the multiplication -a * b for each element of B for the above ordering, or -b * a for the below ordering, generating a reordered NTuple of BitIndex{Q} objects suitable for implementing a geometric product.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Taylor-series-exponential","page":"Internals","title":"Taylor series exponential","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.exp_taylor","category":"page"},{"location":"api/internal.html#CliffordNumbers.exp_taylor","page":"Internals","title":"CliffordNumbers.exp_taylor","text":"CliffordNumbers.exp_taylor(x::AbstractCliffordNumber, order = Val(16))\n\nCalculates the exponential of x using a Taylor expansion up to the specified order. In most cases, 12 is as sufficient number.\n\nNotes\n\n16 iterations is currently used because the number of loop iterations is not currently a performance bottleneck.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Return-types-for-operations","page":"Internals","title":"Return types for operations","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.product_return_type\nCliffordNumbers.exponential_type","category":"page"},{"location":"api/internal.html#CliffordNumbers.product_return_type","page":"Internals","title":"CliffordNumbers.product_return_type","text":"CliffordNumbers.product_return_type(::Type{X}, ::Type{Y}, [::GradeFilter{S}])\n\nReturns a suitable type for representing the product of Clifford numbers of types X and Y. The GradeFilter{S} argument allows for the return type to be changed depending on the type of product. Without specialization on S, a type suitable for the geometric product is returned.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.exponential_type","page":"Internals","title":"CliffordNumbers.exponential_type","text":"CliffordNumbers.exponential_type(::Type{<:AbstractCliffordNumber})\nCliffordNumbers.exponential_type(x::AbstractCliffordNumber)\n\nReturns the type expected when exponentiating a Clifford number. This is an EvenCliffordNumber if the nonzero grades of the input are even, a CliffordNumber otherwise.\n\n\n\n\n\n","category":"function"},{"location":"numeric.html#Numeric-types","page":"Clifford number types","title":"Numeric types","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This package exports a variety of types that represents elements of Clifford algebras.","category":"page"},{"location":"numeric.html#AbstractCliffordNumber{Q,T}-and-subtypes","page":"Clifford number types","title":"AbstractCliffordNumber{Q,T} and subtypes","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The AbstractCliffordNumber{Q,T} type is the supertype for all implmentations of Clifford numbers. Q is a QuadraticForm, which describes the number of dimensions with positive, negative, and zero square, and T is a Union{Real,Complex} type of the coefficients.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"note: Future `StaticCliffordNumber{Q,T,L}` type\nWe may introduce a new abstract type, StaticCliffordNumber{Q,T,L}, for static implementations, like all of the ones provided by this package. These should be implemented as fixed length data structures (ideally an NTuple{L,T}).","category":"page"},{"location":"numeric.html#CliffordNumber{Q,T,L}:-full-grade-Clifford-numbers","page":"Clifford number types","title":"CliffordNumber{Q,T,L}: full grade Clifford numbers","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q,T,L} is the largest possible representation of a Clifford number, and it explicitly includes the coefficients for all 2^dimension(Q) basis blades.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"While this type is useful if working with objects that mix even and odd grades (for instance, projectors or left minimal ideals), it is often more efficient to work with a smaller type, like the ones described below.","category":"page"},{"location":"numeric.html#EvenCliffordNumber{Q,T,L}-and-OddCliffordNumber{Q,T,L}:-even-and-odd-graded-elements","page":"Clifford number types","title":"EvenCliffordNumber{Q,T,L} and OddCliffordNumber{Q,T,L}: even and odd graded elements","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"These types represent Clifford numbers of exclusively even or odd grade, respectively. These are the workhorses of geometric algebra, as they are produced through products of even or odd numbers of 1-blades. In the majority of cases, you can rely entirely on these types.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Internally, these are the same type: they alias CliffordNumbers.Z2CliffordNumber{P,Q,T,L}, where P is a Boolean parameter which is false for EvenCliffordNumber and true for OddCliffordNumber.","category":"page"},{"location":"numeric.html#KVector{K,Q,T,L}:-elements-of-homogeneous-grade","page":"Clifford number types","title":"KVector{K,Q,T,L}: elements of homogeneous grade","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This type represents a k-vector, or a Clifford number of homogeneous grade, with the parameter K indicating the grade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"It should be noted that in general, this type is not as efficient as EvenCliffordNumber, OddCliffordNumber, or CliffordNumber when calculating products (though this may change in the future). Use this type if your primary operations are addition, or if you need compact storage.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"However, there is one exception to this: KVector{0}, which represents a scalar. This type has been optimized so that operations with it are simply converted to scalar operations. Many operations on Clifford numbers that return scalars will return a KVector{0} to preserve the metric signature and other semantics associated with AbstractCliffordNumber.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"warning: Warning\nIt is important to note that k-vectors are not k-blades (the wedge product of k 1-vectors) or k-versors (the geometric product of k 1-vectors). In dimensions up to 3, all k-vectors are also k-blades, but this is not generally true: as a counterexample, e_1 e_2 + e_3 e_4 is not representable as a k-blade. However, all k-blades are k-vectors. k-versors usually consist of more than one grade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"note: Note\nIn the future, we may consider adding a DualKVector or PseudoKVector type to more easily represent pseudoscalars, pseudovectors, and related objects.","category":"page"},{"location":"numeric.html#Promotion-and-widening","page":"Clifford number types","title":"Promotion and widening","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This package provides a robust promotion system for converting Clifford numbers and scalars to common types before performing common numeric operations.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"When promoting the types of Clifford numbers, there are two different types of promotions that can occur: scalar promotions, which promote all the scalar types of the arguments to a common scalar type, and grade promotions, which promote all the arguments to types which have a common set of grades. This package provides the scalar_promote function that allows for the scalar types of each argument to be promoted to a common type. Promote rules have been defined so that promote performs a scalar promotion and a grade promotion. No function currently promotes only the grades of the inputs.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The widen function in Julia Base widens an Number type to a type that can represent the result of addition or subtraction with the the input type without overflowing or losing precision. This functionality is passed through to Clifford numbers, but it only affects the scalar type, not the grades.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The widen_grade function performs an equivalent operation with the grades of a Clifford number, converting KVector to EvenCliffordNumber or OddCliffordNumber depending on the grade, and converting those to CliffordNumber. New AbstractCliffordNumber subtypes will widen directly to CliffordNumber by default, and this should be overridden for new types so that it widens to the smallest wider type.","category":"page"},{"location":"numeric.html#Construction-and-conversion","page":"Clifford number types","title":"Construction and conversion","text":"","category":"section"},{"location":"numeric.html#From-the-constructors","page":"Clifford number types","title":"From the constructors","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The constructors of all AbstractCliffordNumber subtypes accept Tuple or Vararg arguments. In interactive use, you will probably use the latter. When defining a new type, you only need to define the (::Type{T})(::Tuple) constructors, as the Vararg constructors are automatically provided.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Some type parameters may be omitted in constructors, and the differences in behavior between these constructors is given below, using CliffordNumber as an example:","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q,T}(x...) converts all arguments x to type T.\nCliffordNumber{Q}(x...) promotes all arguments x to a common type T, so it is equivalent to CliffordNumber{Q,promote_type(typeof.(x)...)}(x).\nCliffordNumber(x...) is not a valid constructor, as an algebra must be specified.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"For types that include grade information, such as KVector, this information must be included to produce a valid constructor.","category":"page"},{"location":"numeric.html#Indices","page":"Clifford number types","title":"Indices","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"In most literature, the components of multivectors are listed in grade order. However, this ordering is not used here: instead, the natural binary ordering of blades is used.For a computer, each basis blade of an n-dimensional algebra can be represented with an n-bit integer: each of its binary digits correspond to the presence or absence of a vector composing the blade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"For a concrete example, the coefficients of a CliffordNumber{VGA(3)} are ordered like so:","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"left(1 e_1 e_2 e_1 e_2 e_3 e_1 e_3 e_2 e_3 e_1 e_2 e_3right)","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Note how e_1 e_2 precedes e_3 here, but also note how the first four elements and the second four elements only differ by the presence of an e_3 factor.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber and its backing Tuple can be indexed straightforwardly with this relationship. The basis blade order of all AbstractCliffordNumber instances are identical, with smaller types like KVector{2,VGA(3)} skipping over all basis blades not of grade 2 in the list above.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"warning: Warning\nMany resources do not use a lexicographic order for the bivectors of the algebra of physical space or the spacetime algebra, opting for cyclic permutations so that e_3 e_1 is preferred over e_1 e_3. It's a good idea to check the convention before construction so you can include any necessary negative signs.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"As a workaround for the possibly unintuitive ordering of coefficients, you can also use sums of KVector instances: the sum will automatically promote to EvenCliffordNumber, OddCliffordNumber, or CliffordNumber as needed to represent all grades.","category":"page"},{"location":"numeric.html#Scalars","page":"Clifford number types","title":"Scalars","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q} and EvenCliffordNumber{Q} also accept a single scalar argument, and this constructs an object with all non-scalar blade coefficients being zero. By definition, KVector{0} does the same, and is the most efficient representation of a scalar associated with an algebra.","category":"page"},{"location":"numeric.html#From-other-Clifford-numbers","page":"Clifford number types","title":"From other Clifford numbers","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Clifford numbers can be constructed from other CliffordNumbers. This implicitly performs a grade projection operation, so this construction will always succeed, even if some of the basis blades of the input are lost. By contrast, conversion will throw an InexactError if the result does not contain all of the basis blades of the result.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"julia> test = CliffordNumber{VGA(3)}(1, 2, 3, 4, 5, 6, 7, 8)\n8-element CliffordNumber{VGA(3), Int64}:\n1 + 2σ₁ + 3σ₂ + 5σ₃ + 4σ₁σ₂ + 6σ₁σ₃ + 7σ₂σ₃ + 8σ₁σ₂σ₃\n\njulia> EvenCliffordNumber(test)\n4-element EvenCliffordNumber{VGA(3), Int64}:\n1 + 4σ₁σ₂ + 6σ₁σ₃ + 7σ₂σ₃\n\njulia> convert(EvenCliffordNumber, test)\nERROR: InexactError: ...","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"danger: Danger\nThis is an extremely important point: construction of a Clifford number type with fewer grades than the input performs a grade projection operation without throwing an error. However, conversion will throw an error if the grades of the input value are not present in the input type.This is not how other subtypes of Number defined by Julia Base behave, as their conversion operations are generally defined to be identical to the constructor, and always throw the same error for a given pair of type and value.If converting an AbstractCliffordNumber to any other numeric type, construction and conversion behave identically, as expected.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Construction and conversion of Clifford numbers from other Clifford numbers the only time that the quadratic form type parameter can be omitted, as it can be inferred directly from the input. In the case of CliffordNumbers.Z2CliffordNumber, the parity type parameter can also be inferred from a KVector input.","category":"page"},{"location":"numeric.html#Scalar-conversion","page":"Clifford number types","title":"Scalar conversion","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"It may be desirable to convert the scalar type of a Clifford number without having to specify the full typename of the desired output type. The function scalar_convert(T, x) takes a type T<:Union{Real,Complex} and any Clifford number x and converts its scalar type to T. If x is a Real or Complex, it just converts x to an instance of T.","category":"page"},{"location":"indexing.html#Indexing","page":"Indexing","title":"Indexing","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Indexing is a critical operation in linear algebra: it would be difficult to imagine defining operations on vectors, matrices, and arrays without some way of determining the coefficient at a particular location in the object. Similarly, we often want to extract coefficients from multivectors to perform operations.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"However, the philosophy of this package – treating multivectors a number system on the same footing as that of complex numbers or quaternions – means that the AbstractCliffordNumber type foregoes array semantics. All AbstractCliffordNumber instances broadcast as scalars: for two instances x and y, x * y is identical to x .* y, both of which calculate the geometric product.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"On top of this, the grade representation of multivectors makes it difficult to relate the indices of the backing Tuple for each type to the blades represented by the multivector for anything other than the dense CliffordNumber. To solve this issue, this package provides types specifically intended for indexing AbstractCliffordNumber subtypes: BitIndex{Q} and the subtypes of AbstractBitIndices{Q,C}, BitIndices{Q,C} and TransformedBitIndices{Q,C}.","category":"page"},{"location":"indexing.html#BitIndex{Q}","page":"Indexing","title":"BitIndex{Q}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The BitIndex{Q} type is the index type for AbstractCliffordNumber{Q}. This types wraps a UInt: the first dimension(Q) bits represent the presence or absence of the basis vectors associated with each dimension that are used to construct the indexed blade. The most significant bit is a sign bit: this is needed to represent the parity associated with the order of wedge products used to construct the blade.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Regardless of what position in the underlying Tuple a coefficient may be, if x == y, then the same BitIndex b will index x and y identically:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k = KVector{1,VGA(3)}(4,2,0)\n3-element KVector{1, VGA(3), Int64}:\n4e₁ + 2e₂\n\njulia> b = BitIndex(k, 1)\nBitIndex(Val(VGA(3)), 1)\n\njulia> k == OddCliffordNumber(k)\ntrue\n\njulia> k[b] == OddCliffordNumber(k)[b]\ntrue","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"It should also be noted that indexing an AbstractCliffordNumber at an index which is not explicitly represented by the type returns zero:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k[BitIndex(k, 1, 2)]\n0\n","category":"page"},{"location":"indexing.html#Construction","page":"Indexing","title":"Construction","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The internal constructor BitIndex{Q}(signbit::Bool, blade::Unsigned) converts blade to a UInt and changes the most significant bit to match signbit. However, in many cases, constructing a BitIndex{Q} directly from the sign bit and representation of the blade as an unsigned integer is inconvenient.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"For this reason, we define two constructors, the first being BitIndex(::Val{Q}, i::Integer...), which takes the algebra Q wrapped in Val (for reasons of type stability) and the integers i corresponding to basis blade indices defined in Q. The second constructor, BitIndex(x, i::Integer...) calls BitIndex(Val(signature(x))), i...), automatically determining Q.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In both cases, the parity of the permutation of indices is determined automatically from the integer arguments, so this bit is automatically assigned. The presence of a parity bit allows for correct indexing with non-lexicographic conventions: in some literature, e_3 e_1 is used instead of e_1 e_3 for one of the bivector components of APS and STA.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> l = KVector{2,VGA(3)}(0,6,9)\n3-element KVector{2, VGA(3), Int64}:\n6e₁e₃ + 9e₂e₃\n\njulia> l[BitIndex(l, 1, 3)]\n6\n\njulia> l[BitIndex(l, 3, 1)]\n-6","category":"page"},{"location":"indexing.html#Tuples-of-BitIndex{Q}","page":"Indexing","title":"Tuples of BitIndex{Q}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Julia AbstractArray instances can be indexed not just with integers, but with arrays of integers or special objects representing iterable ranges, such as :. Perhaps surprisingly, tuples containing integers (or any other valid index object) are not valid indices of AbstractArray:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> (1:10)[(2, 3, 4)]\nERROR: ArgumentError: invalid index: (2, 3, 4) of type Tuple{Int64, Int64, Int64}\n","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In the case of AbstractCliffordNumber, we have a compelling reason to use tuples of BitIndex{Q} objects for indexing: since the length of a Tuple is known statically, we can use that information to construct a new Tuple of coefficients with statically known length, which may be useful if we want to leverage indexing to convert types. Therefore, indexing an AbstractCliffordNumber{Q,T} with an NTuple{N,BitIndex{Q}} returns an NTuple{N,T}, which can be fed into the constructor for a different type, and this is what the package uses internally to perform conversion.","category":"page"},{"location":"indexing.html#Operations","page":"Indexing","title":"Operations","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"BitIndex{Q} supports a variety of unary and binary operations, many of which are used internally for tasks like calculating geometric products. Many of these operations are also supported for AbstractCliffordNumber{Q} instances, such as negation (-) and the geometric product (*).","category":"page"},{"location":"indexing.html#AbstractBitIndices{Q,C}","page":"Indexing","title":"AbstractBitIndices{Q,C}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Considering that the indices of an AbstractCliffordNumber provided by this package are known from the type, it makes sense to define a type which represents all indices of a subtype or instance of AbstractCliffordNumber. This package defines the supertype AbstractBitIndices{Q,C} and concrete types BitIndices{Q,C} and TransformedBitIndices{Q,C,F} that allow for easy operation across all valid indices of a type C.","category":"page"},{"location":"indexing.html#BitIndices{Q,C}","page":"Indexing","title":"BitIndices{Q,C}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The BitIndices object for an AbstractCliffordNumber subtype C or instance x can be constructed with BitIndices(C) or BitIndices(x). This is a singleton type which is also returned by eachindex(x).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The type information of the BitIndices object is used to determine the type of the result of indexing. Conveniently, you can index one Clifford number x with the indices of another Clifford number y, and this converts x to the a type similar to that of y, but retaining the element type of x:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k = KVector{1,VGA(3)}(4,2,0) # eltype Int64\n3-element KVector{1, VGA(3), Int64}:\n4e₁ + 2e₂\n\njulia> z = zero(CliffordNumber{VGA(3),Float64}) # eltype Float64\n8-element CliffordNumber{VGA(3), Float64}:\n0.0\n\njulia> k[BitIndices(ans)]\n8-element CliffordNumber{VGA(3), Int64}:\n4e₁ + 2e₂\n","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"BitIndices{Q,C} subtypes AbstractBitIndices{Q,C}, which subtypes AbstractVector{BitIndex{Q}}, meaning that the objects can be indexed with integers. This indexing is one-based to match the indices of the Tuple backing a CliffordNumber, but this is subject to change in the future.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"warning: Avoiding type proliferation with `BitIndices`\nOne fundamental issue with BitIndices{Q,C} is that C is only constrained to be a subtype of AbstractCliffordNumber{Q}. However, C may have other type parameters that vary, but produce objects that index equivalently and are identical elementwise:julia> BitIndices{STA,CliffordNumber{STA}}() == BitIndices{STA,CliffordNumber{STA,Float32}}()\ntrue\n\njulia> BitIndices{STA,CliffordNumber{STA}}() == BitIndices{STA,CliffordNumber{STA,Float32,8}}()\ntrue For this reason, you should call BitIndices(x) or BitIndices(C) instead of directly constructing BitIndices{Q,C}().","category":"page"},{"location":"indexing.html#TransformedBitIndices{Q,C,F}","page":"Indexing","title":"TransformedBitIndices{Q,C,F}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"If we want to perform a transformation on all elements of a BitIndices instance, we may use dot syntax and broadcast an operation: for instance, reverse.(BitIndices(x)) to obtain the reverse of all indices. Without any explicit specification of behavior, this will return a Vector, and for the sake of performance we'd like to avoid returning types without statically known lengths.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"We could solve this by converting BitIndices to a Tuple internally as part of the broadcasting implementation, but doing this will cause its own set of problems: indexing an AbstractCliffordNumber with a Tuple returns a Tuple. This may be fine internally, if we know to call the constructor, but this is potentially confusing for new users. For this reason, we provide TransformedBitIndices{Q,C,F}, which is a lazy representation of a function applied to every element of BitIndices(C).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"For convenience, we provide a few aliases for operations which are commonly used with BitIndices:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"ReversedBitIndices{Q,C} is the type of reverse.(::BitIndices{Q,C}).\nGradeInvolutedBitIndices{Q,C} is the type of grade_involution.(::BitIndices{Q,C}).\nConjugatedBitIndices{Q,C} is the type of conj.(::BitIndices{Q,C}).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In the future, we may override some broadcast implementations to ensure that all of these types are interconvertible with each other and with BitIndices{Q,C}.","category":"page"},{"location":"api/clifford.html#Clifford-numbers","page":"CliffordNumbers","title":"Clifford numbers","text":"","category":"section"},{"location":"api/clifford.html#Supertype-and-associated-functions","page":"CliffordNumbers","title":"Supertype and associated functions","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.AbstractCliffordNumber\nCliffordNumbers.scalar_type\nCliffordNumbers.similar_type","category":"page"},{"location":"api/clifford.html#CliffordNumbers.AbstractCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.AbstractCliffordNumber","text":"AbstractCliffordNumber{Q,T} <: Number\n\nAn element of a Clifford algebra, often referred to as a multivector, with quadratic form Q and element type T.\n\nInterface\n\nRequired implementation\n\nAll subtypes C of AbstractCliffordNumber{Q} must implement the following functions:\n\nBase.length(x::C) should return the number of nonzero basis elements represented by x.\nCliffordNumbers.similar_type(::Type{C}, ::Type{T}, ::Type{Q}) where {C,T,Q} should construct a\n\nnew type similar to C which subtypes AbstractCliffordNumber{Q,T} that may serve as a constructor.\n\nBase.getindex(x::C, b::BitIndex{Q}) should allow one to recover the coefficients associated\n\nwith each basis blade represented by C.\n\nRequired implementation for static types\n\nBase.length(::Type{C}) should be defined, with Base.length(x::C) = length(typeof(x)).\nBase.Tuple(x::C) should return the tuple used to construct x. The fallback is\n\ngetfield(x, :data)::Tuple, so any type declared with a NTuple field named data should have this defined automatically.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.scalar_type","page":"CliffordNumbers","title":"CliffordNumbers.scalar_type","text":"scalar_type(::Type{<:AbstractCliffordNumber{Q,T}}) = T\nscalar_type(T::Type{<:Union{Real,Complex}}) = T\nscalar_type(x) = scalar_type(typeof(x))\n\nReturns the numeric type associated with an AbstractCliffordNumber instance. For subtypes of Real and Complex, or their instances, this simply returns the input type or instance type.\n\nWhy not define eltype?\n\nAbstractCliffordNumber instances behave like numbers, not arrays. If collect() is called on a Clifford number of type T, it should not construct a vector of coefficients; instead it should return an Array{T,0}. Similarly, a broadcasted multiplication should return the same result as normal multiplication, as is the case with complex numbers.\n\nFor subtypes T of Number, eltype(T) === T, and this is true for AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.similar_type","page":"CliffordNumbers","title":"CliffordNumbers.similar_type","text":"CliffordNumbers.similar_type(\n C::Type{<:AbstractCliffordNumber},\n [N::Type{<:BaseNumber} = scalar_type(C)],\n [Q::Val = Val(signature(C))]\n) -> Type{<:AbstractCliffordNumber{Q,N}}\n\nConstructs a type similar to T but with numeric type N and quadratic form Q. The quadratic form must be wrapped in a Val to preserve type stability.\n\nThis function must be defined with all its arguments for each concrete type subtyping AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Concrete-types","page":"CliffordNumbers","title":"Concrete types","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.CliffordNumber\nCliffordNumbers.Z2CliffordNumber\nCliffordNumbers.EvenCliffordNumber\nCliffordNumbers.OddCliffordNumber\nCliffordNumbers.KVector\nCliffordNumbers.grade(::Type{<:KVector{K}}) where K","category":"page"},{"location":"api/clifford.html#CliffordNumbers.CliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.CliffordNumber","text":"CliffordNumber{Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA dense multivector (or Clifford number), with quadratic form Q, element type T, and length L (which depends entirely on Q).\n\nThe coefficients are ordered by taking advantage of the natural binary structure of the basis. The grade of an element is given by the Hamming weight of its index. For the algebra of physical space, the order is: 1, e₁, e₂, e₁₂, e₃, e₁₃, e₂₃, e₁₂₃ = i. This order allows for more aggressive SIMD optimization when calculating the geometric product.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.Z2CliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.Z2CliffordNumber","text":"CliffordNumbers.Z2CliffordNumber{P,Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA Clifford number whose only nonzero grades are even or odd. Clifford numbers of this form naturally arise as versors, the geometric product of 1-vectors.\n\nThe type parameter P is constrained to be a Bool: true for odd grade Clifford numbers, and false for even grade Clifford numbers, corresponding to the Boolean result of each grade modulo 2.\n\nType aliases\n\nThis type is not exported, and usually you will want to refer to the following aliases:\n\nconst EvenCliffordNumber{Q,T,L} = Z2CliffordNumber{false,Q,T,L}\nconst OddCliffordNumber{Q,T,L} = Z2CliffordNumber{true,Q,T,L}\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.EvenCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.EvenCliffordNumber","text":"EvenCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{false,Q,T,L})\n\nA Clifford number whose only nonzero grades are even. These are the natural choice of representation for rotors and motors (Euclidean isometries preserving orientation, or \"proper\" isometries), as well as their composition with dilations.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.OddCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.OddCliffordNumber","text":"OddCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{true,Q,T,L})\n\nA Clifford number whose only nonzero grades are odd. These are the natural choice of representation for reflections, as well as their compositions with rotors and motors (Euclidean isometries preserving orientation, or \"proper\" isometries), as well as their composition with dilations.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.KVector","page":"CliffordNumbers","title":"CliffordNumbers.KVector","text":"KVector{K,Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA multivector consisting only linear combinations of basis blades of grade K - in other words, a k-vector.\n\nk-vectors have binomial(dimension(Q), K) components.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.grade-Union{Tuple{Type{<:KVector{K}}}, Tuple{K}} where K","page":"CliffordNumbers","title":"CliffordNumbers.grade","text":"grade(::Type{<:KVector{K}}) = K\ngrade(x::KVector{K}) = k\n\nReturns the grade represented by a KVector{K}, which is K.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Promotion-and-conversion","page":"CliffordNumbers","title":"Promotion and conversion","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.scalar_convert\nCliffordNumbers.scalar_promote\nBase.widen(::Type{<:AbstractCliffordNumber{Q,T}}) where {Q,T}\nCliffordNumbers.widen_grade","category":"page"},{"location":"api/clifford.html#CliffordNumbers.scalar_convert","page":"CliffordNumbers","title":"CliffordNumbers.scalar_convert","text":"scalar_convert(T::Type{<:Union{Real,Complex}}, x::AbstractCliffordNumber) -> T\nscalar_convert(T::Type{<:Union{Real,Complex}}, x::Union{Real,Complex}) -> T\n\nIf x is an AbstractCliffordNumber, converts the scalars of x to type T.\n\nIf x is a Real or Complex, converts x to T.\n\nExamples\n\njulia> scalar_convert(Float32, KVector{1,APS}(1, 2, 3))\n3-element KVector{1, VGA(3), Float32}:\n1.0σ₁ + 2.0σ₂ + 3.0σ\n\njulia> scalar_convert(Float32, 2)\n2.0f0\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.scalar_promote","page":"CliffordNumbers","title":"CliffordNumbers.scalar_promote","text":"scalar_promote(x::AbstractCliffordNumber, y::AbstractCliffordNumber)\n\nPromotes the scalar types of x and y to a common type. This does not increase the number of represented grades of either x or y.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Base.widen-Union{Tuple{Type{<:AbstractCliffordNumber{Q, T}}}, Tuple{T}, Tuple{Q}} where {Q, T}","page":"CliffordNumbers","title":"Base.widen","text":"widen(C::Type{<:AbstractCliffordNumber})\nwiden(x::AbstractCliffordNumber)\n\nConstruct a new type whose scalar type is widened. This behavior matches that of widen(C::Type{Complex{T}}), which results in widening of its scalar type T.\n\nFor obtaining a representation of a Clifford number with an increased number of nonzero grades, use widen_grade(T).\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#CliffordNumbers.widen_grade","page":"CliffordNumbers","title":"CliffordNumbers.widen_grade","text":"widen_grade(C::Type{<:AbstractCliffordNumber})\nwiden_grade(x::AbstractCliffordNumber)\n\nFor type arguments, construct the next largest type that can hold all of the grades of C. KVector{K,Q,T} widens to EvenCliffordNumber{Q,T} or OddCliffordNumber{Q,T}, and EvenCliffordNumber{Q,T} and OddCliffordNumber{Q,T} widen to CliffordNumber{Q,T}, which is the widest type.\n\nFor AbstractCliffordNumber arguments, the argument is converted to the result of widen_grade(typeof(x)).\n\nFor widening the scalar type of an AbstractCliffordNumber, use Base.widen(T).\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Real-and-complex-algebras","page":"CliffordNumbers","title":"Real and complex algebras","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"Base.real(::AbstractCliffordNumber)\nBase.complex(::AbstractCliffordNumber)","category":"page"},{"location":"api/clifford.html#Base.real-Tuple{AbstractCliffordNumber}","page":"CliffordNumbers","title":"Base.real","text":"real(x::AbstractCliffordNumber{Q,T})\n\nGets the real portion of each coefficient of x. For T<:Real this operation does nothing; for T<:Complex{S} this an AbstractCliffordNumber{Q,S}.\n\nNote that this does not return the scalar (grade 0) coefficient of x. Use real(scalar(x)) to obtain this result.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Base.complex-Tuple{AbstractCliffordNumber}","page":"CliffordNumbers","title":"Base.complex","text":"complex(x::AbstractCliffordNumber, [y::AbstractCliffordNumber = zero(typeof(x))])\n\nFor a single argument x, converts the type of each coefficient to a suitable complex type.\n\nFor two arguments x and y, which are both real Clifford numbers, performs the sum x + y*im, constructing a complex Clifford number.\n\nNote that this operation does not isolate a scalar (grade 0) coefficient of x or y. Use complex(scalar(x), [scalar(y)]) to obtain this result.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Scalar-and-pseudoscalar-components","page":"CliffordNumbers","title":"Scalar and pseudoscalar components","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.isscalar\nCliffordNumbers.ispseudoscalar\nCliffordNumbers.scalar","category":"page"},{"location":"api/clifford.html#CliffordNumbers.isscalar","page":"CliffordNumbers","title":"CliffordNumbers.isscalar","text":"isscalar(x::AbstractCliffordNumber)\n\nDetermines whether the Clifford number x is a scalar, meaning that all of its blades of nonzero grade are zero.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.ispseudoscalar","page":"CliffordNumbers","title":"CliffordNumbers.ispseudoscalar","text":"ispseudoscalar(m::AbstractCliffordNumber)\n\nDetermines whether the Clifford number x is a pseudoscalar, meaning that all of its blades with grades below the dimension of the space are zero.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.scalar","page":"CliffordNumbers","title":"CliffordNumbers.scalar","text":"scalar(x::AbstractCliffordNumber{Q,T}) -> T\n\nReturns the scalar portion of x as its scalar type. This is equivalent to x[scalar_index(x)].\n\nTo retain Clifford number semantics, use the KVector{0} constructor.\n\n\n\n\n\n","category":"function"},{"location":"operations.html#Operations","page":"Operations","title":"Operations","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Like with other numbers, standard mathematical operations are supported that relate Clifford numbers to elements of their scalar field and to each other.","category":"page"},{"location":"operations.html#Unary-operations","page":"Operations","title":"Unary operations","text":"","category":"section"},{"location":"operations.html#Grade-automorphisms","page":"Operations","title":"Grade automorphisms","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade automorphisms are operations which preserves the grades of each basis blade, but changes their sign depending on the grade. All of these operations are their own inverse.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"All grade automorphisms are applicable to BitIndex objects, and the way they are implemented is through constructors that use TransformedBitIndices objects to alter each grade.","category":"page"},{"location":"operations.html#Reverse","page":"Operations","title":"Reverse","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The reverse is an operation which reverses the order of the wedge product that constructed each basis blade. This is implemented with methods for Base.reverse and Base.:~.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"note: Syntax changes\nIn the future, Base.:~ will no longer be used for this operation; instead Base.adjoint will be overloaded, providing ' as a syntax for the reverse.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"This is the most commonly used automorphism, and in a sense can be thought of as equivalent to complex conjugation. When working with even elements of the algebras of 2D or 3D space, this behaves identically to complex conjugation and quaternion conjugation. However, this is not the case when working in the even subalgebras.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Base.reverse(::BitIndex)","category":"page"},{"location":"operations.html#Grade-involution","page":"Operations","title":"Grade involution","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade involution changes the sign of all odd grades, an operation equivalent to mirroring every basis vector of the space. This can be acheived with the grade_involution function.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"When interpreting even multivectors as elements of the even subalgebra of the algebra of interest, the grade involution in the even subalgebra is equivalent to the reverse in the algebra of interest.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade involution is equivalent to complex conjugation in when dealing with the even subalgebra of 2D space, which is isomorphic to the complex numbers, but this is not true for quaternion conjugation. Instead, use the Clifford conjugate (described below).","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"CliffordNumbers.grade_involution(::BitIndex)","category":"page"},{"location":"operations.html#Clifford-conjugation","page":"Operations","title":"Clifford conjugation","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The Clifford conjugate is the combination of the reverse and grade involution. This is available via an overload of Base.conj.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"warning: Warning\nconj(::AbstractCliffordNumber) implements the Clifford conjugate, not the reverse!","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"When dealing with the even subalgebras of 2D and 3D VGAs, which are isomorphic to the complex numbers and quaternions, respectively, the Clifford conjugate is equivalent to complex conjugation or quaternion conjugation. Otherwise, this is a less widely used operation than the above two.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Base.conj(::BitIndex)","category":"page"},{"location":"operations.html#Binary-operations","page":"Operations","title":"Binary operations","text":"","category":"section"},{"location":"operations.html#Addition-and-subtraction","page":"Operations","title":"Addition and subtraction","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Addition and subtraction work as expected for Clifford numbers just as they do for other numbers. The promotion system handles all cases where objects of mixed type are added.","category":"page"},{"location":"operations.html#Products","page":"Operations","title":"Products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Clifford algebras admit a variety of products. Common ones are implemented with infix operators.","category":"page"},{"location":"operations.html#Geometric-product","page":"Operations","title":"Geometric product","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The geometric product, or Clifford product, is the defining product of the Clifford algebra. This is implemented with the usual multiplication operator *, but it is also possible to use parenthetical notation as it is with real numbers.","category":"page"},{"location":"operations.html#Wedge-product","page":"Operations","title":"Wedge product","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The wedge product is the defining product of the exterior algebra. This is available with the wedge() function, or with the ∧ infix operator.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"tip: Tip\nYou can define elements of exterior algebras directly by using Metrics.Exterior(D), whose geometric product is equivalent to the wedge product.","category":"page"},{"location":"operations.html#Contractions-and-dot-products","page":"Operations","title":"Contractions and dot products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The contraction operations generalize the dot product of vectors to Clifford numbers. While it is possible to define a symmetric dot product (and one is provided in this package), the generalization of the dot product to Clifford numbers is naturally asymmetric in cases where the grade of one input blade is not equal to that of the other.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"For Clifford numbers x and y, the left contraction x ⨼ y describes the result of projecting x onto the space spanned by y. If x and y are homogeneous in grade, this product is equal to the geometric product if grade(y) ≥ grade(x), and zero otherwise. For general multivectors, the left contraction can be calculated by applying this rule to the products of their basis blades.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The analogous right contraction is only nonzero if grade(x) ≥ grade(y), and it can be calculated with ⨽.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The dot product is a symmetric variation of the left and right contractions, and provides a looser constraint on the basis blades: grade(CliffordNumbers.dot(x,y)) must equal abs(grade(x) - grade(y)). The Hestenes dot product is equivalent to the dot product above, but is zero if either x or y is a scalar.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"note: Note\nCurrently, the dot product is implemented with the unexported function CliffordNumbers.dot. This package does not depend on LinearAlgebra, so there would be a name conflict if this method were exported and both this package and LinearAlgebra were loaded.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Contractions are generally favored over the dot products due to their nicer implementations and properties, which have fewer exceptions. It is generally recommended that the Hestenes dot product be avoided, though it is included in this library for the sake of completeness as CliffordNumber.hestenes_dot, which is also not exported.","category":"page"},{"location":"operations.html#Commutator-and-anticommutator-products","page":"Operations","title":"Commutator and anticommutator products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The commutator product (or antisymmetric product) of Clifford numbers x and y, denoted x × y, is equal to 1//2 * (x*y - y*x). This product is nonzero if the geometric product of x and y does not commute, and the value represents the degree to which they fail to commute.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The commutator product is the building block of Lie algebras; in particular, the commutator products of bivectors, which are also bivectors. With the bivectors of 3D space, the Lie algebra is equivalent to that generated by the cross product, hence the × notation.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The analogous anticommutator product (or symmetric product) is 1//2 * (x*y + y*x). This uses the ⨰ operator, which is not an operator generally used for this purpose, but was selected as it looks similar to the commutator product, with the dot indicating the similarity with the dot product, which is also symmetric.","category":"page"},{"location":"operations.html#Defining-new-products:-Multiplication-internals","page":"Operations","title":"Defining new products: Multiplication internals","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Products are implemented with the fast multiplication kernel CliffordNumbers.mul, which accepts two Clifford numbers with the same scalar type and a CliffordNumbers.GradeFilter object. This GradeFilter object defines a method that takes two or more BitIndex objects and returns false if their product is constrained to be zero.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"CliffordNumbers.mul requires that the coefficient types of the numbers being multiplied are the same. Methods which leverage CliffordNumbers.mul should promote the coefficient types of the arguments to a common type using scalar_promote before passing them to the kernel. Any further promotion needed to return the final result is handled by the kernel.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"In general, it is also strongly recommended to promote the types of the arguments to CliffordNumbers.Z2CliffordNumber or CliffordNumber for higher performance. Currently, the implementation of CliffordNumbers.mul is asymmetric, and does not consider which input is longer. Even in the preferred order, we find that KVector incurs a significant performance penalty.","category":"page"}] +[{"location":"metrics.html#Metric-signatures","page":"Metric signatures","title":"Metric signatures","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Clifford algebras are characterized by the metric signatures of the spaces they represent. Some are very commonly used, such as the algebra of physical space (APS), or are generated as part of a family, such as the projective geometric algebras (PGAs), but in other cases you may need the flexibility to work with custom metric signatures.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"The CliffordNumbers.Metrics submodule provides tools for working with metric signatures.","category":"page"},{"location":"metrics.html#Interface","page":"Metric signatures","title":"Interface","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"The type parameter Q of AbstractCliffordNumber{Q,T} is not constrained in any way, which means that any type or data consisting of pure bits may reside there. However, for the sake of correctness and fully defined behavior, Q must satisfy an informal interface.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metric signature objects are treated like AbstractVector{Int8} instances, but with the elements constrained to be equal to +1, 0, or -1, corresponding to basis 1-blades squaring to positive values, negative values, or zero. In the future, we may support arbitrary values for this type.","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"This array is not constrained to be a 1-based array, and the values of eachindex for the array correspond to the indices of the basis 1-blades of the algebra.","category":"page"},{"location":"metrics.html#The-Metrics.AbstractSignature-type","page":"Metric signatures","title":"The Metrics.AbstractSignature type","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"We define a type, Metrics.AbstractSignature <: AbstractVector{Int8}, for which this interface is already partially implemented.","category":"page"},{"location":"metrics.html#Pre-defined-signatures","page":"Metric signatures","title":"Pre-defined signatures","text":"","category":"section"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"There are many commonly used families of algebras, and for the sake of convenience, we provide four subtypes of Metrics.AbstractSignature to handles these cases:","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metrics.VGA represents vanilla geometric algebras.\nMetrics.PGA represents projective geometric algebras.\nMetrics.CGA represents conformal geometric algebras.\nMetrics.LGA{C} represents Lorentzian geometric algebras:\nMetrics.LGAEast uses the East Coast convention (timelike dimensions square to -1).\nMetrics.LGAWest uses the West Coast convention (timelike dimensions square to +1).","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"To construct an instance of one of these types, call it with the number of modeled spatial dimensions:","category":"page"},{"location":"metrics.html","page":"Metric signatures","title":"Metric signatures","text":"Metrics.VGA(3) models 3 spatial dimensions with no extra dimensions.\nMetrics.PGA(3) models 3 spatial dimensions with 1 degenerate (zero-squaring) dimension.\nMetrics.CGA(3) models 3 spatial dimensions with 2 extra dimensions.\nMetrics.LGAEast(3) models 3 spatial dimensions with an extra negative-squaring time dimension.","category":"page"},{"location":"home.html","page":"Home","title":"Home","text":"CurrentModule = CliffordNumbers","category":"page"},{"location":"home.html#CliffordNumbers","page":"Home","title":"CliffordNumbers","text":"","category":"section"},{"location":"home.html","page":"Home","title":"Home","text":"CliffordNumbers.jl is a package that provides fully static multivectors (Clifford numbers) in arbitrary dimensions and metrics. While in many cases, sparse representations of multivectors are more efficient, for spaces of low dimension, dense static representations may provide a performance and convenience advantage.","category":"page"},{"location":"home.html#Design-goals","page":"Home","title":"Design goals","text":"","category":"section"},{"location":"home.html","page":"Home","title":"Home","text":"The goal of this package is to provide a multivector implementation that:","category":"page"},{"location":"home.html","page":"Home","title":"Home","text":"Allows for the construction of multivectors in arbitrary metrics, with coefficients that subtype any instance of Julia's base numeric types, Real or Complex.\nProvides data structures of fixed sizes that represent multivectors. This allows for instances to be allocated on the stack or stored inline in an Array rather than as pointers to individually allocated instances.\nProvides dense representations of multivectors, as well as convenient sparse representations, which can be constructed from each other, converted in a way that guarantees representability, and allows for promotion between instances.\nSubtypes Number: The term \"Clifford number\" emphasizes the perspective of multivectors as an extension of the real numbers, in the same way that complex numbers and quaternions extend them. (It should be noted that both complex numbers and quaternions are Clifford algebras themselves!)\nAggressively optimizes all mathematical operations, utilizing fma operations and SIMD instructions whenever possible.\nInteroperates with automatic differentiation tools and other packages which allow for the implementation of operations from geometric calculus.","category":"page"},{"location":"api/math.html#Mathematical-operations","page":"Math","title":"Mathematical operations","text":"","category":"section"},{"location":"api/math.html#Grade-automorphisms","page":"Math","title":"Grade automorphisms","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.reverse(::BitIndex)\nCliffordNumbers.grade_involution(::BitIndex)\nBase.conj(::BitIndex)","category":"page"},{"location":"api/math.html#Duals-and-inverses","page":"Math","title":"Duals and inverses","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"CliffordNumbers.versor_inverse\nBase.inv(::AbstractCliffordNumber)","category":"page"},{"location":"api/math.html#CliffordNumbers.versor_inverse","page":"Math","title":"CliffordNumbers.versor_inverse","text":"CliffordNumbers.versor_inverse(x::AbstractCliffordNumber)\n\nCalculates the versor inverse of x, equal to x' / abs2(x).\n\nThe versor inverse is only guaranteed to be an inverse for versors. Not all Clifford numbers have a well-defined inverse, (for instance, in algebras with 2 or more positive-squaring, dimensions, 1 + e₁ has no inverse). To validate the result, use inv(x) instead.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Base.inv-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.inv","text":"inv(x::AbstractCliffordNumber) -> AbstractCliffordNumber\n\nCalculates the inverse of x, if it exists, using the versor inverse formula x' / abs2(x). The result is tested to check if its left and right products with x are approximately 1, and a CliffordNumbers.InverseException is thrown if this test does not pass.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Addition-and-subtraction","page":"Math","title":"Addition and subtraction","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Addition and subtraction integrate seamlessly with those of the Julia Base number types, and no special documentation is included here.","category":"page"},{"location":"api/math.html#Products","page":"Math","title":"Products","text":"","category":"section"},{"location":"api/math.html#Products-with-scalars","page":"Math","title":"Products with scalars","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"The standard multiplication and division operations (*, /, //) between Clifford numbers and scalars behave as expected. Base.muladd has been overloaded to take advantage of fma instructions available on some hardware platforms.","category":"page"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.muladd(x::BaseNumber, y::T, z::T) where T<:AbstractCliffordNumber","category":"page"},{"location":"api/math.html#Base.muladd-Union{Tuple{T}, Tuple{Union{Real, Complex}, T, T}} where T<:AbstractCliffordNumber","page":"Math","title":"Base.muladd","text":"muladd(x::Union{Real,Complex}, y::AbstractCliffordNumber{Q}, z::AbstractCliffordNumber{Q})\nmuladd(x::AbstractCliffordNumber{Q}, y::Union{Real,Complex}, z::AbstractCliffordNumber{Q})\n\nMultiplies a scalar with a Clifford number and adds another Clifford number, utilizing optimizations made available with scalar muladd, such as fma if hardware support is available.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Geometric-products","page":"Math","title":"Geometric products","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.:*(::AbstractCliffordNumber{Q}, ::AbstractCliffordNumber{Q}) where Q\nCliffordNumbers.left_contraction\nCliffordNumbers.right_contraction\nCliffordNumbers.dot\nCliffordNumbers.hestenes_dot\nCliffordNumbers.wedge(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q}) where Q\nCliffordNumbers.commutator\nCliffordNumbers.anticommutator","category":"page"},{"location":"api/math.html#CliffordNumbers.left_contraction","page":"Math","title":"CliffordNumbers.left_contraction","text":"left_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n⨼(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the left contraction of x and y.\n\nFor basis blades A of grade m and B of grade n, the left contraction is zero if n < m, otherwise it is KVector{n-m,Q}(A*B).\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.right_contraction","page":"Math","title":"CliffordNumbers.right_contraction","text":"right_contraction(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n⨽(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the right contraction of x and y.\n\nFor basis blades A of grade m and B of grade n, the right contraction is zero if m < n, otherwise it is KVector{m-n,Q}(A*B).\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.dot","page":"Math","title":"CliffordNumbers.dot","text":"CliffordNumbers.dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the dot product of x and y.\n\nFor basis blades A of grade m and B of grade n, the dot product is equal to the left contraction when m >= n and is equal to the right contraction (up to sign) when n >= m.\n\nWhy is this function not exported?\n\nThe LinearAlgebra package also defines a dot function, and if both packages are used together, this will cause a name conflict if CliffordNumbers.dot is exported. In the future, we will try to resolve this without requiring a LinearAlgebra dependency.\n\nAdditionally, there is reason to prefer the use of the left and right contractions over the dot product because the contractions require fewer exceptions in their definitions and properties.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.hestenes_dot","page":"Math","title":"CliffordNumbers.hestenes_dot","text":"CliffordNumbers.hestenes_dot(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nReturns the Hestenes product: this is equal to the dot product given by dot(x, y) but is equal to to zero when either x or y is a scalar.\n\nWhy is this function not exported?\n\nIn almost every case, left and right contractions are preferable - the dot product and the Hestenes product are less regular in algebraic sense, and the conditionals present in its implementation slow it down relative to contractions. It is provided for the sake of exact reproducibility of results which use it.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.commutator","page":"Math","title":"CliffordNumbers.commutator","text":"×(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\ncommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the commutator (or antisymmetric) product, equal to 1//2 * (x*y - y*x).\n\nNote that the commutator product, in general, is not equal to the wedge product, which may be invoked with the wedge function or the ∧ operator.\n\nType promotion\n\nBecause of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.anticommutator","page":"Math","title":"CliffordNumbers.anticommutator","text":"⨰(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\nanticommutator(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the anticommutator (or symmetric) product, equal to 1//2 * (x*y + y*x).\n\nNote that the dot product, in general, is not equal to the anticommutator product, which may be invoked with dot. In some cases, the preferred operators might be the left and right contractions, which use infix operators ⨼ and ⨽ respectively.\n\nType promotion\n\nBecause of the rational 1//2 factor in the product, inputs with scalar types subtyping Integer will be promoted to Rational subtypes.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Scalar-products-and-normalization","page":"Math","title":"Scalar products and normalization","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"CliffordNumbers.scalar_product\nBase.abs2(::AbstractCliffordNumber)\nBase.abs(::AbstractCliffordNumber)\nCliffordNumbers.normalize","category":"page"},{"location":"api/math.html#CliffordNumbers.scalar_product","page":"Math","title":"CliffordNumbers.scalar_product","text":"scalar_product(x::AbstractCliffordNumber{Q}, y::AbstractCliffordNumber{Q})\n\nCalculates the scalar product of two Clifford numbers with quadratic form Q. The result is a Real or Complex number. This can be converted back to an AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Base.abs2-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.abs2","text":"abs2(x::AbstractCliffordNumber{Q,T}) -> T\n\nCalculates the squared norm of x, equal to scalar_product(x, x').\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#Base.abs-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.abs","text":"abs2(x::AbstractCliffordNumber{Q,T}) -> Union{Real,Complex}\n\nCalculates the norm of x, equal to sqrt(scalar_product(x, x')).\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#CliffordNumbers.normalize","page":"Math","title":"CliffordNumbers.normalize","text":"normalize(x::AbstractCliffordNumber{Q}) -> AbstractCliffordNumber{Q}\n\nNormalizes x so that its magnitude (as calculated by abs2(x)) is 1.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#Exponentiation","page":"Math","title":"Exponentiation","text":"","category":"section"},{"location":"api/math.html","page":"Math","title":"Math","text":"Base.exp(::AbstractCliffordNumber)\nCliffordNumbers.exppi\nCliffordNumbers.exptau","category":"page"},{"location":"api/math.html#Base.exp-Tuple{AbstractCliffordNumber}","page":"Math","title":"Base.exp","text":"exp(x::AbstractCliffordNumber{Q})\n\nReturns the natural exponential of a Clifford number.\n\nFor special cases where m squares to a scalar, the following shortcuts can be used to calculate exp(x):\n\nWhen x^2 < 0: exp(x) === cos(abs(x)) + x * sin(abs(x)) / abs(x)\nWhen x^2 > 0: exp(x) === cosh(abs(x)) + x * sinh(abs(x)) / abs(x)\nWhen x^2 == 0: exp(x) == 1 + x\n\nSee also: exppi, exptau.\n\n\n\n\n\n","category":"method"},{"location":"api/math.html#CliffordNumbers.exppi","page":"Math","title":"CliffordNumbers.exppi","text":"exppi(x::AbstractCliffordNumber)\n\nReturns the natural exponential of π * x with greater accuracy than exp(π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).\n\nSee also: exp, exptau.\n\n\n\n\n\n","category":"function"},{"location":"api/math.html#CliffordNumbers.exptau","page":"Math","title":"CliffordNumbers.exptau","text":"exptau(x::AbstractCliffordNumber)\n\nReturns the natural exponential of 2π * x with greater accuracy than exp(2π * x) in the case where x^2 is a negative scalar, especially for large values of abs(x).\n\nSee also: exp, exppi.\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#Metric-signatures","page":"Metric signatures","title":"Metric signatures","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics","page":"Metric signatures","title":"CliffordNumbers.Metrics","text":"CliffordNumbers.Metrics\n\nContains tools for working with metric signatures associated with AbstractCliffordNumber subtypes and instances. This includes the Metrics.AbstractSignature type and its subtypes.\n\n\n\n\n\n","category":"module"},{"location":"api/metrics.html#Signature-types","page":"Metric signatures","title":"Signature types","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics.AbstractSignature\nCliffordNumbers.Metrics.Signature\nCliffordNumbers.Metrics.VGA\nCliffordNumbers.Metrics.PGA\nCliffordNumbers.Metrics.CGA\nCliffordNumbers.Metrics.LGA\nCliffordNumbers.Metrics.LGAEast\nCliffordNumbers.Metrics.LGAWest\nCliffordNumbers.Metrics.Exterior","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.AbstractSignature","page":"Metric signatures","title":"CliffordNumbers.Metrics.AbstractSignature","text":"Metrics.AbstractSignature <: AbstractVector{Int8}\n\nSupertype for all data types that represent metric signatures. This includes the generic Signature type as well as other specialized types.\n\nMetric signatures can be interpreted as the signs of the diagonal elements of the metric tensor. All elements are either -1, 0, or 1. All nondegenerate Clifford algebras admit an orthonormal basis corresponding to the metric.\n\nAside from the generic Metrics.Signature subtype, types for commonly used algebras are available, including Metrics.VGA, Metrics.PGA, and Metrics.CGA. Custom signatures with firmer bounds on their behavior can be implemented by subtyping this type.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.Signature","page":"Metric signatures","title":"CliffordNumbers.Metrics.Signature","text":"Metrics.Signature <: Metrics.AbstractSignature\nMetrics.Signature(\n dimensions::Integer,\n negative::UInt,\n degenerate::UInt,\n [first_index::Integer = 1]\n)\n\nContains information about the metric associated with a Clifford algebra or Clifford number. This type is constructed to be as generic as possible; other subtypes of Metrics.AbstractSignature may provide firmer guarantees on behavior, such as VGA.\n\nThe number which the dimensions square to is stored in a pair of UInt fields. The negative field consists of 1 bits for dimensions that square to a negative number, and 0 bits for those squaring to a positive number, matching the convention of sign bits in signed numbers.\n\nThe degenerate field consists of 1 bits for degenerate dimensions (dimensions that square to zero) and 0 bits for nondegenerate dimensions.\n\nThe numerical index of the first basis vector is first_index, which defaults to 1. Some algebras conventionally use 0 as the first index, such as projective geometric algebras and Lorentzian geometric algebras, and in some cases it may be useful to start with a negative index if there are a larger number of modeling dimensions.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA","text":"VGA <: Metrics.AbstractSignature\n\nRepresents the signature associated with a vanilla geometric algebra (VGA), a positive-definite geometric algebra which models space without any projective dimensions.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA","text":"PGA <: Metrics.AbstractSignature\n\nRepresents the signature associated with a PGA (projective geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one degenerate (zero-squaring) dimension represented by e₀. This degenerate dimension corresponds with the n∞ null vector in CGA (conformal geometric algebra).\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA","text":"CGA <: Metrics.AbstractSignature\n\nRepresents the signature of a CGA (conformal geometric algebra) with the given number of modeled dimensions. The constructed algebra will contain the number of modeled dimensions plus one positive-squaring dimension and one negative-squaring dimension.\n\nThere are two common choices of vector basis for the extra dimensions added when working with CGA. The most straightforward one is e₊ and e₋, which square to +1 and -1, respectively, and this is what is used internally, with the negative-squaring dimension being the first one.\n\nHowever, there is another commonly used basis: define null vectors n₀ = (e₋ - e₊)/2 and n∞ = e₋ - e₊, which represent the origin point and the point at infinity, respectively. n∞ corresponds to e₀ in PGA (projective geometric algebra).\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGA","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGA","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGAEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGAEast","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.LGAWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.LGAWest","text":"LGA{C} <: Metrics.AbstractSignature\n\nRepresents the signature of a Lorentzian geometric algebra (LGA), an algebra which models a given number of spatial dimensions associated with a single time dimension at index 0.\n\nThe type parameter C corresponds to the sign bit associated with the square of the spatial 1-blades. For convenience, the following aliases are defined:\n\nconst LGAEast = LGA{false}\nconst LGAWest = LGA{true}\n\nThe names correspond to the \"East Coast\" and \"West Coast\" conventions for the metric signature of spacetime, with the East Coast convention having positive squares for spatial 1-blades and the West Coast convention having negative squares for spatial 1-blades.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#CliffordNumbers.Metrics.Exterior","page":"Metric signatures","title":"CliffordNumbers.Metrics.Exterior","text":"Exterior <: Metrics.AbstractSignature\n\nRepresents a signature corresponding to an exterior algebra. In an exterior algebra, all 1-blades square to 0, and the geometric product is equivalent ot the wedge product.\n\nUnlike VGA, PGA, CGA, and LGA, the first index is not assumed when constructing this object, and can be manually specified. If it is not specified, it defaults to 1.\n\n\n\n\n\n","category":"type"},{"location":"api/metrics.html#Aliases-for-common-signatures","page":"Metric signatures","title":"Aliases for common signatures","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.Metrics.VGA2D\nCliffordNumbers.Metrics.VGA3D\nCliffordNumbers.Metrics.PGA2D\nCliffordNumbers.Metrics.PGA3D\nCliffordNumbers.Metrics.CGA2D\nCliffordNumbers.Metrics.CGA3D\nCliffordNumbers.Metrics.STAEast\nCliffordNumbers.Metrics.STAWest\nCliffordNumbers.Metrics.STA\nCliffordNumbers.Metrics.STAPEast\nCliffordNumbers.Metrics.STAPWest\nCliffordNumbers.Metrics.STAP","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA2D","text":"VGA2D (alias for VGA(2))\n\nThe algebra of 2D space. The even subalgebra of this algebra is isomorphic to ℂ, the complex numbers.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.VGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.VGA3D","text":"VGA3D (alias for VGA(3))\nconst APS = VGA3D\n\nThe algebra of physical space, a 3D VGA which is commonly used (explicitly and implicitly) to model non-relativistic physics. It also serves as the subalgebra of both signature conventions of the spacetime algebra (available as STAEast and STAWest).\n\nThe even subalgebra of this algebra is isomorphic to ℍ, the quaternions.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA2D","text":"PGA2D (alias for PGA(2))\n\nThe projective geometric algebra of 2D space, which represents points and lines on the plane.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.PGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.PGA3D","text":"PGA3D (alias for PGA(3))\n\nThe projective geometric algebra of 3D space, which represents points, lines, and planes in a 3D space.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA2D","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA2D","text":"CGA2D (alias for CGA(2))\n\nThe conformal geometric algebra of 2D space, which represents points, lines, and circles on the plane. This algebra constitutes a framework for compass and straightedge constructions.\n\nThis algebra is isomorphic to STAEast, and this isomorphism is the reason why the default convention for spacetime algebras in this package is the West Coast (mostly negative) convention.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.CGA3D","page":"Metric signatures","title":"CliffordNumbers.Metrics.CGA3D","text":"CGA3D (alias for CGA(3))\n\nThe conformal geometric algebra of 3D space, which represents points, lines, and planes, as well as circles and spheres. This algebra constitutes a framework for extending compass and straightedge constructions to 3 dimensions.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAEast","text":"STAEast (alias for LGAEast(3))\n\nThe spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative), with the temporal dimension at index 0.\n\nThis convention is not the default STA convention, since this signature is identical to that of the 2D conformal geometric algebra.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAWest","text":"STAWest (alias for LGAWest(3))\nconst STA = STAWest\n\nThe spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive), with the temporal dimension at index 0.\n\nThis convention is the default STA convention in this package, since the signature for the East Coast convention can be interpreted as that of the 2D conformal geometric algebra.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STA","page":"Metric signatures","title":"CliffordNumbers.Metrics.STA","text":"STAWest (alias for LGAWest(3))\nconst STA = STAWest\n\nThe spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive), with the temporal dimension at index 0.\n\nThis convention is the default STA convention in this package, since the signature for the East Coast convention can be interpreted as that of the 2D conformal geometric algebra.\n\n\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAPEast","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAPEast","text":"STAPEast (alias for Signature(5, 0b00010, 0b00001, -1))\n\nThe projective spacetime algebra using the East Coast sign convention (spatial dimensions square positive, temporal dimensions square negative). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAPWest","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAPWest","text":"STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))\nconst STAP = STAPWest\n\nThe projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#CliffordNumbers.Metrics.STAP","page":"Metric signatures","title":"CliffordNumbers.Metrics.STAP","text":"STAPWest (alias for Signature(5, 0b11100, 0b00001, -1))\nconst STAP = STAPWest\n\nThe projective spacetime algebra using the West Coast sign convention (spatial dimensions square negative, temporal dimensions square positive). The degenerate dimension is at index -1.\n\nAs with STA, the default convention for STAP is the West Coast metric. For an explanation, see STA.\n\n\n\n\n\n\n\n","category":"constant"},{"location":"api/metrics.html#Associated-methods","page":"Metric signatures","title":"Associated methods","text":"","category":"section"},{"location":"api/metrics.html","page":"Metric signatures","title":"Metric signatures","text":"CliffordNumbers.dimension\nCliffordNumbers.blade_count\nCliffordNumbers.grades\nCliffordNumbers.is_degenerate\nCliffordNumbers.is_positive_definite","category":"page"},{"location":"api/metrics.html#CliffordNumbers.Metrics.dimension","page":"Metric signatures","title":"CliffordNumbers.Metrics.dimension","text":"dimension(s::AbstractSignature) -> Int8\n\nReturns the total number of dimensions associated with s. The default implementation returns signed(s.dimensions).\n\nThe total number of basis blades is equal to to the size of the power set of all basis vectors, and is equal to 2^dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.blade_count","page":"Metric signatures","title":"CliffordNumbers.Metrics.blade_count","text":"blade_count(s) -> Int\n\nReturns the total number of blades associated with metric signature s, which is equal to 2^dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.grades","page":"Metric signatures","title":"CliffordNumbers.Metrics.grades","text":"grades(s::AbstractSignature) -> UnitRange{Int8}\n\nReturns the total number of grades associated with s, which is equal to 0:dimension(s).\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.is_degenerate","page":"Metric signatures","title":"CliffordNumbers.Metrics.is_degenerate","text":"is_degenerate(s::AbstractSignature)\n\nReturns true if any basis elements of s square to 0.\n\nThis does not imply that no elements of the associated Clifford algebra square to 0.\n\n\n\n\n\n","category":"function"},{"location":"api/metrics.html#CliffordNumbers.Metrics.is_positive_definite","page":"Metric signatures","title":"CliffordNumbers.Metrics.is_positive_definite","text":"is_positive_definite(s::AbstractSignature)\n\nReturns true if all basis 1-blades of s square to a positive value.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Grades-and-indices","page":"Indexing","title":"Grades and indices","text":"","category":"section"},{"location":"api/indexing.html#Grades","page":"Indexing","title":"Grades","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.nonzero_grades\nCliffordNumbers.has_grades_of","category":"page"},{"location":"api/indexing.html#CliffordNumbers.nonzero_grades","page":"Indexing","title":"CliffordNumbers.nonzero_grades","text":"nonzero_grades(::Type{<:AbstractCliffordNumber})\nnonzero_grades(::AbstractCliffordNumber)\n\nA function returning an indexable object representing all nonzero grades of a Clifford number representation.\n\nThis function is used to define the indexing of RepresentedGrades, and should be defined for any subtypes of AbstractCliffordNumber.\n\nExamples\n\njulia> CliffordNumbers.nonzero_grades(CliffordNumber{APS})\n0:3\n\njulia> CliffordNumbers.nonzero_grades(KVector{2,APS})\n2:2\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.has_grades_of","page":"Indexing","title":"CliffordNumbers.has_grades_of","text":"has_grades_of(S::Type{<:AbstractCliffordNumber}, T::Type{<:AbstractCliffordNumber}) -> Bool\nhas_grades_of(x::AbstractCliffordNumber, y::AbstractCliffordNumber) -> Bool\n\nReturns true if the grades represented in S are also represented in T; false otherwise.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#BitIndex","page":"Indexing","title":"BitIndex","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.BitIndex\nCliffordNumbers.is_same_blade","category":"page"},{"location":"api/indexing.html#CliffordNumbers.BitIndex","page":"Indexing","title":"CliffordNumbers.BitIndex","text":"BitIndex{Q}\n\nA representation of an index corresponding to a basis blade of the geometric algebra with quadratic form Q.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.is_same_blade","page":"Indexing","title":"CliffordNumbers.is_same_blade","text":"CliffordNumbers.is_same_blade(a::BitIndex{Q}, b::BitIndex{Q})\n\nChecks if a and b perform identical indexing up to sign.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Special-indices","page":"Indexing","title":"Special indices","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.scalar_index\nCliffordNumbers.pseudoscalar_index","category":"page"},{"location":"api/indexing.html#CliffordNumbers.scalar_index","page":"Indexing","title":"CliffordNumbers.scalar_index","text":"scalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}\n\nConstructs the BitIndex used to obtain the scalar (grade zero) portion of x.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.pseudoscalar_index","page":"Indexing","title":"CliffordNumbers.pseudoscalar_index","text":"pseudoscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}\n\nConstructs the BitIndex used to obtain the pseudoscalar (highest grade) portion of x.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Tools-for-implementing-mathematical-operations","page":"Indexing","title":"Tools for implementing mathematical operations","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"Base.reverse(::BitIndex)\nCliffordNumbers.grade_involution(::BitIndex)\nBase.conj(::BitIndex)","category":"page"},{"location":"api/indexing.html#Base.reverse-Tuple{BitIndex}","page":"Indexing","title":"Base.reverse","text":"adjoint(i::BitIndex) = reverse(i::BitIndex) = i' -> BitIndex\nadjoint(x::AbstractCliffordNumber) = reverse(x::AbstractCliffordNumber) = x' -> typeof(x)\n\nPerforms the reverse operation on the basis blade indexed by b or the Clifford number x. The sign of the reverse depends on the grade of the basis blade g, and is positive for g % 4 in 0:1 and negative for g % 4 in 2:3.\n\n\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.grade_involution-Tuple{BitIndex}","page":"Indexing","title":"CliffordNumbers.grade_involution","text":"grade_involution(i::BitIndex) -> BitIndex\ngrade_involution(x::AbstractCliffordNumber) -> typeof(x)\n\nCalculates the grade involution of the basis blade indexed by b or the Clifford number x. This effectively reflects all of the basis vectors of the space along their own mirror operation, which makes elements of odd grade flip sign.\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#Base.conj-Tuple{BitIndex}","page":"Indexing","title":"Base.conj","text":"conj(i::BitIndex) -> BitIndex\nconj(x::AbstractCliffordNumber) -> typeof(x)\n\nCalculates the Clifford conjugate of the basis blade indexed by b or the Clifford number x. This is equal to grade_involution(reverse(x)).\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.grade(::BitIndex)\nCliffordNumbers.sign_of_square\nCliffordNumbers.signbit_of_square\nCliffordNumbers.nondegenerate_square\nCliffordNumbers.sign_of_mult\nCliffordNumbers.signbit_of_mult\nCliffordNumbers.nondegenerate_mult\nBase.:*(::T, ::T) where T<:BitIndex\nCliffordNumbers.has_wedge","category":"page"},{"location":"api/indexing.html#CliffordNumbers.grade-Tuple{BitIndex}","page":"Indexing","title":"CliffordNumbers.grade","text":"grade(i::BitIndex) -> Int\n\nReturns the grade of the basis blade represented by i, which ranges from 0 to the dimension of the space represented by i (equal to dimension(signature(i))).\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.sign_of_square","page":"Indexing","title":"CliffordNumbers.sign_of_square","text":"CliffordNumbers.sign_of_square(b::BitIndex) -> Int8\n\nReturns the sign associated with squaring the basis blade indexed by b using an Int8 as proxy: positive signs return Int8(1), negative signs return Int8(-1), and zeros from degenerate components return Int8(0).\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.signbit_of_square","page":"Indexing","title":"CliffordNumbers.signbit_of_square","text":"CliffordNumbers.signbit_of_square(b::BitIndex) -> Bool\n\nReturns the signbit associated with squaring the basis blade indexed by b.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.nondegenerate_square","page":"Indexing","title":"CliffordNumbers.nondegenerate_square","text":"CliffordNumbers.nondegenerate_square(b::BitIndex) -> Bool\n\nReturns false if squaring the basis blade b is zero due to a degenerate component, true otherwise. For a nondegenerate metric, this is always true.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.sign_of_mult","page":"Indexing","title":"CliffordNumbers.sign_of_mult","text":"CliffordNumbers.sign_of_mult(a::T, b::T) where T<:BitIndex -> Int8\n\nReturns an Int8 that carries the sign associated with the multiplication of two basis blades of Clifford/geometric algebras of the same quadratic form.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.signbit_of_mult","page":"Indexing","title":"CliffordNumbers.signbit_of_mult","text":"CliffordNumbers.signbit_of_mult(a::Integer, [b::Integer]) -> Bool\nCliffordNumbers.signbit_of_mult(a::BitIndex, [b::BitIndex]) -> Bool\n\nCalculates the sign bit associated with multiplying basis elements indexed with bit indices supplied as either integers or BitIndex instances. The sign bit flips when the order of a and b are reversed, unless a === b. \n\nAs with Base.signbit(), true represents a negative sign and false a positive sign. However, in degenerate metrics (such as those of projective geometric algebras) the sign bit may be irrelevant as the multiplication of those basis blades would result in zero.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#CliffordNumbers.nondegenerate_mult","page":"Indexing","title":"CliffordNumbers.nondegenerate_mult","text":"CliffordNumbers.nondegenerate_mult(a::T, b::T) where T<:BitIndex -> Bool\n\nReturns false if the product of a and b is zero due to the squaring of a degenerate component, true otherwise. This function always returns true if R === 0.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#Base.:*-Union{Tuple{T}, Tuple{T, T}} where T<:BitIndex","page":"Indexing","title":"Base.:*","text":"*(a::BitIndex{Q}, b::BitIndex{Q}) -> BitIndex{Q}\n\nReturns the BitIndex corresponding to the basis blade resulting from the geometric product of the basis blades indexed by a and b.\n\n\n\n\n\n","category":"method"},{"location":"api/indexing.html#CliffordNumbers.has_wedge","page":"Indexing","title":"CliffordNumbers.has_wedge","text":"CliffordNumbers.has_wedge(a::BitIndex{Q}, b::BitIndex{Q}, [c::BitIndex{Q}...]) -> Bool\n\nReturns true if the basis blades indexed by a, b, or any other blades c... have a nonzero wedge product; false otherwise. This is determined by comparing all bits of the arguments (except the sign bit) to identify any matching basis blades using bitwise AND.\n\n\n\n\n\n","category":"function"},{"location":"api/indexing.html#BitIndices-and-related-types","page":"Indexing","title":"BitIndices and related types","text":"","category":"section"},{"location":"api/indexing.html","page":"Indexing","title":"Indexing","text":"CliffordNumbers.AbstractBitIndices\nCliffordNumbers.BitIndices\nCliffordNumbers.TransformedBitIndices","category":"page"},{"location":"api/indexing.html#CliffordNumbers.AbstractBitIndices","page":"Indexing","title":"CliffordNumbers.AbstractBitIndices","text":"AbstractBitIndices{Q,C<:AbstractCliffordNumber{Q}} <: AbstractVector{BitIndex{Q}}\n\nSupertype for vectors containing all valid BitIndex{Q} objects for the basis elements represented by C.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.BitIndices","page":"Indexing","title":"CliffordNumbers.BitIndices","text":"BitIndices{Q,C<:AbstractCliffordNumber{Q,<:Any}} <: AbstractVector{BitIndex{Q}}\n\nRepresents a range of valid BitIndex objects for the nonzero components of a given multivector of algebra Q.\n\nFor a generic AbstractCliffordNumber{Q}, this returns BitIndices{Q,CliffordNumber{Q}}, which contains all possible indices for a multivector associated with the algebra parameter Q. For sparser representations, such as KVector{K,Q}, the object only contains the indices of the nonzero elements of the multivector.\n\nConstruction\n\nBitIndices can be constructed by calling the type constructor with the Clifford number or its type. This will automatically strip some type parameters so that identical BitIndices objects are constructed regardless of the scalar type.\n\nFor this reason, you should not use BitIndices{Q,C}(); instead use BitIndices(C).\n\nIndexing\n\nBitIndices always uses one-based indexing like most Julia arrays. Although it is more natural in the dense case to use zero-based indexing, as the basis blades are naturally encoded in the indices for the dense representation of CliffordNumber, one-based indexing is used by the tuples which contain the data associated with this package's implementations of Clifford numbers.\n\nBroadcasting\n\nBecause BitIndices(x) only lazily references the indices of x, we define a new type, TransformedBitIndices, which allows for a function f to be lazily associated with the BitIndices object, and this type is constructed when a f.(BitIndices(x)) is called.\n\nInterfaces for new subtypes of AbstractCliffordNumber\n\nWhen defining the behavior of BitIndices for new subtypes T of AbstractCliffordNumber, Base.getindex(::BitIndices{Q,T}, i::Integer) should be defined so that all indices of T that are not constrained to be zero are returned.\n\nYou should also define CliffordNumbers.bitindices_type(::Type{T}) so that type parameters that do not affect the construction of the BitIndices object are stripped.\n\n\n\n\n\n","category":"type"},{"location":"api/indexing.html#CliffordNumbers.TransformedBitIndices","page":"Indexing","title":"CliffordNumbers.TransformedBitIndices","text":"TransformedBitIndices{Q,C,F} <: AbstractBitIndices{Q,C}\n\nLazy representation of BitIndices{Q,C} with some function of type f applied to each element. These objects can be used to perform common operations which act on basis blades or grades, such as the reverse or grade involution.\n\n\n\n\n\n","category":"type"},{"location":"api/internal.html#Internal-methods","page":"Internals","title":"Internal methods","text":"","category":"section"},{"location":"api/internal.html#Hamming-weights-and-related-operations","page":"Internals","title":"Hamming weights and related operations","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.Hamming\nCliffordNumbers.Hamming.isevil\nCliffordNumbers.Hamming.isodious\nCliffordNumbers.Hamming.number_of_parity\nCliffordNumbers.Hamming.evil_number\nCliffordNumbers.Hamming.odious_number\nCliffordNumbers.Hamming.next_of_hamming_weight\nCliffordNumbers.Hamming.hamming_number","category":"page"},{"location":"api/internal.html#CliffordNumbers.Hamming","page":"Internals","title":"CliffordNumbers.Hamming","text":"CliffordNumbers.Hamming\n\nA submodule containing methods for working with the sum of binary digits contained in an integer. This is essential to representing the basis blades of a geometric algebra, as the presence or absence of each possible basis vector in a blade can be represented by a binary 1 or 0. Operations that require knowledge of the grade of a basis blade will need the operations in this submodule.\n\n\n\n\n\n","category":"module"},{"location":"api/internal.html#CliffordNumbers.Hamming.isevil","page":"Internals","title":"CliffordNumbers.Hamming.isevil","text":"CliffordNumbers.Hamming.isevil(i::Integer) -> Bool\n\nDetermines whether a number is evil, meaning that its Hamming weight (sum of its binary digits) is even.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.isodious","page":"Internals","title":"CliffordNumbers.Hamming.isodious","text":"CliffordNumbers.Hamming.isodious(i::Integer) -> Bool\n\nDetermines whether a number is odious, meaning that its Hamming weight (sum of its binary digits) is odd.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.number_of_parity","page":"Internals","title":"CliffordNumbers.Hamming.number_of_parity","text":"CliffordNumbers.Hamming.number_of_parity(n::Integer, modulo::Bool)\n\nReturns the nth number whose Hamming weight is even (for modulo = false) or odd (for modulo = true).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.evil_number","page":"Internals","title":"CliffordNumbers.Hamming.evil_number","text":"CliffordNumbers.Hamming.evil_number(n::Integer)\n\nReturns the nth evil number, with the first evil number (n == 1) defined to be 0.\n\nEvil numbers are numbers which have an even Hamming weight (sum of its binary digits).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.odious_number","page":"Internals","title":"CliffordNumbers.Hamming.odious_number","text":"CliffordNumbers.Hamming.odious_number(n::Integer)\n\nReturns the nth odious number, with the first odious number (n == 1) defined to be 1.\n\nOdious numbers are numbers which have an odd Hamming weight (sum of its binary digits).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.next_of_hamming_weight","page":"Internals","title":"CliffordNumbers.Hamming.next_of_hamming_weight","text":"CliffordNumbers.Hamming.next_of_hamming_weight(n::Integer)\n\nReturns the next integer with the same Hamming weight as n.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.Hamming.hamming_number","page":"Internals","title":"CliffordNumbers.Hamming.hamming_number","text":"CliffordNumbers.Hamming.hamming_number(w::Integer, n::Integer)\n\nGets the nth number with Hamming weight w. The first number with this Hamming weight (n = 1) is 2^w - 1.\n\nExample\n\njulia> CliffordNumbers.hamming_number(3, 2)\n11\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Indexing","page":"Internals","title":"Indexing","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.signmask\nCliffordNumbers._sort_with_parity!\nCliffordNumbers.bitindices_type","category":"page"},{"location":"api/internal.html#CliffordNumbers.signmask","page":"Internals","title":"CliffordNumbers.signmask","text":"CliffordNumbers.signmask([T::Type{<:Integer} = UInt], [signbit::Bool = true]) -> T\n\nGenerates a signmask, or a string of bits where the only 1 bit is the sign bit. If signbit is set to false, this returns zero (or whatever value is represented by all bits being 0).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers._sort_with_parity!","page":"Internals","title":"CliffordNumbers._sort_with_parity!","text":"CliffordNumbers._sort_with_parity!(v::AbstractVector{<:Real}) -> Tuple{typeof(v),Bool}\n\nPerforms a parity-tracking insertion sort of v, which modifies v in place. The function returns a tuple containing v and the parity, which is true for an odd permutation and false for an even permutation. This is implemented with a modified insertion sort algorithm.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.bitindices_type","page":"Internals","title":"CliffordNumbers.bitindices_type","text":"CliffordNumbers.bitindices_type(C::Type{<:AbstractCliffordNumber{Q,T}})\n\nRemoves extraneous type parameters from C, converting it to the least parameterized type that can be used to parameterize an AbstractBitIndices{Q,C} object. This is to avoid issues with the proliferation of type parameters that would construct identical BitIndices objects otherwise: for instance, BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Float32,4}}() and BitIndices{VGA(3),EvenCliffordNumber{VGA(3),Int}}() have identical elements, and are equal when compared with ==, but are not the same object.\n\nFor types defined in this package, this strips the scalar type parameter T and any length parameters present.\n\nExamples\n\njulia> CliffordNumbers.bitindices_type(CliffordNumber{VGA(3),Float32,8})\nCliffordNumber{VGA(3)}\n\njulia> CliffordNumbers.bitindices_type(KVector{2,STA,Bool})\nKVector{2,STA}\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Construction","page":"Internals","title":"Construction","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.zero_tuple\nCliffordNumbers.check_element_count","category":"page"},{"location":"api/internal.html#CliffordNumbers.zero_tuple","page":"Internals","title":"CliffordNumbers.zero_tuple","text":"CliffordNumbers.zero_tuple(::Type{T}, ::Val{L}) -> NTuple{L,T}\n\nGenerates a Tuple of length L with all elements being zero(T).\n\n\n\n\n\nCliffordNumbers.zero_tuple(::Type{C<:AbstractCliffordNumber})\n -> NTuple{nblades(C),scalar_type(C)}\n\nGenerates a Tuple that can be used to construct zero(C).\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.check_element_count","page":"Internals","title":"CliffordNumbers.check_element_count","text":"CliffordNumbers.check_element_count(sz, [L], data)\n\nEnsures that the number of elements in data is the same as the result of f(Q), where f is a function that generates the expected number of elements for the type. This function is used in the inner constructors of subtypes of AbstractCliffordNumber{Q} to ensure that the input has the correct length.\n\nIf provided, the length type parameter L can be included as an argument, and it will be checked for type (must be an Int) and value (must be equal to sz).\n\nThis function returns nothing, but throws an AssertionError for failed checks.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Multiplication-kernels","page":"Internals","title":"Multiplication kernels","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.mul\nCliffordNumbers.GradeFilter\nCliffordNumbers.nondegenerate_mask\nCliffordNumbers.mul_mask\nCliffordNumbers.mul_signs\nCliffordNumbers.bitindex_shuffle\nCliffordNumbers.widen_grade_for_mul","category":"page"},{"location":"api/internal.html#CliffordNumbers.mul","page":"Internals","title":"CliffordNumbers.mul","text":"CliffordNumbers.mul(\n x::AbstractCliffordNumber{Q},\n y::AbstractCliffordNumber{Q},\n [F::GradeFilter = GradeFilter{:*}()]\n)\n\nA fast geometric product implementation using generated functions for specific cases, and generic methods which either convert the arguments or fall back to other methods.\n\nThe arguments to this function should all agree in scalar type T. The * function, which exposes the fast geometric product implementation, promotes the scalar types of the arguments before utilizing this kernel. The scalar multiplication operations are implemented using muladd, allowing for hardware fma operations to be used when available.\n\nThe GradeFilter F allows for some blade multiplications to be excluded if they meet certain criteria. This is useful for implementing products besides the geometric product, such as the wedge product, which excludes multiplications between blades with shared vectors. Without a filter, this kernel just returns the geometric product.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.GradeFilter","page":"Internals","title":"CliffordNumbers.GradeFilter","text":"CliffordNumbers.GradeFilter{S}\n\nA type that can be used to filter certain products of blades in a geometric product multiplication. The type parameter S must be a Symbol. The single instance of GradeFilter{S} is a callable object which implements a function that takes two or more BitIndex{Q} objects a and b and returns false if the product of the blades indexed is zero.\n\nTo implement a grade filter for a product function f, define the following method: (::GradeFilter{:f})(::BitIndex{Q}, ::BitIndex{Q}) # Or if the definition allows for more arguments (::GradeFilter{:f})(::BitIndex{Q}...) where Q\n\n\n\n\n\n","category":"type"},{"location":"api/internal.html#CliffordNumbers.nondegenerate_mask","page":"Internals","title":"CliffordNumbers.nondegenerate_mask","text":"CliffordNumbers.nondegenerate_mask(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})\n\nConstructs a Boolean mask which is false for any multiplication that squares a degenerate blade; true otherwise.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.mul_mask","page":"Internals","title":"CliffordNumbers.mul_mask","text":"CliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})\nCliffordNumbers.mul_mask(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})\n\nCliffordNumbers.mul_mask(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})\nCliffordNumbers.mul_mask(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})\n\nGenerates a NTuple{L,Bool} which is true whenever the multiplication of the blade indexed by a and blades indexed by B is nonzero. false is returned if the grades multiply to zero due to the squaring of a degenerate component, or if they are filtered by F.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.mul_signs","page":"Internals","title":"CliffordNumbers.mul_signs","text":"CliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::NTuple{L,BitIndices{Q}})\nCliffordNumbers.mul_signs(F::GradeFilter, B::NTuple{L,BitIndices{Q}}, a::BitIndex{Q})\n\nCliffordNumbers.mul_signs(F::GradeFilter, a::BitIndex{Q}, B::BitIndices{Q})\nCliffordNumbers.mul_signs(F::GradeFilter, B::BitIndices{Q}, a::BitIndex{Q})\n\nGenerates an NTuple{L,Int8} which represents the sign associated with the multiplication needed to calculate components of a multiplication result.\n\nThis is equivalent to sign.(B) unless F === CliffordNumbers.GradeFilter{:dot}().\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.bitindex_shuffle","page":"Internals","title":"CliffordNumbers.bitindex_shuffle","text":"CliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::NTuple{L,BitIndex{Q}})\nCliffordNumbers.bitindex_shuffle(a::BitIndex{Q}, B::BitIndices{Q})\n\nCliffordNumbers.bitindex_shuffle(B::NTuple{L,BitIndex{Q}}, a::BitIndex{Q})\nCliffordNumbers.bitindex_shuffle(B::BitIndices{Q}, a::BitIndex{Q})\n\nPerforms the multiplication -a * b for each element of B for the above ordering, or -b * a for the below ordering, generating a reordered NTuple of BitIndex{Q} objects suitable for implementing a geometric product.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Taylor-series-exponential","page":"Internals","title":"Taylor series exponential","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.exp_taylor","category":"page"},{"location":"api/internal.html#CliffordNumbers.exp_taylor","page":"Internals","title":"CliffordNumbers.exp_taylor","text":"CliffordNumbers.exp_taylor(x::AbstractCliffordNumber, order = Val(16))\n\nCalculates the exponential of x using a Taylor expansion up to the specified order. In most cases, 12 is as sufficient number.\n\nNotes\n\n16 iterations is currently used because the number of loop iterations is not currently a performance bottleneck.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#Return-types-for-operations","page":"Internals","title":"Return types for operations","text":"","category":"section"},{"location":"api/internal.html","page":"Internals","title":"Internals","text":"CliffordNumbers.product_return_type\nCliffordNumbers.exponential_type","category":"page"},{"location":"api/internal.html#CliffordNumbers.product_return_type","page":"Internals","title":"CliffordNumbers.product_return_type","text":"CliffordNumbers.product_return_type(::Type{X}, ::Type{Y}, [::GradeFilter{S}])\n\nReturns a suitable type for representing the product of Clifford numbers of types X and Y. The GradeFilter{S} argument allows for the return type to be changed depending on the type of product. Without specialization on S, a type suitable for the geometric product is returned.\n\n\n\n\n\n","category":"function"},{"location":"api/internal.html#CliffordNumbers.exponential_type","page":"Internals","title":"CliffordNumbers.exponential_type","text":"CliffordNumbers.exponential_type(::Type{<:AbstractCliffordNumber})\nCliffordNumbers.exponential_type(x::AbstractCliffordNumber)\n\nReturns the type expected when exponentiating a Clifford number. This is an EvenCliffordNumber if the nonzero grades of the input are even, a CliffordNumber otherwise.\n\n\n\n\n\n","category":"function"},{"location":"numeric.html#Numeric-types","page":"Clifford number types","title":"Numeric types","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This package exports a variety of types that represents elements of Clifford algebras.","category":"page"},{"location":"numeric.html#AbstractCliffordNumber{Q,T}-and-subtypes","page":"Clifford number types","title":"AbstractCliffordNumber{Q,T} and subtypes","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The AbstractCliffordNumber{Q,T} type is the supertype for all implmentations of Clifford numbers. Q is a QuadraticForm, which describes the number of dimensions with positive, negative, and zero square, and T is a Union{Real,Complex} type of the coefficients.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"note: Future `StaticCliffordNumber{Q,T,L}` type\nWe may introduce a new abstract type, StaticCliffordNumber{Q,T,L}, for static implementations, like all of the ones provided by this package. These should be implemented as fixed length data structures (ideally an NTuple{L,T}).","category":"page"},{"location":"numeric.html#CliffordNumber{Q,T,L}:-full-grade-Clifford-numbers","page":"Clifford number types","title":"CliffordNumber{Q,T,L}: full grade Clifford numbers","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q,T,L} is the largest possible representation of a Clifford number, and it explicitly includes the coefficients for all 2^dimension(Q) basis blades.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"While this type is useful if working with objects that mix even and odd grades (for instance, projectors or left minimal ideals), it is often more efficient to work with a smaller type, like the ones described below.","category":"page"},{"location":"numeric.html#EvenCliffordNumber{Q,T,L}-and-OddCliffordNumber{Q,T,L}:-even-and-odd-graded-elements","page":"Clifford number types","title":"EvenCliffordNumber{Q,T,L} and OddCliffordNumber{Q,T,L}: even and odd graded elements","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"These types represent Clifford numbers of exclusively even or odd grade, respectively. These are the workhorses of geometric algebra, as they are produced through products of even or odd numbers of 1-blades. In the majority of cases, you can rely entirely on these types.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Internally, these are the same type: they alias CliffordNumbers.Z2CliffordNumber{P,Q,T,L}, where P is a Boolean parameter which is false for EvenCliffordNumber and true for OddCliffordNumber.","category":"page"},{"location":"numeric.html#KVector{K,Q,T,L}:-elements-of-homogeneous-grade","page":"Clifford number types","title":"KVector{K,Q,T,L}: elements of homogeneous grade","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This type represents a k-vector, or a Clifford number of homogeneous grade, with the parameter K indicating the grade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"It should be noted that in general, this type is not as efficient as EvenCliffordNumber, OddCliffordNumber, or CliffordNumber when calculating products (though this may change in the future). Use this type if your primary operations are addition, or if you need compact storage.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"However, there is one exception to this: KVector{0}, which represents a scalar. This type has been optimized so that operations with it are simply converted to scalar operations. Many operations on Clifford numbers that return scalars will return a KVector{0} to preserve the metric signature and other semantics associated with AbstractCliffordNumber.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"warning: Warning\nIt is important to note that k-vectors are not k-blades (the wedge product of k 1-vectors) or k-versors (the geometric product of k 1-vectors). In dimensions up to 3, all k-vectors are also k-blades, but this is not generally true: as a counterexample, e_1 e_2 + e_3 e_4 is not representable as a k-blade. However, all k-blades are k-vectors. k-versors usually consist of more than one grade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"note: Note\nIn the future, we may consider adding a DualKVector or PseudoKVector type to more easily represent pseudoscalars, pseudovectors, and related objects.","category":"page"},{"location":"numeric.html#Promotion-and-widening","page":"Clifford number types","title":"Promotion and widening","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"This package provides a robust promotion system for converting Clifford numbers and scalars to common types before performing common numeric operations.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"When promoting the types of Clifford numbers, there are two different types of promotions that can occur: scalar promotions, which promote all the scalar types of the arguments to a common scalar type, and grade promotions, which promote all the arguments to types which have a common set of grades. This package provides the scalar_promote function that allows for the scalar types of each argument to be promoted to a common type. Promote rules have been defined so that promote performs a scalar promotion and a grade promotion. No function currently promotes only the grades of the inputs.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The widen function in Julia Base widens an Number type to a type that can represent the result of addition or subtraction with the the input type without overflowing or losing precision. This functionality is passed through to Clifford numbers, but it only affects the scalar type, not the grades.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The widen_grade function performs an equivalent operation with the grades of a Clifford number, converting KVector to EvenCliffordNumber or OddCliffordNumber depending on the grade, and converting those to CliffordNumber. New AbstractCliffordNumber subtypes will widen directly to CliffordNumber by default, and this should be overridden for new types so that it widens to the smallest wider type.","category":"page"},{"location":"numeric.html#Construction-and-conversion","page":"Clifford number types","title":"Construction and conversion","text":"","category":"section"},{"location":"numeric.html#From-the-constructors","page":"Clifford number types","title":"From the constructors","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"The constructors of all AbstractCliffordNumber subtypes accept Tuple or Vararg arguments. In interactive use, you will probably use the latter. When defining a new type, you only need to define the (::Type{T})(::Tuple) constructors, as the Vararg constructors are automatically provided.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Some type parameters may be omitted in constructors, and the differences in behavior between these constructors is given below, using CliffordNumber as an example:","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q,T}(x...) converts all arguments x to type T.\nCliffordNumber{Q}(x...) promotes all arguments x to a common type T, so it is equivalent to CliffordNumber{Q,promote_type(typeof.(x)...)}(x).\nCliffordNumber(x...) is not a valid constructor, as an algebra must be specified.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"For types that include grade information, such as KVector, this information must be included to produce a valid constructor.","category":"page"},{"location":"numeric.html#Indices","page":"Clifford number types","title":"Indices","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"In most literature, the components of multivectors are listed in grade order. However, this ordering is not used here: instead, the natural binary ordering of blades is used.For a computer, each basis blade of an n-dimensional algebra can be represented with an n-bit integer: each of its binary digits correspond to the presence or absence of a vector composing the blade.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"For a concrete example, the coefficients of a CliffordNumber{VGA(3)} are ordered like so:","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"left(1 e_1 e_2 e_1 e_2 e_3 e_1 e_3 e_2 e_3 e_1 e_2 e_3right)","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Note how e_1 e_2 precedes e_3 here, but also note how the first four elements and the second four elements only differ by the presence of an e_3 factor.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber and its backing Tuple can be indexed straightforwardly with this relationship. The basis blade order of all AbstractCliffordNumber instances are identical, with smaller types like KVector{2,VGA(3)} skipping over all basis blades not of grade 2 in the list above.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"warning: Warning\nMany resources do not use a lexicographic order for the bivectors of the algebra of physical space or the spacetime algebra, opting for cyclic permutations so that e_3 e_1 is preferred over e_1 e_3. It's a good idea to check the convention before construction so you can include any necessary negative signs.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"As a workaround for the possibly unintuitive ordering of coefficients, you can also use sums of KVector instances: the sum will automatically promote to EvenCliffordNumber, OddCliffordNumber, or CliffordNumber as needed to represent all grades.","category":"page"},{"location":"numeric.html#Scalars","page":"Clifford number types","title":"Scalars","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"CliffordNumber{Q} and EvenCliffordNumber{Q} also accept a single scalar argument, and this constructs an object with all non-scalar blade coefficients being zero. By definition, KVector{0} does the same, and is the most efficient representation of a scalar associated with an algebra.","category":"page"},{"location":"numeric.html#From-other-Clifford-numbers","page":"Clifford number types","title":"From other Clifford numbers","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Clifford numbers can be constructed from other CliffordNumbers. This implicitly performs a grade projection operation, so this construction will always succeed, even if some of the basis blades of the input are lost. By contrast, conversion will throw an InexactError if the result does not contain all of the basis blades of the result.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"julia> test = CliffordNumber{VGA(3)}(1, 2, 3, 4, 5, 6, 7, 8)\n8-element CliffordNumber{VGA(3), Int64}:\n1 + 2σ₁ + 3σ₂ + 5σ₃ + 4σ₁σ₂ + 6σ₁σ₃ + 7σ₂σ₃ + 8σ₁σ₂σ₃\n\njulia> EvenCliffordNumber(test)\n4-element EvenCliffordNumber{VGA(3), Int64}:\n1 + 4σ₁σ₂ + 6σ₁σ₃ + 7σ₂σ₃\n\njulia> convert(EvenCliffordNumber, test)\nERROR: InexactError: ...","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"danger: Danger\nThis is an extremely important point: construction of a Clifford number type with fewer grades than the input performs a grade projection operation without throwing an error. However, conversion will throw an error if the grades of the input value are not present in the input type.This is not how other subtypes of Number defined by Julia Base behave, as their conversion operations are generally defined to be identical to the constructor, and always throw the same error for a given pair of type and value.If converting an AbstractCliffordNumber to any other numeric type, construction and conversion behave identically, as expected.","category":"page"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"Construction and conversion of Clifford numbers from other Clifford numbers the only time that the quadratic form type parameter can be omitted, as it can be inferred directly from the input. In the case of CliffordNumbers.Z2CliffordNumber, the parity type parameter can also be inferred from a KVector input.","category":"page"},{"location":"numeric.html#Scalar-conversion","page":"Clifford number types","title":"Scalar conversion","text":"","category":"section"},{"location":"numeric.html","page":"Clifford number types","title":"Clifford number types","text":"It may be desirable to convert the scalar type of a Clifford number without having to specify the full typename of the desired output type. The function scalar_convert(T, x) takes a type T<:Union{Real,Complex} and any Clifford number x and converts its scalar type to T. If x is a Real or Complex, it just converts x to an instance of T.","category":"page"},{"location":"indexing.html#Indexing","page":"Indexing","title":"Indexing","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Indexing is a critical operation in linear algebra: it would be difficult to imagine defining operations on vectors, matrices, and arrays without some way of determining the coefficient at a particular location in the object. Similarly, we often want to extract coefficients from multivectors to perform operations.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"However, the philosophy of this package – treating multivectors a number system on the same footing as that of complex numbers or quaternions – means that the AbstractCliffordNumber type foregoes array semantics. All AbstractCliffordNumber instances broadcast as scalars: for two instances x and y, x * y is identical to x .* y, both of which calculate the geometric product.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"On top of this, the grade representation of multivectors makes it difficult to relate the indices of the backing Tuple for each type to the blades represented by the multivector for anything other than the dense CliffordNumber. To solve this issue, this package provides types specifically intended for indexing AbstractCliffordNumber subtypes: BitIndex{Q} and the subtypes of AbstractBitIndices{Q,C}, BitIndices{Q,C} and TransformedBitIndices{Q,C}.","category":"page"},{"location":"indexing.html#BitIndex{Q}","page":"Indexing","title":"BitIndex{Q}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The BitIndex{Q} type is the index type for AbstractCliffordNumber{Q}. This types wraps a UInt: the first dimension(Q) bits represent the presence or absence of the basis vectors associated with each dimension that are used to construct the indexed blade. The most significant bit is a sign bit: this is needed to represent the parity associated with the order of wedge products used to construct the blade.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Regardless of what position in the underlying Tuple a coefficient may be, if x == y, then the same BitIndex b will index x and y identically:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k = KVector{1,VGA(3)}(4,2,0)\n3-element KVector{1, VGA(3), Int64}:\n4e₁ + 2e₂\n\njulia> b = BitIndex(k, 1)\nBitIndex(Val(VGA(3)), 1)\n\njulia> k == OddCliffordNumber(k)\ntrue\n\njulia> k[b] == OddCliffordNumber(k)[b]\ntrue","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"It should also be noted that indexing an AbstractCliffordNumber at an index which is not explicitly represented by the type returns zero:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k[BitIndex(k, 1, 2)]\n0\n","category":"page"},{"location":"indexing.html#Construction","page":"Indexing","title":"Construction","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The internal constructor BitIndex{Q}(signbit::Bool, blade::Unsigned) converts blade to a UInt and changes the most significant bit to match signbit. However, in many cases, constructing a BitIndex{Q} directly from the sign bit and representation of the blade as an unsigned integer is inconvenient.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"For this reason, we define two constructors, the first being BitIndex(::Val{Q}, i::Integer...), which takes the algebra Q wrapped in Val (for reasons of type stability) and the integers i corresponding to basis blade indices defined in Q. The second constructor, BitIndex(x, i::Integer...) calls BitIndex(Val(signature(x))), i...), automatically determining Q.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In both cases, the parity of the permutation of indices is determined automatically from the integer arguments, so this bit is automatically assigned. The presence of a parity bit allows for correct indexing with non-lexicographic conventions: in some literature, e_3 e_1 is used instead of e_1 e_3 for one of the bivector components of APS and STA.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> l = KVector{2,VGA(3)}(0,6,9)\n3-element KVector{2, VGA(3), Int64}:\n6e₁e₃ + 9e₂e₃\n\njulia> l[BitIndex(l, 1, 3)]\n6\n\njulia> l[BitIndex(l, 3, 1)]\n-6","category":"page"},{"location":"indexing.html#Tuples-of-BitIndex{Q}","page":"Indexing","title":"Tuples of BitIndex{Q}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Julia AbstractArray instances can be indexed not just with integers, but with arrays of integers or special objects representing iterable ranges, such as :. Perhaps surprisingly, tuples containing integers (or any other valid index object) are not valid indices of AbstractArray:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> (1:10)[(2, 3, 4)]\nERROR: ArgumentError: invalid index: (2, 3, 4) of type Tuple{Int64, Int64, Int64}\n","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In the case of AbstractCliffordNumber, we have a compelling reason to use tuples of BitIndex{Q} objects for indexing: since the length of a Tuple is known statically, we can use that information to construct a new Tuple of coefficients with statically known length, which may be useful if we want to leverage indexing to convert types. Therefore, indexing an AbstractCliffordNumber{Q,T} with an NTuple{N,BitIndex{Q}} returns an NTuple{N,T}, which can be fed into the constructor for a different type, and this is what the package uses internally to perform conversion.","category":"page"},{"location":"indexing.html#Operations","page":"Indexing","title":"Operations","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"BitIndex{Q} supports a variety of unary and binary operations, many of which are used internally for tasks like calculating geometric products. Many of these operations are also supported for AbstractCliffordNumber{Q} instances, such as negation (-) and the geometric product (*).","category":"page"},{"location":"indexing.html#AbstractBitIndices{Q,C}","page":"Indexing","title":"AbstractBitIndices{Q,C}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"Considering that the indices of an AbstractCliffordNumber provided by this package are known from the type, it makes sense to define a type which represents all indices of a subtype or instance of AbstractCliffordNumber. This package defines the supertype AbstractBitIndices{Q,C} and concrete types BitIndices{Q,C} and TransformedBitIndices{Q,C,F} that allow for easy operation across all valid indices of a type C.","category":"page"},{"location":"indexing.html#BitIndices{Q,C}","page":"Indexing","title":"BitIndices{Q,C}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The BitIndices object for an AbstractCliffordNumber subtype C or instance x can be constructed with BitIndices(C) or BitIndices(x). This is a singleton type which is also returned by eachindex(x).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"The type information of the BitIndices object is used to determine the type of the result of indexing. Conveniently, you can index one Clifford number x with the indices of another Clifford number y, and this converts x to the a type similar to that of y, but retaining the element type of x:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"julia> k = KVector{1,VGA(3)}(4,2,0) # eltype Int64\n3-element KVector{1, VGA(3), Int64}:\n4e₁ + 2e₂\n\njulia> z = zero(CliffordNumber{VGA(3),Float64}) # eltype Float64\n8-element CliffordNumber{VGA(3), Float64}:\n0.0\n\njulia> k[BitIndices(ans)]\n8-element CliffordNumber{VGA(3), Int64}:\n4e₁ + 2e₂\n","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"BitIndices{Q,C} subtypes AbstractBitIndices{Q,C}, which subtypes AbstractVector{BitIndex{Q}}, meaning that the objects can be indexed with integers. This indexing is one-based to match the indices of the Tuple backing a CliffordNumber, but this is subject to change in the future.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"warning: Avoiding type proliferation with `BitIndices`\nOne fundamental issue with BitIndices{Q,C} is that C is only constrained to be a subtype of AbstractCliffordNumber{Q}. However, C may have other type parameters that vary, but produce objects that index equivalently and are identical elementwise:julia> BitIndices{STA,CliffordNumber{STA}}() == BitIndices{STA,CliffordNumber{STA,Float32}}()\ntrue\n\njulia> BitIndices{STA,CliffordNumber{STA}}() == BitIndices{STA,CliffordNumber{STA,Float32,8}}()\ntrue For this reason, you should call BitIndices(x) or BitIndices(C) instead of directly constructing BitIndices{Q,C}().","category":"page"},{"location":"indexing.html#TransformedBitIndices{Q,C,F}","page":"Indexing","title":"TransformedBitIndices{Q,C,F}","text":"","category":"section"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"If we want to perform a transformation on all elements of a BitIndices instance, we may use dot syntax and broadcast an operation: for instance, reverse.(BitIndices(x)) to obtain the reverse of all indices. Without any explicit specification of behavior, this will return a Vector, and for the sake of performance we'd like to avoid returning types without statically known lengths.","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"We could solve this by converting BitIndices to a Tuple internally as part of the broadcasting implementation, but doing this will cause its own set of problems: indexing an AbstractCliffordNumber with a Tuple returns a Tuple. This may be fine internally, if we know to call the constructor, but this is potentially confusing for new users. For this reason, we provide TransformedBitIndices{Q,C,F}, which is a lazy representation of a function applied to every element of BitIndices(C).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"For convenience, we provide a few aliases for operations which are commonly used with BitIndices:","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"ReversedBitIndices{Q,C} is the type of reverse.(::BitIndices{Q,C}).\nGradeInvolutedBitIndices{Q,C} is the type of grade_involution.(::BitIndices{Q,C}).\nConjugatedBitIndices{Q,C} is the type of conj.(::BitIndices{Q,C}).","category":"page"},{"location":"indexing.html","page":"Indexing","title":"Indexing","text":"In the future, we may override some broadcast implementations to ensure that all of these types are interconvertible with each other and with BitIndices{Q,C}.","category":"page"},{"location":"api/clifford.html#Clifford-numbers","page":"CliffordNumbers","title":"Clifford numbers","text":"","category":"section"},{"location":"api/clifford.html#Supertype-and-associated-functions","page":"CliffordNumbers","title":"Supertype and associated functions","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.AbstractCliffordNumber\nCliffordNumbers.nblades\nCliffordNumbers.scalar_type\nCliffordNumbers.similar_type","category":"page"},{"location":"api/clifford.html#CliffordNumbers.AbstractCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.AbstractCliffordNumber","text":"AbstractCliffordNumber{Q,T} <: Number\n\nAn element of a Clifford algebra, often referred to as a multivector, with quadratic form Q and element type T. These are statically size and therefore should be able to be stored inline in arrays or other data structures,\n\nInterface\n\nRequired implementation\n\nAll subtypes C of AbstractCliffordNumber{Q} must implement the following functions:\n\nCliffordNumbers.similar_type(::Type{C}, ::Type{T}, ::Type{Q}) where {C,T,Q} should construct a\n\nnew type similar to C which subtypes AbstractCliffordNumber{Q,T} that may serve as a constructor.\n\nBase.getindex(x::C, b::BitIndex{Q}) should allow one to recover the coefficients associated\n\nwith each basis blade represented by C.\n\nnblades(::Type{C}) should be defined to return the number of basis blades represented by the\n\ntype. By default, nblades(x::AbstractCliffordNumber) = nblades(typeof(x)).\n\nBase.Tuple(x::C) should return the tuple used to construct x. The fallback is\n\ngetfield(x, :data)::Tuple, so any type declared with a NTuple field named data should have this defined automatically.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.nblades","page":"CliffordNumbers","title":"CliffordNumbers.nblades","text":"nblades(::Type{<:Number}) -> Int\nnblades(x::Number)\n\nReturns the number of blades represented by a Number subtype or instance. For subtypes of Number that are not AbstractCliffordNumber, this is always 1.\n\nThis function is separate from Base.length since AbstractCliffordNumber is a scalar type for which collect() returns a zero-dimensional array. For consistency, length(x) should always equal length(collect(x)).\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.scalar_type","page":"CliffordNumbers","title":"CliffordNumbers.scalar_type","text":"scalar_type(::Type{<:AbstractCliffordNumber{Q,T}}) = T\nscalar_type(T::Type{<:Union{Real,Complex}}) = T\nscalar_type(x) = scalar_type(typeof(x))\n\nReturns the numeric type associated with an AbstractCliffordNumber instance. For subtypes of Real and Complex, or their instances, this simply returns the input type or instance type.\n\nWhy not define eltype?\n\nAbstractCliffordNumber instances behave like numbers, not arrays. If collect() is called on a Clifford number of type T, it should not construct a vector of coefficients; instead it should return an Array{T,0}. Similarly, a broadcasted multiplication should return the same result as normal multiplication, as is the case with complex numbers.\n\nFor subtypes T of Number, eltype(T) === T, and this is true for AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.similar_type","page":"CliffordNumbers","title":"CliffordNumbers.similar_type","text":"CliffordNumbers.similar_type(\n C::Type{<:AbstractCliffordNumber},\n [N::Type{<:BaseNumber} = scalar_type(C)],\n [Q::Val = Val(signature(C))]\n) -> Type{<:AbstractCliffordNumber{Q,N}}\n\nConstructs a type similar to T but with numeric type N and quadratic form Q. The quadratic form must be wrapped in a Val to preserve type stability.\n\nThis function must be defined with all its arguments for each concrete type subtyping AbstractCliffordNumber.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Concrete-types","page":"CliffordNumbers","title":"Concrete types","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.CliffordNumber\nCliffordNumbers.Z2CliffordNumber\nCliffordNumbers.EvenCliffordNumber\nCliffordNumbers.OddCliffordNumber\nCliffordNumbers.KVector\nCliffordNumbers.grade(::Type{<:KVector{K}}) where K","category":"page"},{"location":"api/clifford.html#CliffordNumbers.CliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.CliffordNumber","text":"CliffordNumber{Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA dense multivector (or Clifford number), with quadratic form Q, element type T, and length L (which depends entirely on Q).\n\nThe coefficients are ordered by taking advantage of the natural binary structure of the basis. The grade of an element is given by the Hamming weight of its index. For the algebra of physical space, the order is: 1, e₁, e₂, e₁₂, e₃, e₁₃, e₂₃, e₁₂₃ = i. This order allows for more aggressive SIMD optimization when calculating the geometric product.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.Z2CliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.Z2CliffordNumber","text":"CliffordNumbers.Z2CliffordNumber{P,Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA Clifford number whose only nonzero grades are even or odd. Clifford numbers of this form naturally arise as versors, the geometric product of 1-vectors.\n\nThe type parameter P is constrained to be a Bool: true for odd grade Clifford numbers, and false for even grade Clifford numbers, corresponding to the Boolean result of each grade modulo 2.\n\nType aliases\n\nThis type is not exported, and usually you will want to refer to the following aliases:\n\nconst EvenCliffordNumber{Q,T,L} = Z2CliffordNumber{false,Q,T,L}\nconst OddCliffordNumber{Q,T,L} = Z2CliffordNumber{true,Q,T,L}\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.EvenCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.EvenCliffordNumber","text":"EvenCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{false,Q,T,L})\n\nA Clifford number whose only nonzero grades are even. These are the natural choice of representation for rotors and motors (Euclidean isometries preserving orientation, or \"proper\" isometries), as well as their composition with dilations.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.OddCliffordNumber","page":"CliffordNumbers","title":"CliffordNumbers.OddCliffordNumber","text":"OddCliffordNumber{P,Q,T,L} (alias for CliffordNumbers.Z2CliffordNumber{true,Q,T,L})\n\nA Clifford number whose only nonzero grades are odd. These are the natural choice of representation for reflections, as well as their compositions with rotors and motors (Euclidean isometries preserving orientation, or \"proper\" isometries), as well as their composition with dilations.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.KVector","page":"CliffordNumbers","title":"CliffordNumbers.KVector","text":"KVector{K,Q,T,L} <: AbstractCliffordNumber{Q,T}\n\nA multivector consisting only linear combinations of basis blades of grade K - in other words, a k-vector.\n\nk-vectors have binomial(dimension(Q), K) components.\n\n\n\n\n\n","category":"type"},{"location":"api/clifford.html#CliffordNumbers.grade-Union{Tuple{Type{<:KVector{K}}}, Tuple{K}} where K","page":"CliffordNumbers","title":"CliffordNumbers.grade","text":"grade(::Type{<:KVector{K}}) = K\ngrade(x::KVector{K}) = k\n\nReturns the grade represented by a KVector{K}, which is K.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Promotion-and-conversion","page":"CliffordNumbers","title":"Promotion and conversion","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.scalar_convert\nCliffordNumbers.scalar_promote\nBase.widen(::Type{<:AbstractCliffordNumber{Q,T}}) where {Q,T}\nCliffordNumbers.widen_grade","category":"page"},{"location":"api/clifford.html#CliffordNumbers.scalar_convert","page":"CliffordNumbers","title":"CliffordNumbers.scalar_convert","text":"scalar_convert(T::Type{<:Union{Real,Complex}}, x::AbstractCliffordNumber) -> T\nscalar_convert(T::Type{<:Union{Real,Complex}}, x::Union{Real,Complex}) -> T\n\nIf x is an AbstractCliffordNumber, converts the scalars of x to type T.\n\nIf x is a Real or Complex, converts x to T.\n\nExamples\n\njulia> scalar_convert(Float32, KVector{1,APS}(1, 2, 3))\n3-element KVector{1, VGA(3), Float32}:\n1.0σ₁ + 2.0σ₂ + 3.0σ\n\njulia> scalar_convert(Float32, 2)\n2.0f0\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.scalar_promote","page":"CliffordNumbers","title":"CliffordNumbers.scalar_promote","text":"scalar_promote(x::AbstractCliffordNumber, y::AbstractCliffordNumber)\n\nPromotes the scalar types of x and y to a common type. This does not increase the number of represented grades of either x or y.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Base.widen-Union{Tuple{Type{<:AbstractCliffordNumber{Q, T}}}, Tuple{T}, Tuple{Q}} where {Q, T}","page":"CliffordNumbers","title":"Base.widen","text":"widen(C::Type{<:AbstractCliffordNumber})\nwiden(x::AbstractCliffordNumber)\n\nConstruct a new type whose scalar type is widened. This behavior matches that of widen(C::Type{Complex{T}}), which results in widening of its scalar type T.\n\nFor obtaining a representation of a Clifford number with an increased number of nonzero grades, use widen_grade(T).\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#CliffordNumbers.widen_grade","page":"CliffordNumbers","title":"CliffordNumbers.widen_grade","text":"widen_grade(C::Type{<:AbstractCliffordNumber})\nwiden_grade(x::AbstractCliffordNumber)\n\nFor type arguments, construct the next largest type that can hold all of the grades of C. KVector{K,Q,T} widens to EvenCliffordNumber{Q,T} or OddCliffordNumber{Q,T}, and EvenCliffordNumber{Q,T} and OddCliffordNumber{Q,T} widen to CliffordNumber{Q,T}, which is the widest type.\n\nFor AbstractCliffordNumber arguments, the argument is converted to the result of widen_grade(typeof(x)).\n\nFor widening the scalar type of an AbstractCliffordNumber, use Base.widen(T).\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#Real-and-complex-algebras","page":"CliffordNumbers","title":"Real and complex algebras","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"Base.real(::AbstractCliffordNumber)\nBase.complex(::AbstractCliffordNumber)","category":"page"},{"location":"api/clifford.html#Base.real-Tuple{AbstractCliffordNumber}","page":"CliffordNumbers","title":"Base.real","text":"real(x::AbstractCliffordNumber{Q,T})\n\nGets the real portion of each coefficient of x. For T<:Real this operation does nothing; for T<:Complex{S} this an AbstractCliffordNumber{Q,S}.\n\nNote that this does not return the scalar (grade 0) coefficient of x. Use real(scalar(x)) to obtain this result.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Base.complex-Tuple{AbstractCliffordNumber}","page":"CliffordNumbers","title":"Base.complex","text":"complex(x::AbstractCliffordNumber, [y::AbstractCliffordNumber = zero(typeof(x))])\n\nFor a single argument x, converts the type of each coefficient to a suitable complex type.\n\nFor two arguments x and y, which are both real Clifford numbers, performs the sum x + y*im, constructing a complex Clifford number.\n\nNote that this operation does not isolate a scalar (grade 0) coefficient of x or y. Use complex(scalar(x), [scalar(y)]) to obtain this result.\n\n\n\n\n\n","category":"method"},{"location":"api/clifford.html#Scalar-and-pseudoscalar-components","page":"CliffordNumbers","title":"Scalar and pseudoscalar components","text":"","category":"section"},{"location":"api/clifford.html","page":"CliffordNumbers","title":"CliffordNumbers","text":"CliffordNumbers.isscalar\nCliffordNumbers.ispseudoscalar\nCliffordNumbers.scalar","category":"page"},{"location":"api/clifford.html#CliffordNumbers.isscalar","page":"CliffordNumbers","title":"CliffordNumbers.isscalar","text":"isscalar(x::AbstractCliffordNumber)\n\nDetermines whether the Clifford number x is a scalar, meaning that all of its blades of nonzero grade are zero.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.ispseudoscalar","page":"CliffordNumbers","title":"CliffordNumbers.ispseudoscalar","text":"ispseudoscalar(m::AbstractCliffordNumber)\n\nDetermines whether the Clifford number x is a pseudoscalar, meaning that all of its blades with grades below the dimension of the space are zero.\n\n\n\n\n\n","category":"function"},{"location":"api/clifford.html#CliffordNumbers.scalar","page":"CliffordNumbers","title":"CliffordNumbers.scalar","text":"scalar(x::AbstractCliffordNumber{Q,T}) -> T\n\nReturns the scalar portion of x as its scalar type. This is equivalent to x[scalar_index(x)].\n\nTo retain Clifford number semantics, use the KVector{0} constructor.\n\n\n\n\n\n","category":"function"},{"location":"operations.html#Operations","page":"Operations","title":"Operations","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Like with other numbers, standard mathematical operations are supported that relate Clifford numbers to elements of their scalar field and to each other.","category":"page"},{"location":"operations.html#Unary-operations","page":"Operations","title":"Unary operations","text":"","category":"section"},{"location":"operations.html#Grade-automorphisms","page":"Operations","title":"Grade automorphisms","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade automorphisms are operations which preserves the grades of each basis blade, but changes their sign depending on the grade. All of these operations are their own inverse.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"All grade automorphisms are applicable to BitIndex objects, and the way they are implemented is through constructors that use TransformedBitIndices objects to alter each grade.","category":"page"},{"location":"operations.html#Reverse","page":"Operations","title":"Reverse","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The reverse is an operation which reverses the order of the wedge product that constructed each basis blade. This is implemented with methods for Base.reverse and Base.:~.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"note: Syntax changes\nIn the future, Base.:~ will no longer be used for this operation; instead Base.adjoint will be overloaded, providing ' as a syntax for the reverse.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"This is the most commonly used automorphism, and in a sense can be thought of as equivalent to complex conjugation. When working with even elements of the algebras of 2D or 3D space, this behaves identically to complex conjugation and quaternion conjugation. However, this is not the case when working in the even subalgebras.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Base.reverse(::BitIndex)","category":"page"},{"location":"operations.html#Grade-involution","page":"Operations","title":"Grade involution","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade involution changes the sign of all odd grades, an operation equivalent to mirroring every basis vector of the space. This can be acheived with the grade_involution function.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"When interpreting even multivectors as elements of the even subalgebra of the algebra of interest, the grade involution in the even subalgebra is equivalent to the reverse in the algebra of interest.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Grade involution is equivalent to complex conjugation in when dealing with the even subalgebra of 2D space, which is isomorphic to the complex numbers, but this is not true for quaternion conjugation. Instead, use the Clifford conjugate (described below).","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"CliffordNumbers.grade_involution(::BitIndex)","category":"page"},{"location":"operations.html#Clifford-conjugation","page":"Operations","title":"Clifford conjugation","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The Clifford conjugate is the combination of the reverse and grade involution. This is available via an overload of Base.conj.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"warning: Warning\nconj(::AbstractCliffordNumber) implements the Clifford conjugate, not the reverse!","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"When dealing with the even subalgebras of 2D and 3D VGAs, which are isomorphic to the complex numbers and quaternions, respectively, the Clifford conjugate is equivalent to complex conjugation or quaternion conjugation. Otherwise, this is a less widely used operation than the above two.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Base.conj(::BitIndex)","category":"page"},{"location":"operations.html#Binary-operations","page":"Operations","title":"Binary operations","text":"","category":"section"},{"location":"operations.html#Addition-and-subtraction","page":"Operations","title":"Addition and subtraction","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Addition and subtraction work as expected for Clifford numbers just as they do for other numbers. The promotion system handles all cases where objects of mixed type are added.","category":"page"},{"location":"operations.html#Products","page":"Operations","title":"Products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Clifford algebras admit a variety of products. Common ones are implemented with infix operators.","category":"page"},{"location":"operations.html#Geometric-product","page":"Operations","title":"Geometric product","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The geometric product, or Clifford product, is the defining product of the Clifford algebra. This is implemented with the usual multiplication operator *, but it is also possible to use parenthetical notation as it is with real numbers.","category":"page"},{"location":"operations.html#Wedge-product","page":"Operations","title":"Wedge product","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The wedge product is the defining product of the exterior algebra. This is available with the wedge() function, or with the ∧ infix operator.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"tip: Tip\nYou can define elements of exterior algebras directly by using Metrics.Exterior(D), whose geometric product is equivalent to the wedge product.","category":"page"},{"location":"operations.html#Contractions-and-dot-products","page":"Operations","title":"Contractions and dot products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The contraction operations generalize the dot product of vectors to Clifford numbers. While it is possible to define a symmetric dot product (and one is provided in this package), the generalization of the dot product to Clifford numbers is naturally asymmetric in cases where the grade of one input blade is not equal to that of the other.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"For Clifford numbers x and y, the left contraction x ⨼ y describes the result of projecting x onto the space spanned by y. If x and y are homogeneous in grade, this product is equal to the geometric product if grade(y) ≥ grade(x), and zero otherwise. For general multivectors, the left contraction can be calculated by applying this rule to the products of their basis blades.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The analogous right contraction is only nonzero if grade(x) ≥ grade(y), and it can be calculated with ⨽.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The dot product is a symmetric variation of the left and right contractions, and provides a looser constraint on the basis blades: grade(CliffordNumbers.dot(x,y)) must equal abs(grade(x) - grade(y)). The Hestenes dot product is equivalent to the dot product above, but is zero if either x or y is a scalar.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"note: Note\nCurrently, the dot product is implemented with the unexported function CliffordNumbers.dot. This package does not depend on LinearAlgebra, so there would be a name conflict if this method were exported and both this package and LinearAlgebra were loaded.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Contractions are generally favored over the dot products due to their nicer implementations and properties, which have fewer exceptions. It is generally recommended that the Hestenes dot product be avoided, though it is included in this library for the sake of completeness as CliffordNumber.hestenes_dot, which is also not exported.","category":"page"},{"location":"operations.html#Commutator-and-anticommutator-products","page":"Operations","title":"Commutator and anticommutator products","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The commutator product (or antisymmetric product) of Clifford numbers x and y, denoted x × y, is equal to 1//2 * (x*y - y*x). This product is nonzero if the geometric product of x and y does not commute, and the value represents the degree to which they fail to commute.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The commutator product is the building block of Lie algebras; in particular, the commutator products of bivectors, which are also bivectors. With the bivectors of 3D space, the Lie algebra is equivalent to that generated by the cross product, hence the × notation.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"The analogous anticommutator product (or symmetric product) is 1//2 * (x*y + y*x). This uses the ⨰ operator, which is not an operator generally used for this purpose, but was selected as it looks similar to the commutator product, with the dot indicating the similarity with the dot product, which is also symmetric.","category":"page"},{"location":"operations.html#Defining-new-products:-Multiplication-internals","page":"Operations","title":"Defining new products: Multiplication internals","text":"","category":"section"},{"location":"operations.html","page":"Operations","title":"Operations","text":"Products are implemented with the fast multiplication kernel CliffordNumbers.mul, which accepts two Clifford numbers with the same scalar type and a CliffordNumbers.GradeFilter object. This GradeFilter object defines a method that takes two or more BitIndex objects and returns false if their product is constrained to be zero.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"CliffordNumbers.mul requires that the coefficient types of the numbers being multiplied are the same. Methods which leverage CliffordNumbers.mul should promote the coefficient types of the arguments to a common type using scalar_promote before passing them to the kernel. Any further promotion needed to return the final result is handled by the kernel.","category":"page"},{"location":"operations.html","page":"Operations","title":"Operations","text":"In general, it is also strongly recommended to promote the types of the arguments to CliffordNumbers.Z2CliffordNumber or CliffordNumber for higher performance. Currently, the implementation of CliffordNumbers.mul is asymmetric, and does not consider which input is longer. Even in the preferred order, we find that KVector incurs a significant performance penalty.","category":"page"}] }