Skip to content

Commit

Permalink
Added left and right complements of basis blades
Browse files Browse the repository at this point in the history
  • Loading branch information
brainandforce committed Jun 2, 2024
1 parent 0717fb2 commit 09aa25f
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/src/api/indexing.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ CliffordNumbers.pseudoscalar_index
Base.reverse(::BitIndex)
CliffordNumbers.grade_involution(::BitIndex)
Base.conj(::BitIndex)
CliffordNumbers.left_complement
CliffordNumbers.right_complement
```

```@docs
Expand Down
3 changes: 2 additions & 1 deletion src/CliffordNumbers.jl
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ export nonzero_grades, has_grades_of
# Indexing each graded element of an AbstractCliffordNumber
include("bitindex.jl")
export BitIndex
export grade, scalar_index, pseudoscalar_index, grade_involution, dual, undual
export grade, scalar_index, pseudoscalar_index, grade_involution, dual, undual, left_complement,
right_complement
include("bitindices.jl")
export AbstractBitIndices, BitIndices, TransformedBitIndices, ReversedBitIndices,
GradeInvolutedBitIndices, ConjugatedBitIndices
Expand Down
32 changes: 32 additions & 0 deletions src/bitindex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,35 @@ end

dual(b::BitIndex{Q}) where Q = b * BitIndex{Q}(false, typemax(UInt))
undual(b::BitIndex{Q}) where Q = b * BitIndex{Q}(!iszero(dimension(Q) & 2), typemax(UInt))

"""
left_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.
"""
left_complement(b::BitIndex{Q}) where Q = BitIndex{Q}(false, typemax(UInt)) * b'

"""
right_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.
"""
right_complement(b::BitIndex{Q}) where Q = b' * BitIndex{Q}(false, typemax(UInt))
38 changes: 38 additions & 0 deletions test/indexing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,44 @@
@test eval(Meta.parse(repr(BitIndex(Val{VGA(3)}(), 2, 1)))) === BitIndex(Val(VGA(3)), 2, 1)
end

@testset "Complements" begin
b = BitIndex(Val(VGA(2)))
@test left_complement(b) === BitIndex(Val(VGA(2)), 1, 2)
@test right_complement(b) === BitIndex(Val(VGA(2)), 1, 2)
@test left_complement(b) * b === BitIndex(Val(VGA(2)), 1, 2)
@test b * right_complement(b) === BitIndex(Val(VGA(2)), 1, 2)
b = BitIndex(Val(VGA(2)), 1)
@test left_complement(b) === -BitIndex(Val(VGA(2)), 2)
@test right_complement(b) === BitIndex(Val(VGA(2)), 2)
@test left_complement(b) * b === BitIndex(Val(VGA(2)), 1, 2)
@test b * right_complement(b) === BitIndex(Val(VGA(2)), 1, 2)
b = BitIndex(Val(VGA(2)), 1, 2)
@test left_complement(b) === BitIndex(Val(VGA(2)))
@test right_complement(b) === BitIndex(Val(VGA(2)))
@test left_complement(b) * b === BitIndex(Val(VGA(2)), 1, 2)
@test b * right_complement(b) === BitIndex(Val(VGA(2)), 1, 2)
b = BitIndex(Val(VGA(3)))
@test left_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
@test right_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
@test left_complement(b) * b === BitIndex(Val(VGA(3)), 1, 2, 3)
@test b * right_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
b = BitIndex(Val(VGA(3)), 1)
@test left_complement(b) === BitIndex(Val(VGA(3)), 2, 3)
@test right_complement(b) === BitIndex(Val(VGA(3)), 2, 3)
@test left_complement(b) * b === BitIndex(Val(VGA(3)), 1, 2, 3)
@test b * right_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
b = BitIndex(Val(VGA(3)), 1, 2)
@test left_complement(b) === BitIndex(Val(VGA(3)), 3)
@test right_complement(b) === BitIndex(Val(VGA(3)), 3)
@test left_complement(b) * b === BitIndex(Val(VGA(3)), 1, 2, 3)
@test b * right_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
b = BitIndex(Val(VGA(3)), 1, 2, 3)
@test left_complement(b) === BitIndex(Val(VGA(3)))
@test right_complement(b) === BitIndex(Val(VGA(3)))
@test left_complement(b) * b === BitIndex(Val(VGA(3)), 1, 2, 3)
@test b * right_complement(b) === BitIndex(Val(VGA(3)), 1, 2, 3)
end

@testset "BitIndices" begin
# Tests to check that types don't proliferate like crazy
@test BitIndices(CliffordNumber{VGA(3)}) === BitIndices{VGA(3),CliffordNumber{VGA(3)}}()
Expand Down

0 comments on commit 09aa25f

Please sign in to comment.