Skip to content
This repository has been archived by the owner on Jan 30, 2023. It is now read-only.

Commit

Permalink
Implement __floordiv__ in the coercion model
Browse files Browse the repository at this point in the history
  • Loading branch information
jdemeyer committed Jan 19, 2016
1 parent adef4de commit 5e8a5e3
Show file tree
Hide file tree
Showing 12 changed files with 132 additions and 96 deletions.
12 changes: 6 additions & 6 deletions src/sage/combinat/q_analogues.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,13 +313,13 @@ def q_binomial(n, k, q=None, algorithm='auto'):
else:
num = prod(one - q**i for i in range(n-k+1, n+1))
try:
return num//denom
except TypeError:
try:
return num/denom
except (TypeError,ZeroDivisionError):
#try a substitution
return q_binomial(n,k)(q)
return num // denom
except TypeError:
return num / denom
except (TypeError, ZeroDivisionError):
# use substitution instead
return q_binomial(n,k)(q)
elif algorithm == 'cyclo_generic':
from sage.rings.polynomial.cyclotomic import cyclotomic_value
return prod(cyclotomic_value(d,q)
Expand Down
17 changes: 6 additions & 11 deletions src/sage/rings/finite_rings/integer_mod.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1653,21 +1653,16 @@ cdef class IntegerMod_abstract(FiniteRingElement):
return infinity
return r

def __floordiv__(self, other):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Exact division for prime moduli, for compatibility with other fields.
EXAMPLES:
sage: GF(7)(3) // GF(7)(5)
2
EXAMPLES::
sage: GF(7)(3) // 5
2
"""
# needs to be rewritten for coercion
if other.parent() is not self.parent():
other = self.parent().coerce(other)
if self.parent().is_field():
return self / other
else:
raise TypeError, "Floor division not defined for non-prime modulus"
return self._mul_(~right)

def _repr_(self):
return str(self.lift())
Expand Down
37 changes: 10 additions & 27 deletions src/sage/rings/integer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -1732,7 +1732,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
# we can't cimport rationals.
return the_integer_ring._div(self, right)

def __floordiv__(x, y):
cpdef RingElement _floordiv_(self, RingElement right):
r"""
Computes the whole part of `\frac{x}{y}`.
Expand Down Expand Up @@ -1769,34 +1769,17 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement):
sage: [int(a) // b for a,b in signs] == control
True
"""
cdef Integer z = <Integer>PY_NEW(Integer)
cdef long yy, res
if type(x) is type(y):
if not mpz_sgn((<Integer>y).value):
raise ZeroDivisionError, "Integer division by zero"
if mpz_size((<Integer>x).value) > 100000:
sig_on()
mpz_fdiv_q(z.value, (<Integer>x).value, (<Integer>y).value)
sig_off()
else:
mpz_fdiv_q(z.value, (<Integer>x).value, (<Integer>y).value)
return z

elif PyInt_CheckExact(y):
yy = PyInt_AS_LONG(y)
if yy > 0:
mpz_fdiv_q_ui(z.value, (<Integer>x).value, yy)
elif yy == 0:
raise ZeroDivisionError, "Integer division by zero"
else:
res = mpz_fdiv_q_ui(z.value, (<Integer>x).value, -yy)
mpz_neg(z.value, z.value)
if res:
mpz_sub_ui(z.value, z.value, 1)
return z
if not mpz_sgn((<Integer>right).value):
raise ZeroDivisionError("Integer division by zero")

cdef Integer z = <Integer>PY_NEW(Integer)
if mpz_size(self.value) > 1000:
sig_on()
mpz_fdiv_q(z.value, self.value, (<Integer>right).value)
sig_off()
else:
return bin_op(x, y, operator.floordiv)
mpz_fdiv_q(z.value, self.value, (<Integer>right).value)
return z

def __pow__(self, n, modulus):
r"""
Expand Down
2 changes: 1 addition & 1 deletion src/sage/rings/padics/padic_generic_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ cdef class pAdicGenericElement(LocalGenericElement):
sage: (a // b) * b + a % b
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^16)
The alternative definition:
The alternative definition::
sage: a
3 + 2*5^4 + 5^5 + 3*5^6 + 5^7 + O(5^20)
Expand Down
18 changes: 13 additions & 5 deletions src/sage/rings/polynomial/laurent_polynomial.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -641,19 +641,23 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial_generic):
raise ValueError("exponent must be an integer")
return LaurentPolynomial_univariate(self._parent, self.__u**right, self.__n*right)

def __floordiv__(LaurentPolynomial_univariate self, RingElement rhs):
cpdef RingElement _floordiv_(self, RingElement rhs):
"""
Perform division with remainder and return the quotient.
EXAMPLES::
sage: L.<x> = LaurentPolynomialRing(QQ)
sage: f = x**3 + x^-3
sage: f = x^3 + x^-3
sage: g = x^-1 + x
sage: f // g
x^-2 - 1 + x^2
sage: g * (f // g) == f
True
sage: f // 1
x^-3 + x^3
sage: 1 // f
0
"""
cdef LaurentPolynomial_univariate right = <LaurentPolynomial_univariate> rhs
return LaurentPolynomial_univariate(self._parent,
Expand Down Expand Up @@ -2029,23 +2033,27 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic):
ans._poly = self._poly * (<LaurentPolynomial_mpair>right)._poly
return ans

def __floordiv__(LaurentPolynomial_mpair self, RingElement right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Perform division with remainder and return the quotient.
EXAMPLES::
sage: L.<x,y> = LaurentPolynomialRing(QQ)
sage: f = x**3 + y^-3
sage: f = x^3 + y^-3
sage: g = y + x
sage: f // g
x^5*y^-3 - x^4*y^-2 + x^3*y^-1
sage: h = x + y**(-1)
sage: h = x + y^(-1)
sage: f // h
x^2 - x*y^-1 + y^-2
sage: h * (f // h) == f
True
sage: f // 1
x^3 + y^-3
sage: 1 // f
0
TESTS:
Expand Down
5 changes: 1 addition & 4 deletions src/sage/rings/polynomial/multi_polynomial_element.py
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,7 @@ def __nonzero__(self):
"""
return self._MPolynomial_element__element.dict()!={}

def __floordiv__(self,right):
def _floordiv_(self, right):
r"""
Quotient of division of self by other. This is denoted //.
Expand All @@ -1464,9 +1464,6 @@ def __floordiv__(self,right):
sage: type(0//y)
<class 'sage.rings.polynomial.multi_polynomial_element.MPolynomial_polydict'>
"""
if type(self) is not type(right) or self.parent() is not right.parent():
self, right = canonical_coercion(self, right)
return self // right # this looks like recursion, but, in fact, it may be that self, right are a totally new composite type
# handle division by monomials without using Singular
if len(right.dict()) == 1:
P = self.parent()
Expand Down
13 changes: 4 additions & 9 deletions src/sage/rings/polynomial/multi_polynomial_libsingular.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -3889,7 +3889,7 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn
else:
return False

def __floordiv__(MPolynomial_libsingular self, right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Perform division with remainder and return the quotient.
Expand Down Expand Up @@ -3935,20 +3935,15 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn
cdef poly *temp
cdef poly *p

_self = self

if not isinstance(right, MPolynomial_libsingular) \
or (parent is not (<MPolynomial_libsingular>right)._parent):
_right = parent._coerce_c(right)
else:
_right = right

if right.is_zero():
raise ZeroDivisionError

if self._parent._base.is_finite() and self._parent._base.characteristic() > 1<<29:
raise NotImplementedError, "Division of multivariate polynomials over prime fields with characteristic > 2^29 is not implemented."

_self = <MPolynomial_libsingular>self
_right = <MPolynomial_libsingular>right

if r.ringtype != 0:
if r.ringtype == 4:
P = parent.change_ring(RationalField())
Expand Down
26 changes: 16 additions & 10 deletions src/sage/rings/polynomial/polynomial_element.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ from sage.rings.complex_double import is_ComplexDoubleField, CDF
from sage.rings.real_mpfi import is_RealIntervalField

from sage.structure.element import generic_power
from sage.structure.element cimport parent_c as parent
from sage.structure.element cimport parent_c as parent, have_same_parent_c
from sage.structure.element cimport (Element, RingElement,
ModuleElement, MonoidElement, coercion_model)

Expand Down Expand Up @@ -2270,8 +2270,7 @@ cdef class Polynomial(CommutativeAlgebraElement):
"""
raise IndexError("polynomials are immutable")


def __floordiv__(self,right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Quotient of division of self by other. This is denoted //.
Expand Down Expand Up @@ -8036,18 +8035,25 @@ cdef class Polynomial_generic_dense(Polynomial):
TESTS:
Check that #13048 has been fixed::
Check that :trac:`13048` and :trac:`2034` are fixed::
sage: R.<x> = QQbar[]
sage: x//x
sage: x // x
1
sage: x//1
sage: x // 1
x
sage: x // int(1)
x
sage: x //= int(1); x
x
sage: int(1) // x # check that this doesn't segfault
Traceback (most recent call last):
...
AttributeError: type object 'int' has no attribute 'base_ring'
"""
P = (<Element>self)._parent
if right.parent() == P:
return Polynomial.__floordiv__(self, right)
if have_same_parent_c(self, right):
return (<Polynomial_generic_dense>self)._floordiv_(<Polynomial_generic_dense>right)
P = parent(self)
d = P.base_ring()(right)
cdef Polynomial_generic_dense res = (<Polynomial_generic_dense>self)._new_c([c // d for c in (<Polynomial_generic_dense>self).__coeffs], P)
res.__normalize()
Expand Down
10 changes: 2 additions & 8 deletions src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n):
sig_off()
return q, r

def __floordiv__(self, right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Returns the whole part of self/right, without remainder.
Expand All @@ -929,9 +929,6 @@ cdef class Polynomial_dense_modn_ntl_zz(Polynomial_dense_mod_n):
sage: f - q*g
x + 1
"""
if not have_same_parent_c(self, right):
self, right = canonical_coercion(self, right)
return self // right
cdef Polynomial_dense_modn_ntl_zz numer = <Polynomial_dense_modn_ntl_zz>self
cdef Polynomial_dense_modn_ntl_zz denom = <Polynomial_dense_modn_ntl_zz>right
cdef Polynomial_dense_modn_ntl_zz q = numer._new()
Expand Down Expand Up @@ -1472,7 +1469,7 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n):
sig_off()
return q, r

def __floordiv__(self, right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
Returns the whole part of self/right, without remainder.
Expand All @@ -1487,9 +1484,6 @@ cdef class Polynomial_dense_modn_ntl_ZZ(Polynomial_dense_mod_n):
sage: f - q*g
x + 1
"""
if not have_same_parent_c(self, right):
self, right = canonical_coercion(self, right)
return self // right
cdef Polynomial_dense_modn_ntl_ZZ numer = <Polynomial_dense_modn_ntl_ZZ>self
cdef Polynomial_dense_modn_ntl_ZZ denom = <Polynomial_dense_modn_ntl_ZZ>right
cdef Polynomial_dense_modn_ntl_ZZ q = numer._new()
Expand Down
7 changes: 1 addition & 6 deletions src/sage/rings/polynomial/polynomial_template.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ cdef class Polynomial_template(Polynomial):
#assert(t._parent(tp) == t)
return r,s,t

def __floordiv__(self, right):
cpdef RingElement _floordiv_(self, RingElement right):
"""
EXAMPLE::
Expand All @@ -418,11 +418,6 @@ cdef class Polynomial_template(Polynomial):
sage: (x + 1)//x
1
"""
# We can't use @coerce_binop for operators in cython classes,
# so we use sage.structure.element.bin_op to handle coercion.
if type(self) is not type(right) or \
(<Polynomial_template>self)._parent is not (<Polynomial_template>right)._parent:
return bin_op(self, right, operator.mod)
cdef Polynomial_template _right = <Polynomial_template>right

if celement_is_zero(&_right.x, (<Polynomial_template>self)._cparent):
Expand Down
1 change: 1 addition & 0 deletions src/sage/structure/element.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ cdef class AdditiveGroupElement(ModuleElement):
cdef class RingElement(ModuleElement):
cpdef RingElement _mul_(self, RingElement right)
cpdef RingElement _div_(self, RingElement right)
cpdef RingElement _floordiv_(self, RingElement right)

cdef RingElement _add_long(self, long n)

Expand Down
Loading

0 comments on commit 5e8a5e3

Please sign in to comment.