From 86a92997b4eaff2d0a27b6c56ed36d9dd9c59681 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20G=C3=B6ttgens?= Date: Fri, 26 Apr 2024 15:56:25 +0200 Subject: [PATCH] Fixes for SparsePolyRing (#1692) --- src/exports.jl | 1 - src/generic/GenericTypes.jl | 1 + src/generic/SparsePoly.jl | 32 ++++++++++++++++++++++++++++++++ test/generic/SparsePoly-test.jl | 16 ++++------------ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/exports.jl b/src/exports.jl index 504ff4d2ce..df8ec1a835 100644 --- a/src/exports.jl +++ b/src/exports.jl @@ -93,7 +93,6 @@ export SetMap export SimpleNumField export SimpleNumFieldElem export SkewDiagram -export SparsePolynomialRing export Strassen export SymmetricGroup export UniversalPolyRing diff --git a/src/generic/GenericTypes.jl b/src/generic/GenericTypes.jl index 77b45df237..e7f2da7ddb 100644 --- a/src/generic/GenericTypes.jl +++ b/src/generic/GenericTypes.jl @@ -458,6 +458,7 @@ end ############################################################################### # Q: Why is SparsePolyRing not a subtype of AbstractAlgebra.PolyRing{T} ? +# A: It is purely internal, and implementing the interface would make it slower. @attributes mutable struct SparsePolyRing{T <: RingElement} <: AbstractAlgebra.Ring base_ring::Ring diff --git a/src/generic/SparsePoly.jl b/src/generic/SparsePoly.jl index 931d68e425..c2e9773215 100644 --- a/src/generic/SparsePoly.jl +++ b/src/generic/SparsePoly.jl @@ -34,6 +34,14 @@ end # ############################################################################### +function Base.hash(a::SparsePoly, h::UInt) + b = 0x679c879b67bb8385%UInt + for i in 1:length(a) + b = xor(b, hash(a.exps[i], hash(a.coeffs[i], h))) + end + return b +end + function coeff(x::SparsePoly, i::Int) i < 0 && throw(DomainError(i, "cannot get the i-th coefficient with i < 0")) return x.coeffs[i + 1] @@ -358,6 +366,8 @@ end ############################################################################### function divides(a::SparsePoly{T}, b::SparsePoly{T}) where {T <: RingElement} + iszero(a) && return true, zero(parent(a)) + iszero(b) && return false, parent(a)() d1 = a.exps[a.length] d2 = b.exps[b.length] - b.exps[1] q_alloc = b.length @@ -811,6 +821,28 @@ function (a::SparsePolyRing{T})(b::Vector{T}, m::Vector{UInt}) where {T <: RingE return z end +# Functions to remove ambiguities +function (a::SparsePolyRing{T})(b::T) where {T <: Integer} + parent(b) != base_ring(a) && error("Unable to coerce to polynomial") + z = SparsePoly{T}(b) + z.parent = a + return z +end + +function (a::SparsePolyRing{T})(b::T) where {T <: Rational} + parent(b) != base_ring(a) && error("Unable to coerce to polynomial") + z = SparsePoly{T}(b) + z.parent = a + return z +end + +function (a::SparsePolyRing{T})(b::T) where {T <: AbstractFloat} + parent(b) != base_ring(a) && error("Unable to coerce to polynomial") + z = SparsePoly{T}(b) + z.parent = a + return z +end + ############################################################################### # # SparsePolynomialRing constructor diff --git a/test/generic/SparsePoly-test.jl b/test/generic/SparsePoly-test.jl index 9582c5bf78..39ebdb341e 100644 --- a/test/generic/SparsePoly-test.jl +++ b/test/generic/SparsePoly-test.jl @@ -1,16 +1,6 @@ -# FIXME/TODO: get these conformance tests to work and pass -#function test_elem(Rx::AbstractAlgebra.Generic.SparsePolyRing) -# R = base_ring(Rx) -# x = gen(Rx) -# return sum(x^(5*i) * test_elem(R) for i in 1:rand(0:6); init=zero(Rx)) -#end -# -#@testset "Generic.SparsePoly.conformance" begin -# R, x = SparsePolynomialRing(ZZ, "x") -# test_Ring_interface(R) -#end - @testset "Generic.SparsePoly.constructors" begin + SparsePolynomialRing = AbstractAlgebra.SparsePolynomialRing + R, x = SparsePolynomialRing(ZZ, "x") S, y = SparsePolynomialRing(R, "y") @@ -25,6 +15,8 @@ end @testset "Generic.SparsePoly.printing" begin + SparsePolynomialRing = AbstractAlgebra.SparsePolynomialRing + R, x = SparsePolynomialRing(ZZ, "x") @test string(zero(R)) == "0"