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

Commit

Permalink
sage.libs.pari.convert_sage: Move set_integer_from_gen here from sage…
Browse files Browse the repository at this point in the history
….rings.integer (set_from_pari_gen)
  • Loading branch information
Matthias Koeppe committed Aug 28, 2021
1 parent 488ced5 commit 08084b3
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 52 deletions.
3 changes: 3 additions & 0 deletions src/sage/libs/pari/convert_sage.pxd
Original file line number Diff line number Diff line change
@@ -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)
55 changes: 54 additions & 1 deletion src/sage/libs/pari/convert_sage.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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((<Gen>x).g) != t_INT:
x = x.simplify()
paritype = typ((<Gen>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((<Gen>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, (<Gen>x).g)
61 changes: 10 additions & 51 deletions src/sage/rings/integer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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((<pari_gen>x).g) != t_INT:
x = x.simplify()
paritype = typ((<pari_gen>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((<pari_gen>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, (<pari_gen>x).g)


cdef _digits_naive(mpz_t v,l,int offset,Integer base,digits):
"""
Expand Down Expand Up @@ -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:

Expand Down

0 comments on commit 08084b3

Please sign in to comment.