-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathkvector.jl
104 lines (76 loc) · 4.03 KB
/
kvector.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
"""
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.
"""
struct KVector{K,Q,T<:BaseNumber,L} <: AbstractCliffordNumber{Q,T}
data::NTuple{L,T}
function KVector{K,Q,T,L}(x::Tuple) where {K,Q,T,L}
@assert 0 <= K <= dimension(Q) "K can only range from 0 to $(dimension(Q)) (got $K)."
check_element_count(binomial(dimension(Q), K), L, x)
return new{K,Q,T,L}(x)
end
end
#---Constructors-----------------------------------------------------------------------------------#
KVector{K,Q,T}(x::Tuple{Vararg{BaseNumber,L}}) where {K,Q,T,L} = KVector{K,Q,T,L}(x)
KVector{K,Q}(x::Tuple{Vararg{T}}) where {K,Q,T<:BaseNumber} = KVector{K,Q,T}(x)
# Automatically convert arguments to a common type
KVector{K,Q}(x::Tuple{Vararg{BaseNumber}}) where {K,Q} = KVector{K,Q}(promote(x...))
#---Number of elements-----------------------------------------------------------------------------#
length(::Type{KVector{K,Q,T,L}}) where {K,Q,T,L} = L
length(::Type{<:KVector{K,Q}}) where {K,Q} = binomial(dimension(Q), K)
length(x::KVector) = length(typeof(x))
#---Indexing---------------------------------------------------------------------------------------#
bitindices_type(::Type{<:KVector{K,Q}}) where {K,Q} = KVector{K,Q}
"""
grade(::Type{<:KVector{K}}) = K
grade(x::KVector{K}) = k
Returns the grade represented by a `KVector{K}`, which is K.
"""
grade(::Type{<:KVector{K}}) where K = K
grade(x::KVector) = grade(typeof(x))
nonzero_grades(::Type{<:KVector{K}}) where K = K:K
@inline function getindex(b::BitIndices{Q,<:KVector{K}}, i::Integer) where {Q,K}
@boundscheck checkbounds(b, i)
return BitIndex{Q}(signbit(i-1), unsigned(hamming_number(K, i)))
end
@inline function to_index(C::Type{<:KVector{K,Q}}, b::BitIndex{Q}) where {K,Q}
# Default to 1 as a valid index for any KVector instance
i = 1
for n in 1:length(C)
is_same_blade(b, (@inbounds BitIndices(C)[n])) && (i = n)
end
return i
end
@inline to_index(k::KVector{K,Q}, b::BitIndex{Q}) where {K,Q} = to_index(typeof(k), b)
@inline function getindex(k::KVector{K,Q}, b::BitIndex{Q}) where {K,Q}
return (@inbounds k.data[to_index(k, b)]) * sign(b) * (grade(b) === K)
end
#---Multiplicative identity and pseudoscalar-------------------------------------------------------#
one(K::Type{<:KVector{<:Any,Q}}) where Q = KVector{0,Q}(scalar_type(K)(true))
# Default implementation for AbstractCliffordNumber subtypes if not explicitly given
one(C::Type{<:AbstractCliffordNumber{Q}}) where Q = one(KVector{0,Q,scalar_type(C)})
"""
pseudoscalar(C::Type{<:AbstractCliffordNumber{Q,T}}) -> KVector{dimension{Q},Q,T}
pseudoscalar(x::AbstractCliffordNumber{Q})
Returns the pseudoscalar associated with the signature `Q` of the argument. The result will have the
same scalar type as the input if such information is given; otherwise it will use `Bool` as the
scalar type so as to promote to any other numeric type.
"""
function pseudoscalar(C::Type{<:AbstractCliffordNumber{Q}}) where Q
return KVector{dimension(Q),Q}(scalar_type(C)(true))
end
pseudoscalar(x::AbstractCliffordNumber) = pseudoscalar(typeof(x))
#---Similar types----------------------------------------------------------------------------------#
function similar_type(::Type{<:KVector{K}}, ::Type{T}, ::Val{Q}) where {K,Q,T<:BaseNumber}
return KVector{K,Q,T,binomial(dimension(Q),K)}
end
function similar_type(::Type{<:KVector}, ::Type{T}, ::Val{Q}, ::Val{K}) where {K,Q,T<:BaseNumber}
return KVector{K,Q,T,binomial(dimension(Q),K)}
end
#---Show methods-----------------------------------------------------------------------------------#
short_typename(::Type{<:KVector{K,Q,T}}) where {K,Q,T} = KVector{K,Q,T}
#---Special Z2CliffordNumber constructor-----------------------------------------------------------#
# Automatically infer if we want an even or odd Clifford number
Z2CliffordNumber(x::KVector{K}) where K = Z2CliffordNumber{isodd(K)}(x)