From 43ad81d4ddfac61c9511de601964fa25053d29ab Mon Sep 17 00:00:00 2001 From: kalmarek Date: Wed, 25 Mar 2020 04:19:02 +0100 Subject: [PATCH] separate GWords --- src/Groups.jl | 50 +------------------------------------------------- src/types.jl | 29 +++++++++++++++++++++++++++++ src/words.jl | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 49 deletions(-) create mode 100644 src/words.jl diff --git a/src/Groups.jl b/src/Groups.jl index 76d3752..45c7b54 100644 --- a/src/Groups.jl +++ b/src/Groups.jl @@ -17,53 +17,10 @@ using Markdown include("types.jl") include("gsymbols.jl") include("fallbacks.jl") +include("words.jl") @doc doc""" - - -abstract type GWord{T<:GSymbol} <: GroupElem end - -# fallback definitions -Base.eltype(w::GW) where GW<:GWord = eltype(GW) -@doc doc""" - W::GroupWord{T} <: GWord{T<:GSymbol} <:GroupElem -> Basic representation of element of a finitely presented group. `W.symbols` -> fieldname contains particular group symbols which multiplied constitute a -> group element, i.e. a word in generators. -> As reduction (inside group) of such word may be time consuming we provide -> `savedhash` and `modified` fields as well: -> hash (used e.g. in the `unique` function) is calculated by reducing the word, -> setting `modified` flag to `false` and computing the hash which is stored in -> `savedhash` field. -> whenever word `W` is changed `W.modified` is set to `false`; -> Future comparisons don't perform reduction (and use `savedhash`) as long as -> `modified` flag remains `false`. - """ -mutable struct GroupWord{T} <: GWord{T} - symbols::Vector{T} - modified::Bool - savedhash::UInt - parent::Group - - function GroupWord{T}(symbols::Vector{T}) where {T} - return new{T}(symbols, true, zero(UInt)) - end -end - -syllablelength(w::GWord) = length(w.symbols) -syllables(w::GWord) = w.symbols -ismodified(w::GWord) = w.modified -setmodified!(w::GWord) = (w.modified = true; w) -unsetmodified!(w::GWord) = (w.modified = false; w) -Base.one(w::GWord) = one(parent(w)) - - -############################################################################### -# -# Includes -# -############################################################################### include("FreeGroup.jl") include("FPGroups.jl") @@ -86,11 +43,6 @@ parent(w::GWord{T}) where {T<:GSymbol} = w.parent # ############################################################################### -GroupWord(s::T) where {T<:GSymbol} = GroupWord{T}(T[s]) -GroupWord{T}(s::T) where {T<:GSymbol} = GroupWord{T}(T[s]) -GroupWord(w::GroupWord{T}) where {T<:GSymbol} = w -convert(::Type{GroupWord{T}}, s::T) where {T<:GSymbol} = GroupWord{T}(T[s]) - ############################################################################### # # Basic manipulation diff --git a/src/types.jl b/src/types.jl index 9d93fc8..320b04f 100644 --- a/src/types.jl +++ b/src/types.jl @@ -9,3 +9,32 @@ abstract type AbstractFPGroup <: Group end > * `pow` which is the (multiplicative) exponent of a symbol. """ abstract type GSymbol end + +abstract type GWord{T<:GSymbol} <: GroupElem end + +@doc doc""" + W::GroupWord{T} <: GWord{T<:GSymbol} <:GroupElem +> Basic representation of element of a finitely presented group. `W.symbols` +> fieldname contains particular group symbols which multiplied constitute a +> group element, i.e. a word in generators. +> As reduction (inside group) of such word may be time consuming we provide +> `savedhash` and `modified` fields as well: +> hash (used e.g. in the `unique` function) is calculated by reducing the word, +> setting `modified` flag to `false` and computing the hash which is stored in +> `savedhash` field. +> whenever word `W` is changed `W.modified` is set to `false`; +> Future comparisons don't perform reduction (and use `savedhash`) as long as +> `modified` flag remains `false`. + +""" + +mutable struct GroupWord{T} <: GWord{T} + symbols::Vector{T} + modified::Bool + savedhash::UInt + parent::Group + + function GroupWord{T}(symbols::Vector{<:GSymbol}) where T + return new{T}(symbols, true, zero(UInt)) + end +end diff --git a/src/words.jl b/src/words.jl new file mode 100644 index 0000000..ab08337 --- /dev/null +++ b/src/words.jl @@ -0,0 +1,39 @@ +syllablelength(w::GWord) = length(w.symbols) +syllables(w::GWord) = w.symbols +ismodified(w::GWord) = w.modified +setmodified!(w::GWord) = (w.modified = true; w) +unsetmodified!(w::GWord) = (w.modified = false; w) +savehash!(w::GWord, h::UInt) = (w.savedhash = h; w) +savedhash(w::GWord) = w.savedhash +parent(w::GWord) = w.parent +hasparent(w::GWord) = isdefined(w, :parent) +setparent!(w::GWord, G::AbstractFPGroup) = (w.parent = G; w) + +Base.isempty(w::GWord) = isempty(syllables(w)) +Base.isone(w::GWord) = (freereduce!(w); isempty(w)) +Base.one(w::GWord) = one(parent(w)) + +function Base.iterate(w::GWord, state=(syllable=1, pow=1)) + state.syllable > syllablelength(w) && return nothing + next = iterate(syllables(w)[state.syllable], state.pow) + next === nothing && return iterate(w, (syllable=state.syllable+1, pow=1)) + return first(next), (syllable=state.syllable, pow=last(next)) +end + +Base.eltype(::Type{<:GWord{T}}) where T = T +Base.length(w::GWord) = isempty(w) ? 0 : sum(length, syllables(w)) +Base.size(w::GWord) = (length(w),) +Base.lastindex(w::GWord) = length(w) + +Base.@propagate_inbounds function Base.getindex(w::GWord, i::Integer) + csum = 0 + idx = 0 + @boundscheck 0 < i <= length(w) || throw(BoundsError(w, i)) + while csum < i + idx += 1 + csum += length(syllables(w)[idx]) + end + return first(syllables(w)[idx]) +end + +# no setindex! for syllable based words