separate arithmetic

This commit is contained in:
kalmarek 2020-03-25 04:41:23 +01:00
parent e84152a9cf
commit afa0988ebc
No known key found for this signature in database
GPG Key ID: 8BF1A3855328FC15
2 changed files with 94 additions and 96 deletions

View File

@ -20,6 +20,7 @@ include("fallbacks.jl")
include("words.jl")
include("hashing.jl")
include("freereduce.jl")
include("arithmetic.jl")
include("FreeGroup.jl")
include("FPGroups.jl")
@ -62,102 +63,6 @@ function show(io::IO, s::T) where {T<:GSymbol}
print(io, string((s.id))*"^$(s.pow)")
end
end
###############################################################################
#
# Binary operators
#
###############################################################################
function Base.append!(w::GWord{T}, v::AbstractVector{T}) where T
append!(syllables(w), v)
return w
end
function Base.prepend!(w::GWord{T}, v::AbstractVector{T}) where T
prepend!(syllables(w), v)
return w
end
Base.append!(w::T, v::T) where T <: GWord = append!(w, syllables(v))
Base.prepend!(w::T, v::T) where T <: GWord = prepend!(w, syllables(v))
for (mul, f) in ((:rmul!, :push!), (:lmul!, :pushfirst!))
@eval begin
function $mul(out::T, w::T, s::GSymbol) where T <:GWord
$f(syllables(out), s)
return freereduce!(out)
end
end
end
function rmul!(out::T, x::T, y::T) where T<: GWord
if out === x
out = deepcopy(out)
return freereduce!(append!(out, y))
elseif out === y
out = deepcopy(out)
return freereduce!(prepend!(out, x))
else
slenx = syllablelength(x)
sleny = syllablelength(y)
resize!(syllables(out), slenx+sleny)
syllables(out)[1:slenx] .= syllables(x)
syllables(out)[slenx+1:slenx+sleny] .= syllables(y)
return freereduce!(out)
end
end
lmul!(out::T, x::T, y::T) where T <: GWord = rmul!(out, y, x)
function AbstractAlgebra.mul!(out::T, x::T, y::T) where T <: GWord
return rmul!(out, x, y)
end
(*)(W::GW, Z::GW) where GW <: GWord = rmul!(deepcopy(W), W, Z)
(*)(W::GWord, s::GSymbol) = rmul!(deepcopy(W), W, s)
(*)(s::GSymbol, W::GWord) = lmul!(deepcopy(W), W, s)
function power_by_squaring(W::GWord, p::Integer)
if p < 0
return power_by_squaring(inv(W), -p)
elseif p == 0
return one(parent(W))
elseif p == 1
return W
elseif p == 2
return W*W
end
W = deepcopy(W)
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) > 0
append!(W, W)
end
Z = deepcopy(W)
while p > 0
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) >= 0
append!(W, W)
end
append!(Z, W)
end
return freereduce!(Z)
end
(^)(x::GWord, n::Integer) = power_by_squaring(x,n)
###############################################################################
#
# Inversion
#
###############################################################################
function inv(W::T) where T<:GWord
if length(W) == 0
return W
else
G = parent(W)
w = T([inv(s) for s in Iterators.reverse(syllables(W))])

93
src/arithmetic.jl Normal file
View File

@ -0,0 +1,93 @@
function Base.inv(W::T) where T<:GWord
length(W) == 0 && return W
G = parent(W)
w = T([inv(s) for s in Iterators.reverse(syllables(W))])
return setparent!(w, G)
end
###############################################################################
#
# Binary operators
#
function Base.append!(w::GWord{T}, v::AbstractVector{T}) where T
append!(syllables(w), v)
return w
end
function Base.prepend!(w::GWord{T}, v::AbstractVector{T}) where T
prepend!(syllables(w), v)
return w
end
Base.append!(w::T, v::T) where T <: GWord = append!(w, syllables(v))
Base.prepend!(w::T, v::T) where T <: GWord = prepend!(w, syllables(v))
for (mul, f) in ((:rmul!, :push!), (:lmul!, :pushfirst!))
@eval begin
function $mul(out::T, w::T, s::GSymbol) where T <:GWord
resize!(syllables(out), syllablelength(w))
syllables(out) .= syllables(w)
$f(syllables(out), s)
return freereduce!(out)
end
end
end
function rmul!(out::T, x::T, y::T) where T<: GWord
if out === x
out = deepcopy(out)
return freereduce!(append!(out, y))
elseif out === y
out = deepcopy(out)
return freereduce!(prepend!(out, x))
else
slenx = syllablelength(x)
sleny = syllablelength(y)
resize!(syllables(out), slenx+sleny)
syllables(out)[1:slenx] .= syllables(x)
syllables(out)[slenx+1:slenx+sleny] .= syllables(y)
return freereduce!(out)
end
end
lmul!(out::T, x::T, y::T) where T <: GWord = rmul!(out, y, x)
function AbstractAlgebra.mul!(out::T, x::T, y::T) where T <: GWord
return rmul!(out, x, y)
end
(*)(W::GW, Z::GW) where GW <: GWord = rmul!(deepcopy(W), W, Z)
(*)(W::GWord, s::GSymbol) = rmul!(deepcopy(W), W, s)
(*)(s::GSymbol, W::GWord) = lmul!(deepcopy(W), W, s)
function power_by_squaring(W::GWord, p::Integer)
if p < 0
return power_by_squaring(inv(W), -p)
elseif p == 0
return one(W)
elseif p == 1
return W
elseif p == 2
return W*W
end
W = deepcopy(W)
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) > 0
append!(W, W)
end
Z = deepcopy(W)
while p > 0
t = trailing_zeros(p) + 1
p >>= t
while (t -= 1) >= 0
append!(W, W)
end
append!(Z, W)
end
return freereduce!(Z)
end
(^)(x::GWord, n::Integer) = power_by_squaring(x,n)