diff --git a/src/generic/FreeAssociativeAlgebra.jl b/src/generic/FreeAssociativeAlgebra.jl index b82756a4a..c7e920689 100644 --- a/src/generic/FreeAssociativeAlgebra.jl +++ b/src/generic/FreeAssociativeAlgebra.jl @@ -133,10 +133,14 @@ function (a::FreeAssociativeAlgebra{T})(b::T) where T return FreeAssociativeAlgebraElem{T}(a, T[b], [Int[]], 1) end -function (a::FreeAssociativeAlgebra{T})(b::Integer) where T - iszero(b) && return zero(a) +function (a::FreeAssociativeAlgebra{T})(b::Union{Integer, Rational, AbstractFloat}) where T R = base_ring(a) - return FreeAssociativeAlgebraElem{T}(a, T[R(b)], [Int[]], 1) + return a(R(b)) +end + +function (a::FreeAssociativeAlgebra{T})(b::T) where {T <: Union{Integer, Rational, AbstractFloat}} + iszero(b) && return zero(a) + return FreeAssociativeAlgebraElem{T}(a, T[b], [Int[]], 1) end function (a::FreeAssociativeAlgebra{T})(b::FreeAssociativeAlgebraElem{T}) where T <: RingElement @@ -633,6 +637,20 @@ end # ############################################################################### +function *(a::FreeAssociativeAlgebraElem, n::Union{Integer, Rational, AbstractFloat}) + z = zero(a) + return mul!(z, a, n) +end + +function *(a::FreeAssociativeAlgebraElem{T}, n::T) where {T <: RingElem} + z = zero(a) + return mul!(z, a, n) +end + +*(n::Union{Integer, Rational, AbstractFloat}, a::FreeAssociativeAlgebraElem) = a*n + +*(n::T, a::FreeAssociativeAlgebraElem{T}) where {T <: RingElem} = a*n + function divexact( a::FreeAssociativeAlgebraElem{T}, b::Integer; @@ -786,6 +804,33 @@ function sub!(z::FreeAssociativeAlgebraElem{T}, a::FreeAssociativeAlgebraElem{T} return z end +function mul!(a::FreeAssociativeAlgebraElem{T}, n::Union{Integer, Rational, AbstractFloat, T}) where T <: RingElement + for i in 1:length(a) + a.coeffs[i] = mul!(a.coeffs[i], n) + end + return a +end + +function mul!(z::FreeAssociativeAlgebraElem{T}, a::FreeAssociativeAlgebraElem{T}, n::Union{Integer, Rational, AbstractFloat, T}) where T <: RingElement + if z === a + return mul!(a, n) + end + fit!(z, length(a)) + j = 1 + for i = 1:length(a) + if isassigned(z.coeffs, j) + z.coeffs[j] = mul!(z.coeffs[j], a.coeffs[i], n) + else + z.coeffs[j] = a.coeffs[i] * n + end + if !iszero(z.coeffs[j]) + z.exps[j] = a.exps[i] + j += 1 + end + end + z.length = j - 1 + return z +end ################################################################################ # diff --git a/test/generic/FreeAssociativeAlgebra-test.jl b/test/generic/FreeAssociativeAlgebra-test.jl index 5ee356686..a89e3e363 100644 --- a/test/generic/FreeAssociativeAlgebra-test.jl +++ b/test/generic/FreeAssociativeAlgebra-test.jl @@ -216,6 +216,64 @@ end end end +@testset "Generic.FreeAssociativeAlgebra.adhoc_binary" begin + R, x = ZZ["y"] + + for num_vars = 1:10 + var_names = ["x$j" for j in 1:num_vars] + + S, varlist = free_associative_algebra(R, var_names) + + for iter = 1:100 + f = rand(S, 0:5, 0:100, 0:0, -100:100) + + d1 = rand(-20:20) + d2 = rand(-20:20) + g1 = rand(R, 0:2, -10:10) + g2 = rand(R, 0:2, -10:10) + + @test f*d1 + f*d2 == (d1 + d2)*f + @test f*BigInt(d1) + f*BigInt(d2) == (BigInt(d1) + BigInt(d2))*f + @test f*g1 + f*g2 == (g1 + g2)*f + + @test f + d1 + d2 == d1 + d2 + f + @test f + BigInt(d1) + BigInt(d2) == BigInt(d1) + BigInt(d2) + f + @test f + g1 + g2 == g1 + g2 + f + + @test f - d1 - d2 == -((d1 + d2) - f) + @test f - BigInt(d1) - BigInt(d2) == -((BigInt(d1) + BigInt(d2)) - f) + @test f - g1 - g2 == -((g1 + g2) - f) + + @test f + d1 - d1 == f + @test f + BigInt(d1) - BigInt(d1) == f + @test f + g1 - g1 == f + + if !iszero(d1) + @test divexact(d1 * f, d1) == f + @test divexact(d1 * f, BigInt(d1)) == f + end + end + end + + S, (x,y) = free_associative_algebra(QQ, [:x, :y]) + f = x^2 + x*y^2*x + QQ(5)*y - QQ(1//2)*y*x + + @test 2 + f == QQ(2) + f + @test f + 2 == f + QQ(2) + @test 1//2 + f == QQ(1//2) + f + @test f + 1//2 == f + QQ(1//2) + + @test 2 - f == QQ(2) - f + @test f - 2 == f - QQ(2) + @test 1//2 - f == QQ(1//2) - f + @test f - 1//2 == f - QQ(1//2) + + @test 2 * f == QQ(2) * f + @test f * 2 == f * QQ(2) + @test 1//2 * f == QQ(1//2) * f + @test f * 1//2 == f * QQ(1//2) +end + @testset "Generic.FreeAssociativeAlgebra.NCRing_interface" begin S, = free_associative_algebra(ZZ, 3) test_NCRing_interface(S)