Groups.jl/src/iteration.jl

60 lines
1.4 KiB
Julia

import OrderedCollections: OrderedSet
mutable struct FPGroupIter{S,T,GEl}
seen::S
seen_iter_state::T
current::GEl
gen_idx::Int
u_tmp::GEl
v_tmp::GEl
end
function Base.iterate(G::AbstractFPGroup)
seen = OrderedSet([one(G)])
current, seen_state = iterate(seen)
gr_iter = FPGroupIter(seen, seen_state, current, 1, one(G), one(G))
return one(G), gr_iter
end
function _next_elt!(itr::FPGroupIter)
res = iterate(itr.seen, itr.seen_iter_state)
res === nothing && return true
itr.current = first(res)
itr.seen_iter_state = last(res)
itr.gen_idx = 1
return false
end
function Base.iterate(G::AbstractFPGroup, state)
if state.gen_idx > length(alphabet(G))
finished = _next_elt!(state)
finished && return nothing
end
elt = let u = state.u_tmp, v = state.v_tmp, current = state.current
copyto!(v, current)
push!(word(v), state.gen_idx)
_setnormalform!(v, false)
_setvalidhash!(v, false)
@assert !isnormalform(v)
resize!(word(u), 0)
normalform!(u, v)
end
state.gen_idx += 1
if elt in state.seen
return iterate(G, state)
else
@assert isnormalform(elt)
push!(state.seen, deepcopy(elt))
return elt, state
end
end
# Groups.Core default:
# Base.IteratorSize(::Type{<:AbstractFPGroup}) = Base.SizeUnknown()