diff --git a/src/arithmetic.jl b/src/arithmetic.jl index 9645323..346a1a4 100644 --- a/src/arithmetic.jl +++ b/src/arithmetic.jl @@ -30,12 +30,24 @@ end function MA.promote_operation(::typeof(*), ::Type{T}, ::Type{A}) where {T<:Number, A<:AlgebraElement} return algebra_promote_operation(*, A, T) end -function Base.:*(a::Number, X::AlgebraElement) - return MA.operate_to!(_preallocate_output(*, X, a), *, X, a) +function Base.:*(a::Any, X::AlgebraElement) + return MA.operate_to!(_preallocate_output(*, X, a), *, a, X) end function Base.:div(X::AlgebraElement, a::Number) return MA.operate_to!(_preallocate_output(div, X, a), div, X, a) end +function Base.:*( + a::T, + X::AlgebraElement{A}, +) where {T,O,A<:AbstractStarAlgebra{O,T}} + return MA.operate_to!(similar(X), __lmul, a, X) +end +function Base.:*( + X::AlgebraElement{A}, + a::T, +) where {T,O,A<:AbstractStarAlgebra{O,T}} + return MA.operate_to!(similar(X), __rmul, a, X) +end for op in [:+, :-, :*] @eval begin @@ -64,11 +76,11 @@ end function MA.operate_to!( res::AlgebraElement, ::typeof(*), + a::Any, X::AlgebraElement, - a::Number, ) @assert parent(res) === parent(X) - MA.operate_to!(coeffs(res), *, coeffs(X), a) + MA.operate_to!(coeffs(res), *, a, coeffs(X)) return res end @@ -83,6 +95,17 @@ function MA.operate_to!( return res end +function MA.operate_to!( + res::AlgebraElement, + mul::Union{typeof(__lmul),typeof(__rmul)}, + a, + X::AlgebraElement, +) + @assert parent(res) == parent(X) + MA.operate_to!(coeffs(res), mul, a, coeffs(X)) + return res +end + function MA.operate_to!(res::AlgebraElement, ::typeof(-), X::AlgebraElement) @assert parent(res) === parent(X) MA.operate_to!(coeffs(res), -, coeffs(X)) @@ -118,9 +141,7 @@ function MA.operate_to!( args::Vararg{AlgebraElement,N}, ) where {N} for arg in args - if arg isa AlgebraElement - @assert parent(res) == parent(arg) - end + @assert parent(res) == parent(arg) end mstr = mstructure(basis(res)) MA.operate_to!(coeffs(res), mstr, coeffs.(args)...) @@ -133,9 +154,7 @@ function MA.operate!( args::Vararg{AlgebraElement,N}, ) where {N} for arg in args - if arg isa AlgebraElement - @assert parent(res) == parent(arg) - end + @assert parent(res) == parent(arg) end mstr = mstructure(basis(res)) MA.operate!(UnsafeAddMul(mstr), coeffs(res), coeffs.(args)...) diff --git a/src/coefficients.jl b/src/coefficients.jl index d6edde2..9330350 100644 --- a/src/coefficients.jl +++ b/src/coefficients.jl @@ -122,12 +122,12 @@ end Base.zero(X::AbstractCoefficients) = MA.operate!(zero, similar(X)) Base.:-(X::AbstractCoefficients) = MA.operate_to!(__prealloc(X, -1, *), -, X) -Base.:*(a::Number, X::AbstractCoefficients) = X * a -Base.:/(X::AbstractCoefficients, a::Number) = X * inv(a) +Base.:*(X::AbstractCoefficients, a::Any) = a * X +Base.:/(X::AbstractCoefficients, a::Number) = inv(a) * X Base.://(X::AbstractCoefficients, a::Number) = X * 1 // a -function Base.:*(X::AbstractCoefficients, a::Number) - return MA.operate_to!(__prealloc(X, a, *), *, X, a) +function Base.:*(a::Any, X::AbstractCoefficients) + return MA.operate_to!(__prealloc(X, a, *), *, a, X) end function Base.:div(X::AbstractCoefficients, a::Number) return MA.operate_to!(__prealloc(X, a, div), div, X, a) @@ -167,8 +167,8 @@ end function MA.operate_to!( res::AbstractCoefficients, ::typeof(*), + a::Any, X::AbstractCoefficients, - a::Number, ) if res !== X MA.operate!(zero, res) @@ -240,3 +240,25 @@ function MA.operate_to!( end return res end + +__lmul(a, k) = a * k +__rmul(a, k) = k * a + +function MA.operate_to!( + res::AbstractCoefficients, + mul::Union{typeof(__lmul),typeof(__rmul)}, + a, + X::AbstractCoefficients, +) + if res === X + throw("No aliasing is allowed in shift") + else + MA.operate!(zero, res) + for (k, v) in nonzero_pairs(X) + res[mul(a, k)] += v + end + end + return res +end + + diff --git a/test/abstract_coeffs.jl b/test/abstract_coeffs.jl index 4474945..c4aa1d5 100644 --- a/test/abstract_coeffs.jl +++ b/test/abstract_coeffs.jl @@ -60,4 +60,10 @@ @test norm(fP2m) == norm(P2m) == norm(fP2m) v = coeffs(P2m, basis(fRG)) # an honest vector @test dot(fP2m, fP2m) == dot(coeffs(fP2m), v) == dot(v, coeffs(fP2m)) + + s1, s2 = PermutationGroups.gens(G) + @assert s1 * s2 ≠ s2 * s1 + Z = RG(1) + RG(s1) + @test s2 * Z == RG(s2) + RG(s2 * s1) + @test Z * s2 == RG(s2) + RG(s1 * s2) end diff --git a/test/monoid_algebra.jl b/test/monoid_algebra.jl index 9a3117c..8be47ca 100644 --- a/test/monoid_algebra.jl +++ b/test/monoid_algebra.jl @@ -73,8 +73,8 @@ @test coeffs(Z) == coeffs(fZ, basis(RG)) @test coeffs(fZ) == coeffs(Z, basis(fRG)) - @test coeffs(2 * X * Y) == coeffs(MA.operate_to!(Z, *, Z, 2)) - @test coeffs(2 * fX * fY) == coeffs(MA.operate_to!(fZ, *, fZ, 2)) + @test coeffs(2 * X * Y) == coeffs(MA.operate_to!(Z, *, 2, Z)) + @test coeffs(2 * fX * fY) == coeffs(MA.operate_to!(fZ, *, 2, fZ)) end end @testset "mutable arithmetic" begin @@ -118,19 +118,19 @@ end let d = deepcopy(a) - MA.operate_to!(d, *, a, 2) + MA.operate_to!(d, *, 2, a) @test d == 2a - MA.operate_to!(d, *, d, 2) + MA.operate_to!(d, *, 2, d) @test d == 4a MA.operate_to!(d, *, a, b) @test d == a * b @test_throws ArgumentError MA.operate_to!(d, *, d, b) d = deepcopy(a) - @test @allocated(MA.operate_to!(d, *, d, 2)) == 0 + @test @allocated(MA.operate_to!(d, *, 2, d)) == 0 @test d == 2a - @test @allocated(MA.operate_to!(d, *, a, 2)) == 0 + @test @allocated(MA.operate_to!(d, *, 2, a)) == 0 @test d == 2a MA.operate!(zero, d)