Skip to content

Commit

Permalink
sagemathgh-38717: NotImplementedError when pow() called with modulus
Browse files Browse the repository at this point in the history
    
<!-- ^ Please provide a concise and informative title. -->
<!-- ^ Don't put issue numbers in the title, do this in the PR
description below. -->
<!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method
to calculate 1 + 2". -->
<!-- v Describe your changes below in detail. -->
<!-- v Why is this change required? What problem does it solve? -->
<!-- v If this PR resolves an open issue, please link to it here. For
example, "Fixes sagemath#12345". -->

Many polynomial types silently ignore the modulus (third) argument of
`pow()`.  For example,
```python
sage: R.<x> = PolynomialRing(ZZ)
sage: pow(x, 2, x)
x^2
```
This is true of `LaurentPolynomial`, `LaurentPolynomial_mpair`,
`MPolynomial_libsingular`, `Polynomial_integer_dense_flint`,
`Polynomial_rational_flint`, and `NCPolynomial_plural`.  Ideally these
classes would implement this argument, but at the very least they should
raise `NotImplementedError` instead of giving an incorrect result.
    
URL: sagemath#38717
Reported by: Kyle Hofmann
Reviewer(s): Vincent Macri
  • Loading branch information
Release Manager committed Oct 5, 2024
2 parents ee1154a + 188f93f commit 6c5c30f
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 6 deletions.
14 changes: 13 additions & 1 deletion src/sage/rings/polynomial/laurent_polynomial.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1126,7 +1126,7 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial):
"""
return self.__u.is_monomial()

def __pow__(_self, r, dummy):
def __pow__(_self, r, mod):
"""
EXAMPLES::
Expand All @@ -1145,9 +1145,21 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial):
x^-8
sage: (5*x^-4)^-3
5*x^12
Check that using third argument raises an error::
sage: L.<x> = LaurentPolynomialRing(R)
sage: pow(x, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
cdef LaurentPolynomial_univariate self = _self
cdef long right = r
if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)
if right != r:
raise ValueError("exponent must be an integer")
try:
Expand Down
14 changes: 13 additions & 1 deletion src/sage/rings/polynomial/laurent_polynomial_mpair.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial):
return P({e: c})
return super().__invert__()

def __pow__(LaurentPolynomial_mpair self, n, m):
def __pow__(LaurentPolynomial_mpair self, n, mod):
"""
EXAMPLES::
Expand All @@ -480,8 +480,20 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial):
sage: f = (x+y+z^-1)^2
sage: f.substitute(z=1)
x^2 + 2*x*y + y^2 + 2*x + 2*y + 1
Check that using third argument raises an error::
sage: L.<x,y,z> = LaurentPolynomialRing(R)
sage: pow(x + y + z, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
cdef LaurentPolynomial_mpair ans
if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)
if n < 0:
return ~(self ** -n)
ans = self._new_c()
Expand Down
15 changes: 14 additions & 1 deletion src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2350,7 +2350,7 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
else:
return (left._parent).fraction_field()(left,right_ringelement)

def __pow__(MPolynomial_libsingular self, exp, ignored):
def __pow__(MPolynomial_libsingular self, exp, mod):
"""
Return ``self**(exp)``.
Expand Down Expand Up @@ -2413,7 +2413,20 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base):
Traceback (most recent call last):
...
TypeError: R is neither an integer nor a rational
Check that using third argument raises an error::
sage: R.<x,y,z> = PolynomialRing(ZZ)
sage: pow(x + y + z, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)

if type(exp) is not Integer:
try:
exp = Integer(exp)
Expand Down
17 changes: 16 additions & 1 deletion src/sage/rings/polynomial/plural.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1671,7 +1671,7 @@ cdef class NCPolynomial_plural(RingElement):
else:
return (<NCPolynomialRing_plural>left._parent).fraction_field()(left,right)

def __pow__(NCPolynomial_plural self, exp, ignored):
def __pow__(NCPolynomial_plural self, exp, mod):
"""
Return ``self**(exp)``.
Expand All @@ -1697,7 +1697,22 @@ cdef class NCPolynomial_plural(RingElement):
Traceback (most recent call last):
....
OverflowError: exponent overflow (2147483648)
Check that using third argument raises an error::
sage: A.<x,z,y> = FreeAlgebra(QQ, 3)
sage: P = A.g_algebra(relations={y*x:-x*y + z}, order='lex')
sage: P.inject_variables()
Defining x, z, y
sage: pow(x + y + z, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)
if type(exp) is not Integer:
try:
exp = Integer(exp)
Expand Down
15 changes: 14 additions & 1 deletion src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1035,7 +1035,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial):
sig_off()
return x

def __pow__(Polynomial_integer_dense_flint self, exp, ignored):
def __pow__(Polynomial_integer_dense_flint self, exp, mod):
"""
EXAMPLES::
Expand Down Expand Up @@ -1114,10 +1114,23 @@ cdef class Polynomial_integer_dense_flint(Polynomial):
...
TypeError: no canonical coercion from Univariate Polynomial
Ring in R over Integer Ring to Rational Field
Check that using third argument raises an error::
sage: R.<x> = PolynomialRing(ZZ, implementation='FLINT')
sage: pow(x, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
cdef long nn
cdef Polynomial_integer_dense_flint res

if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)

try:
nn = pyobject_to_long(exp)
except TypeError:
Expand Down
15 changes: 14 additions & 1 deletion src/sage/rings/polynomial/polynomial_rational_flint.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1160,7 +1160,7 @@ cdef class Polynomial_rational_flint(Polynomial):
if do_sig: sig_off()
return res

def __pow__(Polynomial_rational_flint self, exp, ignored):
def __pow__(Polynomial_rational_flint self, exp, mod):
"""
Return ``self`` raised to the power of ``exp``.
Expand Down Expand Up @@ -1266,10 +1266,23 @@ cdef class Polynomial_rational_flint(Polynomial):
...
TypeError: no canonical coercion from Univariate Polynomial
Ring in R over Rational Field to Rational Field
Check that using third argument raises an error::
sage: R.<x> = PolynomialRing(QQ)
sage: pow(x, 2, x)
Traceback (most recent call last):
...
NotImplementedError: pow() with a modulus is not implemented for this ring
"""
cdef Polynomial_rational_flint res
cdef long n

if mod is not None:
raise NotImplementedError(
"pow() with a modulus is not implemented for this ring"
)

try:
n = pyobject_to_long(exp)
except TypeError:
Expand Down

0 comments on commit 6c5c30f

Please sign in to comment.