diff --git a/README.md b/README.md index dfcd48a..3718fc4 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,8 @@ [![Build status](https://ci.appveyor.com/api/projects/status/c36u0rgtm2rjcquk?svg=true)](https://ci.appveyor.com/project/chakravala/grassmann-jl) [![Coverage Status](https://coveralls.io/repos/chakravala/Grassmann.jl/badge.svg?branch=master&service=github)](https://coveralls.io/github/chakravala/Grassmann.jl?branch=master) [![codecov.io](http://codecov.io/github/chakravala/Grassmann.jl/coverage.svg?branch=master)](http://codecov.io/github/chakravala/Grassmann.jl?branch=master) +[![Gitter](https://badges.gitter.im/Grassmann-jl/community.svg)](https://gitter.im/Grassmann-jl/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) +[![Liberapay patrons](https://img.shields.io/liberapay/patrons/chakravala.svg)](https://liberapay.com/chakravala) This package is a work in progress providing the necessary tools to work with arbitrary dual `MultiVector` elements with optional origin. Due to the parametric type system for the generating `VectorSpace`, the Julia compiler can fully preallocate and often cache values efficiently. Both static and mutable vector types are supported. @@ -40,7 +42,7 @@ Let `N` be the dimension of a `VectorSpace{N}`. The metric signature of the `Basis{V,1}` elements of a vector space `V` can be specified with the `V"..."` constructor by using `+` and `-` to specify whether the `Basis{V,1}` element of the corresponding index squares to `+1` or `-1`. For example, `V"+++"` constructs a positive definite 3-dimensional `VectorSpace`. ```Julia -julia> ℝ^3 == V"+++" == VectorSpace(3) +julia> ℝ^3 == V"+++" == vectorspace(3) true ``` The direct sum operator `⊕` can be used to join spaces (alternatively `+`), and `'` is an involution which toggles a dual vector space with inverted signature. diff --git a/REQUIRE b/REQUIRE index b4494bd..0107f07 100644 --- a/REQUIRE +++ b/REQUIRE @@ -3,7 +3,7 @@ Combinatorics StaticArrays ComputedFieldTypes Requires -DirectSum 0.1 0.2- +DirectSum 0.2 AbstractTensors AbstractLattices Reduce diff --git a/src/Grassmann.jl b/src/Grassmann.jl index 1624d34..4776cba 100644 --- a/src/Grassmann.jl +++ b/src/Grassmann.jl @@ -7,8 +7,8 @@ using Combinatorics, StaticArrays, Requires using ComputedFieldTypes, AbstractLattices using DirectSum, AbstractTensors -export VectorSpace, vectorspace, ⊕, ℝ, @V_str -import DirectSum: hasdual, hasorigin, dualtype, dual, value, vectorspace, V0, ⊕ +export vectorspace, ⊕, ℝ, @V_str, @D_str, Signature, DiagonalForm, value +import DirectSum: hasinf, hasorigin, dualtype, dual, value, vectorspace, V0, ⊕ include("utilities.jl") include("multivectors.jl") @@ -24,7 +24,7 @@ export hyperplanes abstract type SubAlgebra{V} <: TensorAlgebra{V} end -@pure adjoint(G::A) where A<:SubAlgebra{V} where V = Λ(dual(V)) +adjoint(G::A) where A<:SubAlgebra{V} where V = Λ(dual(V)) @pure dual(G::A) where A<: SubAlgebra = G' Base.firstindex(a::T) where T<:SubAlgebra = 1 Base.lastindex(a::T) where T<:SubAlgebra{V} where V = 1<i for i ∈ 1:1<2algebra_limit && (return getextended(V)) - getalgebra(N,doc2m(Int(hasdual(V)),Int(hasorigin(V)),C),value(V)) -end - @pure function Base.getproperty(λ::typeof(Λ),v::Symbol) v ∈ (:body,:var) && (return getfield(λ,v)) V = string(v) @@ -103,20 +95,34 @@ end # Allocating thread-safe $(2^n)×Basis{VectorSpace} const Λ0 = Λ{V0}(SVector{1,Basis{V0}}(Basis{V0,0,zero(Bits)}()),Dict(:e=>1)) -const algebra_cache = Vector{Dict{Bits,Λ}}[] -@pure function getalgebra(n::Int,m::Int,s::Bits) - n==0 && (return Λ0) - n > sparse_limit && (return getextended(n,m,s)) - n > algebra_limit && (return getsparse(n,m,s)) - for N ∈ length(algebra_cache)+1:n - push!(algebra_cache,[Dict{Int,Λ}() for k∈1:12]) - end - @inbounds if !haskey(algebra_cache[n][m+1],s) - @inbounds push!(algebra_cache[n][m+1],s=>collect(VectorSpace{n,m,s}())) + +for (vs,dat) ∈ ((:Signature,Bits),(:DiagonalForm,Int)) + algebra_cache = Symbol(:algebra_cache_,vs) + getalg = Symbol(:getalgebra_,vs) + @eval begin + const $algebra_cache = Vector{Dict{$dat,Λ}}[] + @pure function $getalg(n::Int,m::Int,s::$dat) + n==0 && (return Λ0) + n > sparse_limit && (return $(Symbol(:getextended_,vs))(n,m,s)) + n > algebra_limit && (return $(Symbol(:getsparse_,vs))(n,m,s)) + for N ∈ length($algebra_cache)+1:n + push!($algebra_cache,[Dict{$dat,Λ}() for k∈1:12]) + end + @inbounds if !haskey($algebra_cache[n][m+1],s) + @inbounds push!($algebra_cache[n][m+1],s=>collect($vs{n,m,s}())) + end + @inbounds $algebra_cache[n][m+1][s] + end + @pure function getalgebra(V::$vs{N,M,S}) where {N,M,S} + dualtype(V)<0 && N>2algebra_limit && (return getextended(V)) + $(Symbol(:getalgebra_,vs))(N,M,S) + end end - @inbounds algebra_cache[n][m+1][s] end +@pure getalgebra(n::Int,d::Int,o::Int,s,c::Int=0) = getalgebra_Signature(n,doc2m(d,o,c),s) +@pure getalgebra(n::Int,m::Int,s) = getalgebra_Signature(n,m,Bits(s)) + @pure getbasis(V::VectorSpace,v::Symbol) = getproperty(getalgebra(V),v) @pure function getbasis(V::VectorSpace{N},b) where N B = Bits(b) @@ -162,29 +168,13 @@ end end @pure SparseAlgebra(n::Int,d::Int=0,o::Int=0,s=zero(Bits)) = getsparse(n,d,o,s) -SparseAlgebra(s::String) = getsparse(VectorSpace(s)) -SparseAlgebra(s::String,v::Symbol) = getbasis(VectorSpace(s),v) +SparseAlgebra(s::String) = getsparse(vectorspace(s)) +SparseAlgebra(s::String,v::Symbol) = getbasis(vectorspace(s),v) function show(io::IO,a::SparseAlgebra{V}) where V print(io,"Grassmann.SparseAlgebra{$V,$(1<SparseAlgebra(VectorSpace{n,m,s}())) - end - @inbounds sparse_cache[n][m+1][s] -end - ## ExtendedAlgebra{V} struct ExtendedAlgebra{V} <: SubAlgebra{V} end @@ -200,28 +190,41 @@ struct ExtendedAlgebra{V} <: SubAlgebra{V} end end @pure ExtendedAlgebra(n::Int,d::Int=0,o::Int=0,s=zero(Bits)) = getextended(n,d,o,s) -ExtendedAlgebra(s::String) = getextended(VectorSpace(s)) -ExtendedAlgebra(s::String,v::Symbol) = getbasis(VectorSpace(s),v) +ExtendedAlgebra(s::String) = getextended(vectorspace(s)) +ExtendedAlgebra(s::String,v::Symbol) = getbasis(vectorspace(s),v) function show(io::IO,a::ExtendedAlgebra{V}) where V N = 1<$ExtraAlgebra($vs{n,m,s}())) + end + @inbounds $extra_cache[n][m+1][s] + end + @pure $getextra(V::$vs{N,M,S}) where {N,M,S} = $getalg(N,M,S) + end end - @inbounds if !haskey(extended_cache[n][m+1],s) - @inbounds push!(extended_cache[n][m+1],s=>ExtendedAlgebra(VectorSpace{n,m,s}())) + @eval begin + @pure $getextra(n::Int,d::Int,o::Int,s,c::Int=0) = $gets(n,doc2m(d,o,c),s) + @pure $getextra(n::Int,m::Int,s) = $gets(n,m,Bits(s)) end - @inbounds extended_cache[n][m+1][s] end # ParaAlgebra diff --git a/src/algebra.jl b/src/algebra.jl index fe628d2..109e5a3 100644 --- a/src/algebra.jl +++ b/src/algebra.jl @@ -24,7 +24,7 @@ const SymField = Any set_val(set,expr,val) = Expr(:(=),expr,set≠:(=) ? Expr(:call,:($Sym.:+),expr,val) : val) -function declare_mutating_operations(M,neg,F,set_val) +function declare_mutating_operations(M,F,set_val,SUB,MUL) for (op,set) ∈ ((:add,:(+=)),(:set,:(=))) sm = Symbol(op,:multi!) sb = Symbol(op,:blade!) @@ -45,33 +45,27 @@ function declare_mutating_operations(M,neg,F,set_val) for s ∈ (sm,sb) @eval begin @inline function $(Symbol(:join,s))(V::VectorSpace{N,D},m::$M,A::Bits,B::Bits,v::S) where {N,D,T<:$F,S<:$F,M} - if v ≠ 0 && !(hasdual(V) && isodd(A) && isodd(B)) - $s(m,parity(A,B,V) ? $neg(v) : v,A ⊻ B,Dimension{N}()) + if v ≠ 0 && !(hasinf(V) && isodd(A) && isodd(B)) + val = (typeof(V)<:Signature || count_ones(A&B)==0) ? (parity(A,B,V) ? $SUB(v) : v) : $MUL(parity_interior(A,B,V),v) + $s(m,val,A ⊻ B,Dimension{N}()) end return m end @inline function $(Symbol(:join,s))(m::$M,v::S,A::Basis{V},B::Basis{V}) where {V,T<:$F,S<:$F,M} - if v ≠ 0 && !(hasdual(V) && hasdual(A) && hasdual(B)) - $s(m,parity(A,B) ? $neg(v) : v,bits(A) ⊻ bits(B),Dimension{ndims(V)}()) - end - return m + $(Symbol(:join,s))(V,m,bits(A),bits(B),v) end end for (prod,uct) ∈ ((:meet,:regressive),(:skew,:interior),(:cross,:crossprod)) @eval begin @inline function $(Symbol(prod,s))(V::VectorSpace{N,D},m::$M,A::Bits,B::Bits,v::T) where {N,D,T,M} if v ≠ 0 - p,C,t = $uct(A,B,V) - t && $s(m,p ? $neg(v) : v,C,Dimension{N}()) + g,C,t = $uct(A,B,V) + t && $s(m,typeof(V) <: Signature ? g ? $SUB(v) : v : $MUL(g,v),C,Dimension{N}()) end return m end @inline function $(Symbol(prod,s))(m::$M,A::Basis{V},B::Basis{V},v::T) where {V,T,M} - if v ≠ 0 - p,C,t = $uct(bits(A),bits(B),V) - t && $s(m,p ? $neg(v) : v,C,Dimension{N}()) - end - return m + $(Symbol(prod,s))(V,m,bits(A),bits(B),v) end end end @@ -85,17 +79,18 @@ end add!(out,val,Basis{V,count_ones(ua),ua},Basis{V,count_ones(ub),ub}) end @inline function add!(m::MultiVector{T,V},v::T,A::Basis{V},B::Basis{V}) where {T<:Field,V} - !(hasdual(V) && isodd(A) && isodd(B)) && addmulti!(m.v,parity(A,B) ? -(v) : v,bits(A).⊻bits(B)) + !(hasinf(V) && isodd(A) && isodd(B)) && addmulti!(m.v,parity(A,B) ? -(v) : v,bits(A).⊻bits(B)) return out end ## geometric product @pure function *(a::Basis{V},b::Basis{V}) where V - hasdual(V) && hasdual(a) && hasdual(b) && (return zero(V)) - c = bits(a) ⊻ bits(b) - d = Basis{V}(c) - return parity(a,b) ? SValue{V}(-1,d) : d + hasinf(V) && hasinf(a) && hasinf(b) && (return zero(V)) + A,B = bits(a), bits(b) + C = A ⊻ B + d = Basis{V}(C) + return (typeof(V)<:Signature || count_ones(A&B)==0) ? (parity(a,b) ? SValue{V}(-1,d) : d) : SValue{V}(parity_interior(A,B,V),d) end @pure function parity_calc(N,S,a,b) @@ -164,25 +159,29 @@ end ## complement -export complementleft, complementright, complementhodge +export complementleft, complementright @pure complement(N::Int,B::UInt) = (~B)&(one(Bits)< sparse_limit - N = n-sparse_limit - for k ∈ length(parity_extra)+1:N - push!(parity_extra,Dict{Bits,Dict{Bits,Dict{Bits,Bool}}}()) - end - @inbounds !haskey(parity_extra[N],s) && push!(parity_extra[N],s=>Dict{Bits,Dict{Bits,Bool}}()) - @inbounds !haskey(parity_extra[N][s],a) && push!(parity_extra[N][s],a=>Dict{Bits,Bool}()) - @inbounds !haskey(parity_extra[N][s][a],b) && push!(parity_extra[N][s][a],b=>parity_calc(n,s,a,b)) - @inbounds parity_extra[N][s][a][b] - else - a1 = a+1 - for k ∈ length(parity_cache)+1:n - push!(parity_cache,Dict{Bits,Vector{Bool}}()) - end - @inbounds !haskey(parity_cache[n],s) && push!(parity_cache[n],s=>Vector{Bool}[]) - @inbounds for k ∈ length(parity_cache[n][s]):a - @inbounds push!(parity_cache[n][s],Bool[]) - end - @inbounds for k ∈ length(parity_cache[n][s][a1]):b - @inbounds push!(parity_cache[n][s][a1],parity_calc(n,s,a,k)) - end - @inbounds parity_cache[n][s][a1][b+1] +const parity_cache = Dict{Bits,Vector{Vector{Bool}}}[] +const parity_extra = Dict{Bits,Dict{Bits,Dict{Bits,Bool}}}[] +@pure function parity(n,s,a,b)::Bool + if n > sparse_limit + N = n-sparse_limit + for k ∈ length(parity_extra)+1:N + push!(parity_extra,Dict{Bits,Dict{Bits,Dict{Bits,Bool}}}()) + end + @inbounds !haskey(parity_extra[N],s) && push!(parity_extra[N],s=>Dict{Bits,Dict{Bits,Bool}}()) + @inbounds !haskey(parity_extra[N][s],a) && push!(parity_extra[N][s],a=>Dict{Bits,Bool}()) + @inbounds !haskey(parity_extra[N][s][a],b) && push!(parity_extra[N][s][a],b=>parity_calc(n,s,a,b)) + @inbounds parity_extra[N][s][a][b] + else + a1 = a+1 + for k ∈ length(parity_cache)+1:n + push!(parity_cache,Dict{Bits,Vector{Bool}}()) end + @inbounds !haskey(parity_cache[n],s) && push!(parity_cache[n],s=>Vector{Bool}[]) + @inbounds for k ∈ length(parity_cache[n][s]):a + @inbounds push!(parity_cache[n][s],Bool[]) + end + @inbounds for k ∈ length(parity_cache[n][s][a1]):b + @inbounds push!(parity_cache[n][s][a1],parity_calc(n,s,a,k)) + end + @inbounds parity_cache[n][s][a1][b+1] end - @pure parity(a::Bits,b::Bits,v::VectorSpace) = parity(ndims(v),value(v),a,b) - @pure parity(a::Basis{V,G,B},b::Basis{V,L,C}) where {V,G,B,L,C} = parity(ndims(V),value(V),bits(a),bits(b)) +end +@pure parity(a::Bits,b::Bits,v::Signature) = parity(ndims(v),value(v),a,b) +@pure parity(a::Bits,b::Bits,v::VectorSpace) = parity(a,b,Signature(v)) +@pure parity(a::Basis{V,G,B},b::Basis{V,L,C}) where {V,G,B,L,C} = parity(bits(a),bits(b),V) + +@pure function parity_interior(a::Bits,b::Bits,V::DiagonalForm) + g = abs(prod(V[indices(a&b)])) + parity(a,b,Signature(V)) ? -(g) : g end ### parity cache 2 for par ∈ (:interior,:regressive,:crossprod) - T = Tuple{Bool,Bits,Bool} - extra = Symbol(par,:_extra) - cache = Symbol(par,:_cache) calc = Symbol(par,:_calc) - @eval begin - const $cache = Vector{Dict{Bits,Vector{Vector{$T}}}}[] - const $extra = Vector{Dict{Bits,Dict{Bits,Dict{Bits,$T}}}}[] - @pure function $par(n,m,s,a,b)::$T - m1 = m+1 - if n > sparse_limit - N = n-sparse_limit - for k ∈ length($extra)+1:N - push!($extra,Dict{Bits,Dict{Bits,Dict{Bits,$T}}}[]) - end - for k ∈ length($extra[N])+1:m1 - push!($extra[N],Dict{Bits,Dict{Bits,Dict{Bits,$T}}}()) - end - @inbounds !haskey($extra[N][m1],s) && push!($extra[N][m1],s=>Dict{Bits,Dict{Bits,$T}}()) - @inbounds !haskey($extra[N][m1][s],a) && push!($extra[N][m1][s],a=>Dict{Bits,$T}()) - @inbounds !haskey($extra[N][m1][s][a],b) && push!($extra[N][m1][s][a],b=>$calc(n,m,s,a,b)) - @inbounds $extra[N][m1][s][a][b] - else - a1 = a+1 - for k ∈ length($cache)+1:n - push!($cache,Dict{Bits,Vector{Vector{$T}}}[]) - end - for k ∈ length($cache[n])+1:m1 - push!($cache[n],Dict{Bits,Vector{Vector{$T}}}()) - end - @inbounds !haskey($cache[n][m1],s) && push!($cache[n][m1],s=>Vector{$T}[]) - @inbounds for k ∈ length($cache[n][m1][s]):a - @inbounds push!($cache[n][m1][s],$T[]) - end - @inbounds for k ∈ length($cache[n][m1][s][a1]):b - @inbounds push!($cache[n][m1][s][a1],$calc(n,m,s,a,k)) + for (vs,space,dat) ∈ ((:_sig,Signature,Bool),(:_diag,DiagonalForm,Any)) + T = Tuple{dat,Bits,Bool} + extra = Symbol(par,vs,:_extra) + cache = Symbol(par,vs,:_cache) + @eval begin + const $cache = Vector{Dict{Bits,Vector{Vector{$T}}}}[] + const $extra = Vector{Dict{Bits,Dict{Bits,Dict{Bits,$T}}}}[] + @pure function ($par(a,b,V::$space{n,m,s})::$T) where {n,m,s} + m1 = m+1 + if n > sparse_limit + N = n-sparse_limit + for k ∈ length($extra)+1:N + push!($extra,Dict{Bits,Dict{Bits,Dict{Bits,$T}}}[]) + end + for k ∈ length($extra[N])+1:m1 + push!($extra[N],Dict{Bits,Dict{Bits,Dict{Bits,$T}}}()) + end + @inbounds !haskey($extra[N][m1],s) && push!($extra[N][m1],s=>Dict{Bits,Dict{Bits,$T}}()) + @inbounds !haskey($extra[N][m1][s],a) && push!($extra[N][m1][s],a=>Dict{Bits,$T}()) + @inbounds !haskey($extra[N][m1][s][a],b) && push!($extra[N][m1][s][a],b=>$calc(V,a,b)) + @inbounds $extra[N][m1][s][a][b] + else + a1 = a+1 + for k ∈ length($cache)+1:n + push!($cache,Dict{Bits,Vector{Vector{$T}}}[]) + end + for k ∈ length($cache[n])+1:m1 + push!($cache[n],Dict{Bits,Vector{Vector{$T}}}()) + end + @inbounds !haskey($cache[n][m1],s) && push!($cache[n][m1],s=>Vector{$T}[]) + @inbounds for k ∈ length($cache[n][m1][s]):a + @inbounds push!($cache[n][m1][s],$T[]) + end + @inbounds for k ∈ length($cache[n][m1][s][a1]):b + @inbounds push!($cache[n][m1][s][a1],$calc(V,a,k)) + end + @inbounds $cache[n][m1][s][a1][b+1] end - @inbounds $cache[n][m1][s][a1][b+1] end end - @pure $par(a::Bits,b::Bits,v::VectorSpace) = $par(ndims(v),DirectSum.options(v),value(v),a,b) - @pure $par(a::Basis{V,G,B},b::Basis{V,L,C}) where {V,G,B,L,C} = $par(ndims(V),DirectSum.options(V),value(V),bits(a),bits(b)) end + @eval @pure $par(a::Basis{V,G,B},b::Basis{V,L,C}) where {V,G,B,L,C} = $par(bits(a),bits(b),V) end ### Product Algebra Constructor function generate_product_algebra(Field=Field,MUL=:*,ADD=:+,SUB=:-,VEC=:mvec,CONJ=:conj) if Field == Grassmann.Field - declare_mutating_operations(:(MArray{Tuple{M},T,1,M}),:-,Field,Expr) + declare_mutating_operations(:(MArray{Tuple{M},T,1,M}),Field,Expr,:-,:*) elseif Field ∈ (SymField,:(SymPy.Sym)) - declare_mutating_operations(:(SizedArray{Tuple{M},T,1,1}),SUB,Field,set_val) + declare_mutating_operations(:(SizedArray{Tuple{M},T,1,1}),Field,set_val,SUB,MUL) end Field == :(SymPy.Sym) && for par ∈ (:parany,:parval,:parsym) @eval $par = ($par...,$Field) @@ -418,8 +448,8 @@ function generate_product_algebra(Field=Field,MUL=:*,ADD=:+,SUB=:-,VEC=:mvec,CON @eval begin @inline function inner_product!(mv::MValue{V,0,B,T} where {W,B},α,β,γ::T) where {V,T<:$Field} if γ≠0 - p,C,f = interior(α,β,V) - f && (mv.v = p ? $SUB(mv.v,γ) : $ADD(mv.v,γ)) + g,C,f = interior(α,β,V) + f && (mv.v = typeof(V)<:Signature ? (g ? $SUB(mv.v,γ) : $ADD(mv.v,γ)) : $ADD(mv.v,$MUL(g,γ))) end return mv end @@ -591,7 +621,7 @@ function generate_product_algebra(Field=Field,MUL=:*,ADD=:+,SUB=:-,VEC=:mvec,CON end end end - for side ∈ (:left,:right,:hodge) + for side ∈ (:left,:right) c = Symbol(:complement,side) p = Symbol(:parity,side) for Blade ∈ MSB @@ -601,7 +631,10 @@ function generate_product_algebra(Field=Field,MUL=:*,ADD=:+,SUB=:-,VEC=:mvec,CON out = zeros($VEC(N,G,T)) for k ∈ 1:binomial(N,G) @inbounds val = b.v[k] - @inbounds val≠0 && setblade!(out,$p(V,ib[k]) ? $SUB(val) : val,complement(N,ib[k]),Dimension{N}()) + if val≠0 + v = typeof(V)<:Signature ? ($p(V,ib[k]) ? $SUB(val) : val) : $p(V,ib[k]) + @inbounds setblade!(out,v,complement(N,ib[k]),Dimension{N}()) + end end return $Blade{T,V,N-G}(out) end @@ -615,7 +648,10 @@ function generate_product_algebra(Field=Field,MUL=:*,ADD=:+,SUB=:-,VEC=:mvec,CON ib = indexbasis(N,g-1) @inbounds for i ∈ 1:bn[g] @inbounds val = m.v[bs[g]+i] - @inbounds val≠0 && setmulti!(out,$p(V,ib[i]) ? $SUB(val) : val,complement(N,ib[i]),Dimension{N}()) + if val≠0 + v = typeof(V)<:Signature ? ($p(V,ib[i]) ? $SUB(val) : val) : $p(V,ib[i]) + @inbounds setmulti!(out,v,complement(N,ib[i]),Dimension{N}()) + end end end return MultiVector{T,V}(out) diff --git a/src/forms.jl b/src/forms.jl index a2d2302..7017485 100644 --- a/src/forms.jl +++ b/src/forms.jl @@ -5,7 +5,7 @@ const dualform_cache = Vector{Tuple{Int,Bool}}[] const dualformC_cache = Vector{Tuple{Int,Bool}}[] -@pure function dualform(V::VectorSpace{N}) where {N} +@pure function dualform(V::Signature{N}) where {N} C = dualtype(V)<0 for n ∈ 2length(C ? dualformC_cache : dualform_cache)+2:2:N push!(C ? dualformC_cache : dualform_cache,Tuple{Int,Bool}[]) diff --git a/src/generators.jl b/src/generators.jl index 758db5a..6ffbb2c 100644 --- a/src/generators.jl +++ b/src/generators.jl @@ -77,33 +77,34 @@ function basis(V::VectorSpace,sig::Symbol=vsn[1],label::Symbol=Symbol(pre[1]),du for i ∈ 2:1< ind[k+1] diff --git a/test/runtests.jl b/test/runtests.jl index 67aa51f..2ed4ab4 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -10,5 +10,5 @@ using Test @test (basis"-+++"; h = 1v1+2v2; h⋅h == 3v) !Sys.iswindows() && @test Λ(62).v32a87Ng == -1Λ(62).v2378agN @test Λ.V3 == Λ.C3' -@test Λ(14) + Λ(14)' == Λ(VectorSpace(14)+VectorSpace(14)') +@test Λ(14) + Λ(14)' == Λ(vectorspace(14)+vectorspace(14)') @test ((a,b) = ((:a*Λ(2).v1 + :b*Λ(2).v2),(:c*Λ(2).v1 + :d*Λ(2).v2)); Algebra.:+(a∧b,a⋅b)==a*b)