2021-05-16 22:47:20 +02:00
|
|
|
|
struct Transvection <: GSymbol
|
|
|
|
|
id::Symbol
|
|
|
|
|
ij::UInt8
|
|
|
|
|
inv::Bool
|
|
|
|
|
|
2021-05-16 23:22:33 +02:00
|
|
|
|
function Transvection(id::Symbol, i::Integer, j::Integer, inv = false)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
@assert id in (:ϱ, :λ)
|
2021-06-28 09:29:32 +02:00
|
|
|
|
@boundscheck @assert 0 < i <= (typemax(UInt8) >> 4)
|
|
|
|
|
@boundscheck @assert 0 < j <= (typemax(UInt8) >> 4)
|
|
|
|
|
return new(id, (convert(UInt8, i) << 4) + convert(UInt8, j), inv)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
ϱ(i, j) = Transvection(:ϱ, i, j)
|
|
|
|
|
λ(i, j) = Transvection(:λ, i, j)
|
|
|
|
|
|
2021-06-28 09:29:32 +02:00
|
|
|
|
_tophalf(ij::UInt8) = (ij & 0xf0) >> 4
|
|
|
|
|
_bothalf(ij::UInt8) = (ij & 0x0f)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
|
|
|
|
|
function Base.getproperty(t::Transvection, s::Symbol)
|
2021-06-28 09:29:32 +02:00
|
|
|
|
s === :i && return _tophalf(t.ij)
|
|
|
|
|
s === :j && return _bothalf(t.ij)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
return Core.getfield(t, s)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function Base.show(io::IO, t::Transvection)
|
|
|
|
|
id = if t.id === :ϱ
|
2021-06-21 17:53:29 +02:00
|
|
|
|
'ϱ'
|
2021-05-16 22:47:20 +02:00
|
|
|
|
else # if t.id === :λ
|
2021-06-21 17:53:29 +02:00
|
|
|
|
'λ'
|
2021-05-16 22:47:20 +02:00
|
|
|
|
end
|
2021-06-21 17:53:29 +02:00
|
|
|
|
print(io, id, subscriptify(t.i), '.', subscriptify(t.j))
|
2021-05-16 22:47:20 +02:00
|
|
|
|
t.inv && print(io, "^-1")
|
|
|
|
|
end
|
|
|
|
|
|
2021-06-28 09:29:32 +02:00
|
|
|
|
Base.inv(t::Transvection) =
|
|
|
|
|
Transvection(t.id, _tophalf(t.ij), _bothalf(t.ij), !t.inv)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
|
|
|
|
|
Base.:(==)(t::Transvection, s::Transvection) =
|
|
|
|
|
t.id === s.id && t.ij == s.ij && t.inv == s.inv
|
|
|
|
|
Base.hash(t::Transvection, h::UInt) = hash(t.id, hash(t.ij, hash(t.inv, h)))
|
|
|
|
|
|
2021-06-07 20:23:04 +02:00
|
|
|
|
Base.@propagate_inbounds function evaluate!(v::NTuple{T, N}, t::Transvection, A::Alphabet, tmp=one(first(v))) where {T, N}
|
2021-06-28 09:29:32 +02:00
|
|
|
|
i, j = t.i, t.j
|
2021-05-16 22:47:20 +02:00
|
|
|
|
@assert i ≤ length(v) && j ≤ length(v)
|
|
|
|
|
|
|
|
|
|
@inbounds begin
|
|
|
|
|
if t.id === :ϱ
|
|
|
|
|
if !t.inv
|
|
|
|
|
append!(word(v[i]), word(v[j]))
|
|
|
|
|
else
|
|
|
|
|
# append!(word(v[i]), inv(A, word(v[j])))
|
|
|
|
|
for l in Iterators.reverse(word(v[j]))
|
|
|
|
|
push!(word(v[i]), inv(A, l))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
else # if t.id === :λ
|
|
|
|
|
if !t.inv
|
|
|
|
|
# prepend!(word(v[i]), word(v[j]))
|
|
|
|
|
for l in Iterators.reverse(word(v[j]))
|
|
|
|
|
pushfirst!(word(v[i]), l)
|
|
|
|
|
end
|
|
|
|
|
else
|
|
|
|
|
# prepend!(word(v[i]), inv(A, word(v[j])))
|
|
|
|
|
for l in word(v[j])
|
|
|
|
|
pushfirst!(word(v[i]), inv(A, l))
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
_setnormalform!(v[i], false)
|
|
|
|
|
_setvalidhash!(v[i], false)
|
|
|
|
|
end
|
2021-05-26 12:06:40 +02:00
|
|
|
|
normalform!(tmp, v[i])
|
|
|
|
|
copyto!(v[i], tmp)
|
2021-05-16 22:47:20 +02:00
|
|
|
|
|
|
|
|
|
return v
|
|
|
|
|
end
|