diff --git a/docs/src/ring_interface.md b/docs/src/ring_interface.md index da5bdd32c4..ec5cd45391 100644 --- a/docs/src/ring_interface.md +++ b/docs/src/ring_interface.md @@ -900,7 +900,7 @@ function ==(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement end function isequal(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - check_parent(f, g) + parent(f) == parent(g) || return false return isequal(f.c, g.c) end diff --git a/src/AbsSeries.jl b/src/AbsSeries.jl index a6eb4ace5f..719bb1867f 100644 --- a/src/AbsSeries.jl +++ b/src/AbsSeries.jl @@ -486,8 +486,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::AbsPowerSeriesRingElem{T}, y::AbsPowerSeriesRingElem{T}) where T <: RingElement - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) prec = min(precision(x), precision(y)) m1 = min(length(x), length(y)) @@ -523,9 +522,8 @@ power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::AbsPowerSeriesRingElem{T}, y::AbsPowerSeriesRingElem{T}) where T <: RingElement - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false + if precision(x) != precision(y) || length(x) != length(y) return false end diff --git a/src/Fraction.jl b/src/Fraction.jl index 05e5a41f5d..a8abbe22e5 100644 --- a/src/Fraction.jl +++ b/src/Fraction.jl @@ -417,8 +417,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::FracElem{T}, y::FracElem{T}) where {T <: RingElem} - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) return (denominator(x, false) == denominator(y, false) && numerator(x, false) == numerator(y, false)) || @@ -437,9 +436,7 @@ inexact, e.g. power series. Only if the power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::FracElem{T}, y::FracElem{T}) where {T <: RingElem} - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false return isequal(numerator(x, false)*denominator(y, false), denominator(x, false)*numerator(y, false)) end diff --git a/src/Matrix.jl b/src/Matrix.jl index c60217cfe9..c3d33cbd32 100644 --- a/src/Matrix.jl +++ b/src/Matrix.jl @@ -1303,8 +1303,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement} - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) for i = 1:nrows(x) for j = 1:ncols(x) if x[i, j] != y[i, j] @@ -1324,8 +1323,7 @@ series. Only if the power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::MatrixElem{T}, y::MatrixElem{T}) where {T <: NCRingElement} - b = check_parent(x, y, false) - !b && return false + parent(x) == parent(y) || return false for i = 1:nrows(x) for j = 1:ncols(x) if !isequal(x[i, j], y[i, j]) diff --git a/src/NCPoly.jl b/src/NCPoly.jl index e27c49c396..87383213ce 100644 --- a/src/NCPoly.jl +++ b/src/NCPoly.jl @@ -342,15 +342,13 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::NCPolyRingElem{T}, y::NCPolyRingElem{T}) where T <: NCRingElem - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) if length(x) != length(y) return false - else - for i = 1:length(x) - if coeff(x, i - 1) != coeff(y, i - 1) - return false - end + end + for i = 1:length(x) + if coeff(x, i - 1) != coeff(y, i - 1) + return false end end return true @@ -365,9 +363,7 @@ power series. Only if the power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::NCPolyRingElem{T}, y::NCPolyRingElem{T}) where T <: NCRingElem - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false if length(x) != length(y) return false end diff --git a/src/NCRings.jl b/src/NCRings.jl index 1a33ac9e9b..d1893ba19c 100644 --- a/src/NCRings.jl +++ b/src/NCRings.jl @@ -83,15 +83,22 @@ end *(x::NCRingElement, y::NCRingElem) = parent(y)(x)*y -function ==(x::NCRingElem, y::NCRingElem) - fl, u, v = try_promote(x, y) - if fl - return u == v - else - return false - end - end - +# == throws an error when inputs have different parent to help user +# find bugs in their code +function ==(a::NCRingElem, b::NCRingElem) + check_parent(a, b) + throw(NotImplementedError(:(==), x, y)) +end + +# isequal treats ring elements with differing parent as simply being not equal +# (instead of throwing an exception like == does) as it is used to compare set +# elements or keys in dictionaries, and there it seems at least plausible to +# allow mixed parents +function isequal(a::NCRingElem, b::NCRingElem) + return parent(a) == parent(b) && a == b +end + + ==(x::NCRingElem, y::NCRingElement) = x == parent(x)(y) ==(x::NCRingElement, y::NCRingElem) = parent(y)(x) == y diff --git a/src/Poly.jl b/src/Poly.jl index 2bbaf01c1a..d25095d1df 100644 --- a/src/Poly.jl +++ b/src/Poly.jl @@ -839,15 +839,14 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::PolyRingElem{T}, y::PolyRingElem{T}) where T <: RingElement - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) + if length(x) != length(y) return false - else - for i = 1:length(x) - if coeff(x, i - 1) != coeff(y, i - 1) - return false - end + end + for i = 1:length(x) + if coeff(x, i - 1) != coeff(y, i - 1) + return false end end return true @@ -862,9 +861,8 @@ power series. Only if the power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::PolyRingElem{T}, y::PolyRingElem{T}) where T <: RingElement - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false + if length(x) != length(y) return false end diff --git a/src/RelSeries.jl b/src/RelSeries.jl index ca6d792d58..a0f5899b36 100644 --- a/src/RelSeries.jl +++ b/src/RelSeries.jl @@ -727,8 +727,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::RelPowerSeriesRingElem{T}, y::RelPowerSeriesRingElem{T}) where T <: RingElement - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) xval = valuation(x) xprec = precision(x) @@ -762,9 +761,8 @@ power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::RelPowerSeriesRingElem{T}, y::RelPowerSeriesRingElem{T}) where T <: RingElement - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false + if precision(x) != precision(y) || pol_length(x) != pol_length(y) || valuation(x) != valuation(y) return false diff --git a/src/Residue.jl b/src/Residue.jl index 89126cb566..b506d34408 100644 --- a/src/Residue.jl +++ b/src/Residue.jl @@ -243,8 +243,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(a::ResElem{T}, b::ResElem{T}) where {T <: RingElement} - fl = check_parent(a, b, false) - !fl && return false + check_parent(a, b) return data(a) == data(b) end @@ -257,8 +256,7 @@ Only if the power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(a::ResElem{T}, b::ResElem{T}) where {T <: RingElement} - fl = check_parent(a, b, false) - !fl && return false + parent(a) == parent(b) || return false return isequal(data(a), data(b)) end diff --git a/src/ResidueField.jl b/src/ResidueField.jl index 0bea998023..c98205e089 100644 --- a/src/ResidueField.jl +++ b/src/ResidueField.jl @@ -227,8 +227,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(a::ResFieldElem{T}, b::ResFieldElem{T}) where {T <: RingElement} - fl = check_parent(a, b, false) - !fl && return false + check_parent(a, b) return data(a) == data(b) end diff --git a/src/Rings.jl b/src/Rings.jl index 7a14c0d773..41d107a45d 100644 --- a/src/Rings.jl +++ b/src/Rings.jl @@ -4,10 +4,6 @@ # ############################################################################### -function isequal(a::RingElem, b::RingElem) - return parent(a) == parent(b) && a == b -end - # Implement `isapprox` for ring elements via equality by default. On the one # hand, we need isapprox methods to be able to conformance test series rings. # On the other hand this is essentially the only sensible thing to do in diff --git a/src/algorithms/GenericFunctions.jl b/src/algorithms/GenericFunctions.jl index 2be55cb187..5c7f1d5b67 100644 --- a/src/algorithms/GenericFunctions.jl +++ b/src/algorithms/GenericFunctions.jl @@ -113,7 +113,7 @@ end Return `mod(f^e, m)` but possibly computed more efficiently. """ function powermod(a::T, n::Integer, m::T) where T <: RingElem - parent(a) == parent(m) || error("Incompatible parents") + check_parent(a, m) if n > 1 return internal_powermod(a, n, m) elseif n == 1 @@ -149,7 +149,7 @@ case `q` is set to the quotient, or `flag` is set to `false` and `q` is set to `zero(f)`. """ function divides(a::T, b::T) where T <: RingElem - parent(a) == parent(b) || error("Incompatible parents") + check_parent(a, b) if iszero(b) return iszero(a), b end @@ -166,7 +166,7 @@ the cofactor after $f$ is divided by this power. See also [`valuation`](@ref), which only returns the valuation. """ function remove(a::T, b::T) where T <: Union{RingElem, Number} - parent(a) == parent(b) || error("Incompatible parents") + check_parent(a, b) if (iszero(b) || is_unit(b)) throw(ArgumentError("Second argument must be a non-zero non-unit")) end @@ -205,7 +205,7 @@ any other common divisor of $a$ and $b$ divides $g$. way that if the return is a unit, that unit should be one. """ function gcd(a::T, b::T) where T <: RingElem - parent(a) == parent(b) || error("Incompatible parents") + check_parent(a, b) while !iszero(b) (a, b) = (b, mod(a, b)) end @@ -287,7 +287,7 @@ Return a triple `d, s, t` such that $d = gcd(f, g)$ and $d = sf + tg$, with $s$ loosely reduced modulo $g/d$ and $t$ loosely reduced modulo $f/d$. """ function gcdx(a::T, b::T) where T <: RingElem - parent(a) == parent(b) || error("Incompatible parents") + check_parent(a, b) R = parent(a) if iszero(a) if iszero(b) diff --git a/src/generic/FactoredFraction.jl b/src/generic/FactoredFraction.jl index eb31cba731..11c09ec9a4 100644 --- a/src/generic/FactoredFraction.jl +++ b/src/generic/FactoredFraction.jl @@ -304,7 +304,7 @@ function *(b::Integer, a::FactoredFracFieldElem{T}) where T <: RingElem end function *(b::FactoredFracFieldElem{T}, c::FactoredFracFieldElem{T}) where T <: RingElement - parent(b) == parent(c) || error("Incompatible rings") + check_parent(b, c) input_is_good = _bases_are_coprime(b) && _bases_are_coprime(b) z = FactoredFracFieldElem{T}(b.unit*c.unit, FactoredFracTerm{T}[], parent(b)) if iszero(z.unit) diff --git a/src/generic/FreeAssociativeAlgebra.jl b/src/generic/FreeAssociativeAlgebra.jl index b82756a4a7..13c686b5f3 100644 --- a/src/generic/FreeAssociativeAlgebra.jl +++ b/src/generic/FreeAssociativeAlgebra.jl @@ -295,8 +295,7 @@ end ############################################################################### function ==(a::FreeAssociativeAlgebraElem{T}, b::FreeAssociativeAlgebraElem{T}) where T - fl = check_parent(a, b, false) - !fl && return false + check_parent(a, b) return a.length == b.length && view(a.exps, 1:a.length) == view(b.exps, 1:b.length) && view(a.coeffs, 1:a.length) == view(b.coeffs, 1:b.length) diff --git a/src/generic/LaurentMPoly.jl b/src/generic/LaurentMPoly.jl index 2c00ddc846..8547d69dbc 100644 --- a/src/generic/LaurentMPoly.jl +++ b/src/generic/LaurentMPoly.jl @@ -132,7 +132,7 @@ end ############################################################################### function ==(a::LaurentMPolyWrap, b::LaurentMPolyWrap) - check_parent(a, b, false) || return false + check_parent(a, b) if a.mindegs == b.mindegs return a.mpoly == b.mpoly end diff --git a/src/generic/LaurentPoly.jl b/src/generic/LaurentPoly.jl index f50c7d858d..b3507c98c1 100644 --- a/src/generic/LaurentPoly.jl +++ b/src/generic/LaurentPoly.jl @@ -237,7 +237,7 @@ function canonical_unit(p::LaurentPolyWrap) end function gcd(p::LaurentPolyWrap{T}, q::LaurentPolyWrap{T}) where T - parent(p) == parent(q) || error("Incompatible parents") + check_parent(p, q) if iszero(p) return divexact(q, canonical_unit(q)) elseif iszero(q) @@ -249,7 +249,7 @@ function gcd(p::LaurentPolyWrap{T}, q::LaurentPolyWrap{T}) where T end function gcdx(a::LaurentPolyWrap{T}, b::LaurentPolyWrap{T}) where T - parent(a) == parent(b) || error("Incompatible parents") + check_parent(a, b) R = parent(a) if iszero(a) if iszero(b) diff --git a/src/generic/LaurentSeries.jl b/src/generic/LaurentSeries.jl index 9f5bb1e560..b0e3ac4230 100644 --- a/src/generic/LaurentSeries.jl +++ b/src/generic/LaurentSeries.jl @@ -1037,8 +1037,7 @@ that power series to different precisions may still be arithmetically equal to the minimum of the two precisions. """ function ==(x::LaurentSeriesElem{T}, y::LaurentSeriesElem{T}) where {T <: RingElement} - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) xval = valuation(x) xprec = precision(x) yval = valuation(y) @@ -1094,9 +1093,7 @@ power series are precisely the same, to the same precision, are they declared equal by this function. """ function isequal(x::LaurentSeriesElem{T}, y::LaurentSeriesElem{T}) where {T <: RingElement} - if parent(x) != parent(y) - return false - end + parent(x) == parent(y) || return false if precision(x) != precision(y) || pol_length(x) != pol_length(y) || valuation(x) != valuation(y) || scale(x) != scale(y) return false diff --git a/src/generic/MPoly.jl b/src/generic/MPoly.jl index 96861478bd..216a220984 100644 --- a/src/generic/MPoly.jl +++ b/src/generic/MPoly.jl @@ -2022,8 +2022,7 @@ end ############################################################################### function ==(a::MPoly{T}, b::MPoly{T}) where {T <: RingElement} - fl = check_parent(a, b, false) - !fl && return false + check_parent(a, b) if a.length != b.length return false end diff --git a/src/generic/PuiseuxSeries.jl b/src/generic/PuiseuxSeries.jl index 0dcf434951..2ad0ca50a9 100644 --- a/src/generic/PuiseuxSeries.jl +++ b/src/generic/PuiseuxSeries.jl @@ -555,8 +555,7 @@ end ############################################################################### function ==(a::PuiseuxSeriesElem{T}, b::PuiseuxSeriesElem{T}) where T <: RingElement - fl = check_parent(a, b, false) - !fl && return false + check_parent(a, b) s = gcd(a.scale, b.scale) zscale = div(a.scale*b.scale, s) ainf = div(a.scale, s) @@ -565,6 +564,7 @@ function ==(a::PuiseuxSeriesElem{T}, b::PuiseuxSeriesElem{T}) where T <: RingEle end function isequal(a::PuiseuxSeriesElem{T}, b::PuiseuxSeriesElem{T}) where T <: RingElement + parent(a) == parent(b) || return false return a.scale == b.scale && isequal(a.data, b.data) end diff --git a/src/generic/RationalFunctionField.jl b/src/generic/RationalFunctionField.jl index 8daf0b46b0..99c5e264d6 100644 --- a/src/generic/RationalFunctionField.jl +++ b/src/generic/RationalFunctionField.jl @@ -288,7 +288,7 @@ end function isequal(a::RationalFunctionFieldElem{T, U}, b::RationalFunctionFieldElem{T, U}) where {T <: FieldElement, U <: Union{PolyRingElem, MPolyRingElem}} check_parent(a, b) - return data(a) == data(b) + return isequal(data(a), data(b)) end ############################################################################### diff --git a/src/generic/TotalFraction.jl b/src/generic/TotalFraction.jl index 7087244fa3..41f899ffa5 100644 --- a/src/generic/TotalFraction.jl +++ b/src/generic/TotalFraction.jl @@ -306,8 +306,7 @@ end ############################################################################### function ==(x::TotFrac{T}, y::TotFrac{T}) where {T <: RingElem} - b = check_parent(x, y, false) - !b && return false + check_parent(x, y) return (denominator(x, false) == denominator(y, false) && numerator(x, false) == numerator(y, false)) || @@ -315,10 +314,6 @@ function ==(x::TotFrac{T}, y::TotFrac{T}) where {T <: RingElem} denominator(x, false)*numerator(y, false)) end -function isequal(x::TotFrac{T}, y::TotFrac{T}) where {T <: RingElem} - return x == y -end - ############################################################################### # # Ad hoc comparisons diff --git a/test/algorithms/GenericFunctions-test.jl b/test/algorithms/GenericFunctions-test.jl index be844b28b7..0166dc386e 100644 --- a/test/algorithms/GenericFunctions-test.jl +++ b/test/algorithms/GenericFunctions-test.jl @@ -145,19 +145,19 @@ end # Binary operations function +(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + check_parent(f, g) R = parent(f) return R(f.c + g.c) end function -(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + check_parent(f, g) R = parent(f) return R(f.c - g.c) end function *(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + check_parent(f, g) R = parent(f) return R(f.c*g.c) end @@ -165,12 +165,12 @@ end # Comparison function ==(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + check_parent(f, g) return f.c == g.c end function isequal(f::ConstPoly{T}, g::ConstPoly{T}) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + parent(f) == parent(g) || return false return isequal(f.c, g.c) end @@ -179,7 +179,7 @@ end # Exact division function divexact(f::ConstPoly{T}, g::ConstPoly{T}; check::Bool = true) where T <: RingElement - parent(f) != parent(g) && error("Incompatible rings") + check_parent(f, g) R = parent(f) return R(divexact(f.c, g.c, check = check)) end @@ -271,7 +271,7 @@ end # Euclidean interface function Base.divrem(a::ConstPoly{elem_type(ZZ)}, b::ConstPoly{elem_type(ZZ)}) - parent(a) != parent(b) && error("Incompatible rings") + check_parent(a, b) q, r = AbstractAlgebra.divrem(a.c, b.c) return parent(a)(q), parent(a)(r) end