diff --git a/src/GroupRings.jl b/src/GroupRings.jl index 6f3ffaa..28df494 100644 --- a/src/GroupRings.jl +++ b/src/GroupRings.jl @@ -569,6 +569,7 @@ module New include("bases.jl") include("mstructures.jl") +include("mtables.jl") end diff --git a/src/mtables.jl b/src/mtables.jl new file mode 100644 index 0000000..ad72c23 --- /dev/null +++ b/src/mtables.jl @@ -0,0 +1,73 @@ +abstract type AbstractMTable{I,Tw} <: MultiplicativeStructure{Tw,I} end + +Base.size(mt::AbstractMTable) = size(mt.table) + +_check(mt::AbstractMTable) = check(mt.table, basis(mt), _istwisted(mt)) + +function _check(product_matrix, basis, twisted::Bool) + idx = findfirst(iszero, product_matrix) + if idx != nothing + i, j = Tuple(idx) + x = (twisted ? star(basis[i]) : basis[i]) + throw(ProductNotDefined(i, j, "$x ยท $(basis[j]) = + $(_product(Val(twisted), x, basis[j]))")) + end + return true +end + +_iscached(mt::AbstractMTable, i, j) = !iszero(mt.table[i, j]) + + +## MTables + +struct MTable{I,Twisted,M<:AbstractMatrix{I}} <: AbstractMTable{I,Twisted} + table::M +end + +MTable{Tw}(mt::AbstractMatrix{<:Integer}) where {Tw} = MTable{eltype(mt),Tw,typeof(mt)}(mt) + +MTable(b::AbstractBasis; table_size) = MTable{false}(b; table_size = table_size) + +function MTable{Tw}(basis::AbstractBasis; table_size) where {Tw} + @assert length(table_size) == 2 + @assert 1 <= first(table_size) <= length(basis) + @assert 1 <= last(table_size) <= length(basis) + + table = zeros(SparseArrays.indtype(basis), table_size) + + complete!(table, basis, Val(Tw)) + + _check(table, basis, Tw) + + return MTable{Tw}(table) +end + +function complete!(table, basis, ::Val{false}) + Threads.@threads for j in 1:size(table, 2) + y = basis[j] + for i in 1:size(table, 1) + table[i, j] = basis[_product(Val(false), basis[i] ,y)] + end + end + return table +end + +function complete!(table, basis, ::Val{true}) + Threads.@threads for i in 1:size(table, 1) + x = star(basis[i]) + for j in 1:size(table, 2) + # star(x)*y + table[i, j] = basis[_product(Val(false), x, basis[j])] + end + end + return table +end + +basis(mt::MTable) = throw("No basis is defined for a simple $(typeof(mt))") + +Base.@propagate_inbounds function Base.getindex(m::MTable, i::Integer, j::Integer) + @boundscheck checkbounds(m, i, j) + @boundscheck iszero(m.table[i, j]) && throw(ProductNotDefined(i, j)) + return m.table[i, j] +end +