Skip to content

Commit df57083

Browse files
committed
upgraded syntax definitions
1 parent 9569c77 commit df57083

6 files changed

Lines changed: 99 additions & 49 deletions

File tree

Project.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "DirectSum"
22
uuid = "22fd7b30-a8c0-5bf2-aabe-97783860d07c"
33
authors = ["Michael Reed"]
4-
version = "0.8.13"
4+
version = "0.8.14"
55

66
[deps]
77
ComputedFieldTypes = "459fdd68-db75-56b8-8c15-d717a790f88e"
@@ -12,7 +12,7 @@ Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
1212

1313
[compat]
1414
julia = "1"
15-
Leibniz = "0.2"
15+
Leibniz = "0.2,0.3"
1616
AbstractTensors = "0.8.3"
1717
ComputedFieldTypes = "1"
1818

src/DirectSum.jl

Lines changed: 70 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,11 @@ import Leibniz: parityrightnull, parityleftnull, parityrightnullpre, parityleftn
3939
import Leibniz: hasconformal, parval, TensorTerm, mixed, subs, sups, vio, gdims
4040

4141
import Leibniz: grade, order, options, metric, polymode, dyadmode, diffmode, diffvars
42-
import Leibniz: pseudograde, hasinf, hasorigin, norm, indices, isbasis, Bits, bits,
42+
import Leibniz: pseudograde, hasinf, hasorigin, norm, indices, isbasis,
4343
import Leibniz: isdyadic, isdual, istangent, involute, basis, alphanumv, alphanumw
4444

4545
import Leibniz: algebra_limit, sparse_limit, cache_limit, fill_limit
46-
import Leibniz: binomial, binomial_set, binomsum, binomsum_set, lowerbits, expandbits
46+
import Leibniz: binomial, gdimsall, binomsum, binomcumsum, lowerbits, expandbits
4747
import Leibniz: bladeindex, basisindex, indexbasis, indexbasis_set, loworder, intlog
4848
import Leibniz: promote_type, mvec, svec, intlog, insert_expr, indexparity!
4949

@@ -52,6 +52,8 @@ import Leibniz: promote_type, mvec, svec, intlog, insert_expr, indexparity!
5252
"""
5353
TensorBundle{n,ℙ,g,ν,μ} <: Manifold{n}
5454
55+
A manifold representing the space of tensors with a given metric and basis for projection.
56+
5557
Let `n` be the rank of a `Manifold{n}`.
5658
The type `TensorBundle{n,ℙ,g,ν,μ}` uses *byte-encoded* data available at pre-compilation, where
5759
`ℙ` specifies the basis for up and down projection,
@@ -62,26 +64,67 @@ Lastly, `ν` is the number of tangent variables.
6264
abstract type TensorBundle{n,Options,Metrics,Vars,Diff,Name} <: Manifold{n,Int} end
6365
rank(::TensorBundle{n}) where n = n
6466
mdims(M::TensorBundle) = rank(M)
67+
# Return the manifold dimension (i.e., rank) of a tensor bundle.
68+
69+
"""
70+
tensorhash(d, o; c=0, C=0) -> Int
6571
66-
@pure doc2m(d,o,c=0,C=0) = (1<<(d-1))|(1<<(2*o-1))|(c<0 ? 8 : (1<<(3*c-1)))|(1<<(5*C-1))
72+
Compute a unique integer representation for a set of options.
6773
68-
const names_cache = NTuple{4,String}[]
69-
function names_index(a::NTuple{4,String})
70-
if a names_cache
71-
findfirst(x->x==a,names_cache)
72-
else
73-
push!(names_cache,a)
74-
length(names_cache)
74+
# Arguments:
75+
- `d`: Number of tangent variables (corresponds to `ν`).
76+
- `o`: Order of Leibniz-Taylor monomials multiplicity limit (corresponds to `μ`).
77+
- `c`: Coefficient used to specify the metric (corresponds to `g`). Defaults to 0.
78+
- `C`: Additional coefficient. Defaults to 0.
79+
80+
# Returns
81+
A unique integer representation that can be used as a cache key.
82+
"""
83+
@pure function tensorhash(d,o,c=0,C=0)
84+
(1<<(d-1))|(1<<(2*o-1))|(c<0 ? 8 : (1<<(3*c-1)))|(1<<(5*C-1))
85+
end
86+
87+
const namecache = NTuple{4,String}[]
88+
89+
"""
90+
nameindex(a::NTuple{4, String}) -> Int
91+
92+
Get a unique index for a set of name options, based on a cached result.
93+
"""
94+
function nameindex(a::NTuple{4,String})
95+
if a namecache # check if options are in cache
96+
findfirst(x->x==a,namecache)
97+
else # cache the options and add them to the list
98+
push!(namecache,a)
99+
length(namecache)
75100
end
76101
end
77-
@pure names_index(V::T) where T<:TensorBundle{N,M,S,F,D,Q} where {N,M,S,F,D} where Q = Q
78-
@pure names_index(V::T) where T<:Manifold = names_index(supermanifold(V))
79-
@pure names_index(V::Int) = 1
80-
@pure namelist(V) = names_cache[names_index(V)]
81102

82-
# vector and co-vector prefix
83-
names_index(pre)
84-
names_index(PRE)
103+
# initialize vector and co-vector prefix
104+
nameindex(pre)
105+
nameindex(PRE)
106+
107+
"""
108+
nameindex(V::T) -> Int
109+
110+
Returns the name index for `V` when `V` is a `TensorBundle` or `Manifold`.
111+
"""
112+
@pure nameindex(V::T) where T<:TensorBundle{N,M,S,F,D,Q} where {N,M,S,F,D} where Q = Q
113+
@pure nameindex(V::T) where T<:Manifold = nameindex(supermanifold(V))
114+
115+
"""
116+
nameindex(V::Int) -> Int
117+
118+
Returns a default name index for an integer input.
119+
"""
120+
@pure nameindex(V::Int) = 1
121+
122+
"""
123+
namelist(V) -> String
124+
125+
Get the cached name list for the options specified in `V`.
126+
"""
127+
@pure namelist(V) = namecache[nameindex(V)]
85128

86129
## Signature{N}
87130

@@ -92,18 +135,17 @@ end
92135
@pure Signature{N,M,S,F,D}() where {N,M,S,F,D} = Signature{N,M,S,F,D,1}()
93136
@pure Signature{N,M,S}() where {N,M,S} = Signature{N,M,S,0,0}()
94137
@pure Signature{N,M}(b::BitArray{1},f=0,d=0) where {N,M} = Signature{N,M,bit2int(b[1:N]),f,d}()
95-
@pure Signature{N,M}(b::Array{Bool,1},f=0,d=0) where {N,M} = Signature{N,M}(convert(BitArray{1},b),f,d)
138+
@pure Signature{N,M}(b::Vector{Bool},f=0,d=0) where {N,M} = Signature{N,M}(convert(BitArray{1},b),f,d)
96139
@pure Signature{N,M}(s::String) where {N,M} = Signature{N,M}([k=='-' for ks])
97140
@pure Signature(str::String) = Signature{length(str)}(str)
98-
@pure Signature(n::Int,d::Int=0,o::Int=0,s::UInt=zero(UInt)) = Signature{n,doc2m(d,o),s}()
99-
141+
@pure Signature(n::Int,d::Int=0,o::Int=0,s::UInt=zero(UInt)) = Signature{n,tensorhash(d,o),s}()
100142
@pure function Signature{N}(s::String) where N
101143
ms = match(r"[0-9]+",s)
102144
if ms nothing && String(ms.match) == s
103145
length(s) < 4 && (s *= join(zeros(Int,5-length(s))))
104146
Signature(parse(Int,s[1]),parse(Int,s[2]),parse(Int,s[3]),UInt(parse(Int,s[4:end])))
105147
else
106-
Signature{N,doc2m(Int(vio[1]∈s),Int(vio[2]∈s))}(replace(replace(s,vio[1]=>'+'),vio[2]=>'-'))
148+
Signature{N,tensorhash(Int(vio[1]∈s),Int(vio[2]∈s))}(replace(replace(s,vio[1]=>'+'),vio[2]=>'-'))
107149
end
108150
end
109151

@@ -118,7 +160,9 @@ Base.firstindex(m::TensorBundle) = 1
118160
Base.lastindex(m::TensorBundle{N}) where N = N
119161
Base.length(s::TensorBundle{N}) where N = N
120162

163+
# Type promotion to allow using `Int` with `Signature`
121164
Base.promote_rule(::Type{Int}, ::Type{<:Signature}) = Signature
165+
#Base.promote_rule(::Type{Int}, ::Type{<:TensorBundle}) = Signature
122166

123167
@inline sig(s::Bool) = s ? '-' : '+'
124168
@inline sig(s::Int,k) = '1'
@@ -129,7 +173,7 @@ Base.promote_rule(::Type{Int}, ::Type{<:Signature}) = Signature
129173
@inline printsep(io,s,k,n) = kn && print(io,',')
130174

131175
function Base.show(io::IO,s::Signature)
132-
dm = diffmode(s)
176+
dm = diffmode(s) # print lead symbols
133177
print(io,dm>0 ? "T$(sups[dm])" : '')
134178
C,d = dyadmode(s),diffvars(s)
135179
N = mdims(s)-(d>0 ? (C<0 ? 2d : d) : 0)
@@ -139,9 +183,9 @@ function Base.show(io::IO,s::Signature)
139183
print(io,sig.(s[hasinf(s)+hasorigin(s)+1+(d<0 ? abs(d) : 0):N])...)
140184
d>0 && print(io,[((C>0)!polymode(s) ? sups : subs)[x] for x 1:abs(d)]...)
141185
d>0 && C<0 && print(io,[sups[x] for x 1:abs(d)]...)
142-
print(io,'')
186+
print(io,'') # print end symbols
143187
C 0 ? print(io, C < 0 ? '*' : ''') : nothing
144-
names_index(s)>1 && print(io,subs[names_index(s)])
188+
nameindex(s)>1 && print(io,subs[nameindex(s)])
145189
end
146190

147191
## DiagonalForm{N}
@@ -195,7 +239,7 @@ function Base.show(io::IO,s::DiagonalForm)
195239
d>0 && C<0 && print(io,[sups[x] for x 1:abs(d)]...)
196240
print(io,'')
197241
C 0 ? print(io, C < 0 ? '*' : ''') : nothing
198-
names_index(s)>1 && print(io,subs[names_index(s)])
242+
nameindex(s)>1 && print(io,subs[nameindex(s)])
199243
end
200244

201245
## Submanifold{N}
@@ -307,7 +351,7 @@ function Base.show(io::IO,s::Submanifold{V,NN,S}) where {V,NN,S}
307351
d>0 && C<0 && print(io,[sups[x-NM] for x ind[N+abs(d)+1:end]]...)
308352
print(io,'')
309353
C 0 ? print(io, C < 0 ? '*' : ''') : nothing
310-
names_index(s)>1 && print(io,subs[names_index(s)])
354+
nameindex(s)>1 && print(io,subs[nameindex(s)])
311355
PnV && print(io,'×',length(V))
312356
end
313357

src/basis.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ end
216216
C = V[1]∉('D','C') ? 0 : 1
217217
length(V) < 5 && (V *= join(zeros(Int,5-length(V))))
218218
S = UInt(parse(Int,V[5:end]))
219-
getalgebra(N,doc2m(parse(Int,V[3]),parse(Int,V[4]),C),C>0 ? flip_sig(N,S) : S)
219+
getalgebra(N,tensorhash(parse(Int,V[3]),parse(Int,V[4]),C),C>0 ? flipsign(N,S) : S)
220220
end=#
221221

222222
# Allocating thread-safe $(2^n)×Submanifold{G,V}
@@ -264,7 +264,7 @@ end
264264
getalgebra(mdims(M),options(M),metric(M),S,typeof(M),diffvars(M),diffmode(M))
265265
end
266266
end
267-
@pure getalgebra(n::Int,d::Int,o::Int,s,c::Int=0) = getalgebra(n,doc2m(d,o,c),s)
267+
@pure getalgebra(n::Int,d::Int,o::Int,s,c::Int=0) = getalgebra(n,tensorhash(d,o,c),s)
268268
@pure getalgebra(n::Int,m::Int,s) = getalgebra(n,m,UInt(s),UInt(1)<<n-1,Signature{n,m,UInt(s),0,0})
269269

270270

@@ -419,7 +419,7 @@ for (ExtraBasis,extra) ∈ ((SparseBasis,:sparse),(ExtendedBasis,:extended))
419419
@pure $getextra(V::Int) = $getextra(mdims(V),options(V),metric(V),metric(V),typeof(V),diffvars(V),diffmode(V))
420420
end
421421
@eval begin
422-
@pure $getextra(n::Int,d::Int,o::Int,s,c::Int=0) = $getalg(n,doc2m(d,o,c),s)
422+
@pure $getextra(n::Int,d::Int,o::Int,s,c::Int=0) = $getalg(n,tensorhash(d,o,c),s)
423423
@pure $getextra(n::Int,m::Int,s) = $getalg(n,m,UInt(s),UInt(1)<<n-1,Signature{n,m,UInt(s),0,0})
424424
end
425425
end

src/generic.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,13 @@
1212
# https://github.com/chakravala
1313
# https://crucialflow.com
1414

15-
export basis, grade, order, options, metric, polymode, dyadmode, diffmode, diffvars
15+
export basis, grade, order, options, metrichash, polymode, dyadmode, diffmode, diffvars
1616
export valuetype, value, hasinf, hasorigin, isorigin, norm, indices, tangent, isbasis,
17-
export pseudograde, pseudoreverse, pseudoinvolute, pseudoclifford
17+
export pseudograde, pseudoreverse, pseudoinvolute, pseudoclifford, metric
18+
19+
# deprecate
20+
@pure metric(::T) where T<:TensorBundle{N,M,S} where {N,M} where S = S
21+
@pure metric(V::Signature,b::UInt) = isodd(count_ones(metric(V)&b)) ? -1 : 1
1822

1923
(M::Signature)(b::Int...) = Submanifold{M}(b)
2024
(M::DiagonalForm)(b::Int...) = Submanifold{M}(b)
@@ -41,8 +45,10 @@ export pseudograde, pseudoreverse, pseudoinvolute, pseudoclifford
4145
@pure order(m::Single) = order(basis(m))+order(value(m))
4246
@pure options(::T) where T<:TensorBundle{N,M} where N where M = M
4347
@pure options_list(V::M) where M<:Manifold = hasinf(V),hasorigin(V),dyadmode(V),polymode(V)
44-
@pure metric(::T) where T<:TensorBundle{N,M,S} where {N,M} where S = S
45-
@pure metric(V::Signature,b::UInt) = isodd(count_ones(metric(V)&b)) ? -1 : 1
48+
@pure metrichash(::Int) = zero(UInt)
49+
@pure metrichash(::T) where T<:TensorBundle{N,M,S} where {N,M} where S = S
50+
@pure metrichash(V::M,b::UInt) where M<:Manifold = PROD(V[indices(b)])
51+
@pure metrichash(V::Signature,b::UInt) = isodd(count_ones(metric(V)&b)) ? -1 : 1
4652
@pure polymode(::T) where T<:TensorBundle{N,M} where N where M = _polymode(M)
4753
@pure dyadmode(::T) where T<:TensorBundle{N,M} where N where M = _dyadmode(M)
4854
@pure diffmode(::T) where T<:TensorBundle{N,M,S,F,D} where {N,M,S,F} where D = D
@@ -132,21 +138,21 @@ end
132138

133139
# dual involution
134140

135-
@pure flip_sig(N,S::UInt) = UInt(2^N-1) & (~S)
141+
@pure flipsign(N,S::UInt) = UInt(2^N-1) & (~S)
136142

137143
@pure dual(V::T) where T<:Manifold = isdyadic(V) ? V : V'
138144
@pure dual(V::T,B,M=Int(rank(V)/2)) where T<:Manifold = ((B<<M)&((1<<rank(V))-1))|(B>>M)
139145

140146
@pure function Base.adjoint(V::Signature{N,M,S,F,D}) where {N,M,S,F,D}
141147
C = dyadmode(V)
142148
C < 0 && throw(error("$V is the direct sum of a vector space and its dual space"))
143-
Signature{N,doc2m(hasinf(V),hasorigin(V),Int(!Bool(C))),flip_sig(N,S),F,D}()
149+
Signature{N,tensorhash(hasinf(V),hasorigin(V),Int(!Bool(C))),flipsign(N,S),F,D}()
144150
end
145151

146152
@pure function Base.adjoint(V::DiagonalForm{N,M,S,F,D}) where {N,M,S,F,D}
147153
C = dyadmode(V)
148154
C < 0 && throw(error("$V is the direct sum of a vector space and its dual space"))
149-
DiagonalForm{N,doc2m(hasinf(V),hasorigin(V),Int(!Bool(C))),S,F,D}()
155+
DiagonalForm{N,tensorhash(hasinf(V),hasorigin(V),Int(!Bool(C))),S,F,D}()
150156
end
151157

152158
@pure function Base.adjoint(V::Submanifold{M,N,S}) where {N,M,S}

src/grade.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ for fun ∈ (:gdims,:combo,:binomsum,:spinsum,:antisum,:indexbasis)
2323
@pure $fun(::Grade{N,N},::Grade{N,G}) where {N,G} = $fun(N,G)
2424
end
2525
end
26-
for fun (:binomial_set,:binomsum_set,:spinsum_set,:antisum_set,:indexbasis_set,:indexeven_set,:indexodd_set,:indexbasis,:indexeven,:indexodd)
27-
@eval @pure $fun(::Grade{N,N}) where N = $fun(N)
26+
for fun (:gdimsall,:binomcumsum,:spincumsum,:anticumsum,:indexbasis_set,:indexeven_set,:indexodd_set,:indexbasis,:indexeven,:indexodd)
27+
@eval @pure Leibniz.$fun(::Grade{N,N}) where N = Leibniz.$fun(N)
2828
end
2929

3030
Base.:+(::Grade{N,G},::Grade{N,F}) where {N,G,F} = Grade{N,G+F}()

src/operations.jl

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ export ⊕, χ, gdims
2121
D2,O2,C2 = options_list(b)
2222
ds = (N == M) && (A == B)
2323
if (D1,O1,C1,D2,O2,C2) == (0,0,0,0,0,0)
24-
doc2m(0,0,0)
24+
tensorhash(0,0,0)
2525
elseif (D1,O1,C1,D2,O2,C2) == (0,0,1,0,0,1)
26-
doc2m(0,0,1)
26+
tensorhash(0,0,1)
2727
elseif (D1,O1,C1,D2,O2,C2) == (0,0,0,0,0,1)
28-
doc2m(0,0,ds ? -1 : 0)
28+
tensorhash(0,0,ds ? -1 : 0)
2929
elseif (D1,O1,C1,D2,O2,C2) == (0,0,1,0,0,0)
30-
doc2m(0,0,ds ? -1 : 0)
30+
tensorhash(0,0,ds ? -1 : 0)
3131
else
3232
throw(error("arbitrary TensorBundle direct-sums not yet implemented"))
3333
end
@@ -40,13 +40,13 @@ for op ∈ (:+,:⊕)
4040
D2,O2,C2 = options_list(b)
4141
NM = N == M
4242
opt = if (D1,O1,C1,D2,O2,C2) == (0,0,0,0,0,0)
43-
doc2m(0,0,0)
43+
tensorhash(0,0,0)
4444
elseif (D1,O1,C1,D2,O2,C2) == (0,0,1,0,0,1)
45-
doc2m(0,0,1)
45+
tensorhash(0,0,1)
4646
elseif (D1,O1,C1,D2,O2,C2) == (0,0,0,0,0,1)
47-
doc2m(0,0,NM ? (B flip_sig(N,A) ? 0 : -1) : 0)
47+
tensorhash(0,0,NM ? (B flipsign(N,A) ? 0 : -1) : 0)
4848
elseif (D1,O1,C1,D2,O2,C2) == (0,0,1,0,0,0)
49-
doc2m(0,0,NM ? (A flip_sig(N,B) ? 0 : -1) : 0)
49+
tensorhash(0,0,NM ? (A flipsign(N,B) ? 0 : -1) : 0)
5050
else
5151
throw(error("arbitrary TensorBundle direct-sums not yet implemented"))
5252
end
@@ -358,7 +358,7 @@ for field ∈ (false,true)
358358
args = field ? (:g,) : ()
359359
@eval begin
360360
@pure function metric(b::Submanifold{V,G,B},$(args...)) where {V,G,B}
361-
!isbasis(b) && (return metric(V))
361+
!isbasis(b) && (return metrichash(V)) # can be deprecated
362362
(!isdiag(V) || hasconformal(V) || $field) && (return complementleft(complementrighthodge(b,$(args...))))
363363
isdyadic(V) && throw(error("Complement for mixed tensors is undefined"))
364364
hasorigin(b) && !hasinf(b) && (return Zero(V))

0 commit comments

Comments
 (0)