Skip to content

Commit

Permalink
Add adhoc arithmetics for FreeAssociativeAlgebraElem (#1866)
Browse files Browse the repository at this point in the history
* Add adhoc arithmetics for FreeAssociativeAlgebraElem

* Add more coercions

* Address comment

* Add and use `mul(::FreeAssAlgElem, ::FreeAssAlgElem, ::Coeffs)
  • Loading branch information
lgoettgens authored Oct 18, 2024
1 parent 5ffdd2d commit 983f6ec
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 3 deletions.
51 changes: 48 additions & 3 deletions src/generic/FreeAssociativeAlgebra.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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

################################################################################
#
Expand Down
58 changes: 58 additions & 0 deletions test/generic/FreeAssociativeAlgebra-test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit 983f6ec

Please sign in to comment.