Grades and indices
Grades
CliffordNumbers.nonzero_grades
— Functionnonzero_grades(::Type{<:AbstractCliffordNumber{Q}}) -> AbstractVector{Int}
nonzero_grades(::Number)
Returns an AbstractVector{Int}
whose elements are all nonzero grades of a Clifford number or type. Any subtype T
of AbstractCliffordNumber
should define this method for Type{T}
; it is automatically implemented for instance arguments.
For arguments that are Real
or Complex
, this function returns 0:0
.
Examples
julia> CliffordNumbers.nonzero_grades(CliffordNumber{VGA(3)})
0:3
julia> CliffordNumbers.nonzero_grades(EvenCliffordNumber{VGA(3)})
0:2:2
julia> CliffordNumbers.nonzero_grades(KVector{2,VGA(3)})
2:2
julia> nonzero_grades(Float64)
0:0
CliffordNumbers.has_grades_of
— Functionhas_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.
BitIndex
CliffordNumbers.BitIndex
— TypeBitIndex{Q}
A representation of an index corresponding to a basis blade of the geometric algebra with quadratic form Q
.
CliffordNumbers.is_same_blade
— FunctionCliffordNumbers.is_same_blade(a::BitIndex{Q}, b::BitIndex{Q})
Checks if a
and b
perform identical indexing up to sign.
Special indices
CliffordNumbers.scalar_index
— Functionscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}
Constructs the BitIndex
used to obtain the scalar (grade zero) portion of x
.
CliffordNumbers.pseudoscalar_index
— Functionpseudoscalar_index(x::AbstractCliffordNumber{Q}) -> BitIndex{Q}
Constructs the BitIndex
used to obtain the pseudoscalar (highest grade) portion of x
.
Tools for implementing mathematical operations
Base.reverse
— Methodreverse(i::BitIndex) = i' -> BitIndex
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
.
CliffordNumbers.grade_involution
— Methodgrade_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.
Base.conj
— Methodconj(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))
.
CliffordNumbers.left_complement
— Methodleft_complement(b::BitIndex{Q}) -> BitIndex{Q}
Returns the left complement of b
, define so that left_complement(b) * b
generates the pseudoscalar index of elements of the algebra Q
.
When the left complement is applied twice, the original BitIndex
object is returned up to a change of sign, given by (-1)^(grade(b) * (dimension(Q) - grade(b))). This implies that in algebras of odd dimension, the left complement and [right complement](@ref right_complement) are identical because either
grade(b)or
dimension(Q) - grade(b)must be even. The complement is independent of the signature of
Q`, depending only on the dimension.
Lengyel's convention for the left complement is an underbar.
CliffordNumbers.right_complement
— Methodright_complement(b::BitIndex{Q}) -> BitIndex{Q}
Returns the right complement of b
, define so that b * right_complement(b)
generates the pseudoscalar index of elements of the algebra Q
.
When the right complement is applied twice, the original BitIndex
object is returned up to a change of sign, given by (-1)^(grade(b) * (dimension(Q) - grade(b))). This implies that in algebras of odd dimension, the [left complement](@ref left_complement) and right complement are identical because either
grade(b)or
dimension(Q) - grade(b)must be even. The complement is independent of the signature of
Q`, depending only on the dimension.
Lengyel's convention for the right complement is an overbar.
CliffordNumbers.grade
— Methodgrade(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))
).
CliffordNumbers.sign_of_square
— FunctionCliffordNumbers.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)
.
CliffordNumbers.signbit_of_square
— FunctionCliffordNumbers.signbit_of_square(b::BitIndex) -> Bool
Returns the signbit associated with squaring the basis blade indexed by b
.
For basis blades squaring to zero, the result is not meaningful.
CliffordNumbers.nondegenerate_square
— FunctionCliffordNumbers.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
.
CliffordNumbers.sign_of_mult
— FunctionCliffordNumbers.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.
CliffordNumbers.signbit_of_mult
— FunctionCliffordNumbers.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.
CliffordNumbers.nondegenerate_mult
— FunctionCliffordNumbers.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
.
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
.
CliffordNumbers.has_wedge
— FunctionCliffordNumbers.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.
BitIndices
and related types
CliffordNumbers.AbstractBitIndices
— TypeAbstractBitIndices{Q,C<:AbstractCliffordNumber{Q}} <: AbstractVector{BitIndex{Q}}
Supertype for vectors containing all valid BitIndex{Q}
objects for the basis elements represented by C
.
CliffordNumbers.BitIndices
— TypeBitIndices{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.
CliffordNumbers.TransformedBitIndices
— TypeTransformedBitIndices{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.