diff --git a/src/sage/libs/pari/convert_sage.pxd b/src/sage/libs/pari/convert_sage.pxd index fe77d8b675c..466c8a7da3f 100644 --- a/src/sage/libs/pari/convert_sage.pxd +++ b/src/sage/libs/pari/convert_sage.pxd @@ -1,3 +1,6 @@ from cypari2.gen cimport Gen +from sage.rings.integer cimport Integer cpdef gen_to_sage(Gen z, locals=*) + +cpdef set_integer_from_gen(Integer self, Gen x) diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index 32d6902bc90..8891c69d9ab 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -14,12 +14,17 @@ Convert PARI objects to Sage types # http://www.gnu.org/licenses/ #***************************************************************************** +from cysignals.signals cimport sig_on + from cypari2.types cimport (GEN, typ, t_INT, t_FRAC, t_REAL, t_COMPLEX, t_INTMOD, t_PADIC, t_INFINITY, t_VEC, t_COL, t_VECSMALL, t_MAT, t_STR, lg, precp) from cypari2.pari_instance cimport prec_words_to_bits -from cypari2.paridecl cimport gel, inf_get_sign +from cypari2.paridecl cimport * +from cypari2.gen cimport objtogen +from cypari2.stack cimport new_gen +from .convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational @@ -315,3 +320,51 @@ cpdef gen_to_sage(Gen z, locals=None): from sage.misc.sage_eval import sage_eval locals = {} if locals is None else locals return sage_eval(str(z), locals=locals) + + +cpdef set_integer_from_gen(Integer self, Gen x): + r""" + EXAMPLES:: + + sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] + [1, 1152921504606846976, 2, 1, 2] + sage: Integer(pari(2.1)) # indirect doctest + Traceback (most recent call last): + ... + TypeError: Attempt to coerce non-integral real number to an Integer + """ + # Simplify and lift until we get an integer + while typ((x).g) != t_INT: + x = x.simplify() + paritype = typ((x).g) + if paritype == t_INT: + break + elif paritype == t_REAL: + # Check that the fractional part is zero + if not x.frac().gequal0(): + raise TypeError("Attempt to coerce non-integral real number to an Integer") + # floor yields an integer + x = x.floor() + break + elif paritype == t_PADIC: + if x._valp() < 0: + raise TypeError("Cannot convert p-adic with negative valuation to an integer") + # Lifting a PADIC yields an integer + x = x.lift() + break + elif paritype == t_INTMOD: + # Lifting an INTMOD yields an integer + x = x.lift() + break + elif paritype == t_POLMOD: + x = x.lift() + elif paritype == t_FFELT: + # x = (f modulo defining polynomial of finite field); + # we extract f. + sig_on() + x = new_gen(FF_to_FpXQ_i((x).g)) + else: + raise TypeError("Unable to coerce PARI %s to an Integer"%x) + + # Now we have a true PARI integer, convert it to Sage + INT_to_mpz(self.value, (x).g) diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 14eec0c8c3b..1c09eff559a 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -180,9 +180,8 @@ from sage.libs.gmp.pylong cimport * from sage.libs.gmp.mpq cimport mpq_neg from sage.libs.gmp.binop cimport mpq_add_z, mpq_mul_z, mpq_div_zz -from cypari2.gen cimport objtogen, Gen as pari_gen -from sage.libs.pari.convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t -from cypari2.stack cimport new_gen +from cypari2.gen cimport objtogen +from sage.libs.pari.convert_gmp cimport new_gen_from_mpz_t from sage.libs.flint.ulong_extras cimport * import sage.rings.infinity @@ -198,6 +197,12 @@ cimport gmpy2 gmpy2.import_gmpy2() +try: + from cypari2.gen import Gen as pari_gen +except ImportError: + pari_gen = () + + cdef extern from *: int unlikely(int) nogil # Defined by Cython @@ -208,53 +213,6 @@ cdef object numpy_object_interface = {'typestr': '|O'} cdef set_from_Integer(Integer self, Integer other): mpz_set(self.value, other.value) -cdef set_from_pari_gen(Integer self, pari_gen x): - r""" - EXAMPLES:: - - sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] - [1, 1152921504606846976, 2, 1, 2] - sage: Integer(pari(2.1)) # indirect doctest - Traceback (most recent call last): - ... - TypeError: Attempt to coerce non-integral real number to an Integer - """ - # Simplify and lift until we get an integer - while typ((x).g) != t_INT: - x = x.simplify() - paritype = typ((x).g) - if paritype == t_INT: - break - elif paritype == t_REAL: - # Check that the fractional part is zero - if not x.frac().gequal0(): - raise TypeError("Attempt to coerce non-integral real number to an Integer") - # floor yields an integer - x = x.floor() - break - elif paritype == t_PADIC: - if x._valp() < 0: - raise TypeError("Cannot convert p-adic with negative valuation to an integer") - # Lifting a PADIC yields an integer - x = x.lift() - break - elif paritype == t_INTMOD: - # Lifting an INTMOD yields an integer - x = x.lift() - break - elif paritype == t_POLMOD: - x = x.lift() - elif paritype == t_FFELT: - # x = (f modulo defining polynomial of finite field); - # we extract f. - sig_on() - x = new_gen(FF_to_FpXQ_i((x).g)) - else: - raise TypeError("Unable to coerce PARI %s to an Integer"%x) - - # Now we have a true PARI integer, convert it to Sage - INT_to_mpz(self.value, (x).g) - cdef _digits_naive(mpz_t v,l,int offset,Integer base,digits): """ @@ -684,7 +642,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): raise TypeError("Cannot convert non-integral float to integer") elif isinstance(x, pari_gen): - set_from_pari_gen(self, x) + from sage.libs.pari.convert_sage import set_integer_from_gen + set_integer_from_gen(self, x) else: