@@ -425,16 +425,22 @@ end
425425
426426iszero (x:: MPolyRingElem{T} ) where T <: RingElement = length (x) == 0
427427
428- function is_unit (a:: MPolyRingElem{T} ) where T <: RingElement
429- if is_constant (a)
430- return is_unit (leading_coefficient (a))
431- elseif is_domain_type (elem_type (coefficient_ring (a)))
432- return false
433- elseif length (a) == 1
434- return false
435- else
436- throw (NotImplementedError (:is_unit , a))
437- end
428+ function is_unit (f:: T ) where {T <: MPolyRingElem }
429+ # for constant polynomials we delegate to the coefficient ring:
430+ is_constant (f) && return is_unit (constant_coefficient (f))
431+ # Here deg(f) > 0; over an integral domain, non-constant polynomials are never units:
432+ is_domain_type (T) && return false
433+ # A polynomial over a commutative ring is a unit iff its
434+ # constant term is a unit and all other coefficients are nilpotent:
435+ # see e.g. <https://kconrad.math.uconn.edu/blurbs/ringtheory/polynomial-properties.pdf> for a proof.
436+ for (c, expv) in zip (coefficients (f), exponent_vectors (f))
437+ if is_zero (expv)
438+ is_unit (c) || return false
439+ else
440+ is_nilpotent (c) || return false
441+ end
442+ end
443+ return true
438444end
439445
440446function content (a:: MPolyRingElem{T} ) where T <: RingElement
@@ -445,8 +451,16 @@ function content(a::MPolyRingElem{T}) where T <: RingElement
445451 return z
446452end
447453
454+
455+ function is_nilpotent (f:: T ) where {T <: MPolyRingElem }
456+ is_domain_type (T) && return is_zero (f)
457+ return all (is_nilpotent, coefficients (f))
458+ end
459+
460+
448461function is_zero_divisor (x:: MPolyRingElem{T} ) where T <: RingElement
449- return is_zero_divisor (content (x))
462+ is_domain_type (T) && return is_zero (x)
463+ return is_zero_divisor (content (x))
450464end
451465
452466function is_zero_divisor_with_annihilator (a:: MPolyRingElem{T} ) where T <: RingElement
0 commit comments