Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

sage.libs.pari, sage.rings.real_mpfr: Modularization fixes #36645

Merged
merged 15 commits into from
Dec 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions src/sage/interfaces/gp.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
# sage_setup: distribution = sagemath-pari
# sage.doctest: needs sage.libs.pari
r"""
Interface to the GP calculator of PARI/GP
Expand Down Expand Up @@ -142,14 +141,18 @@
##########################################################################
import os

import sage.interfaces.abc

from sage.env import DOT_SAGE
from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement
from sage.misc.verbose import verbose
from sage.interfaces.tab_completion import ExtraTabCompletion
from sage.libs.pari.all import pari
import sage.rings.complex_mpfr
from sage.misc.instancedoc import instancedoc
import sage.interfaces.abc
from sage.misc.lazy_import import lazy_import
from sage.misc.verbose import verbose

lazy_import('sage.rings.cc', 'CC')

from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement


class Gp(ExtraTabCompletion, Expect):
Expand Down Expand Up @@ -987,7 +990,7 @@ def _complex_double_(self, CDF):
"""
# Retrieving values from another computer algebra system is
# slow anyway, right?
cc_val = self._complex_mpfr_field_(sage.rings.complex_mpfr.ComplexField())
cc_val = self._complex_mpfr_field_(CC)
return CDF(cc_val)

def __len__(self):
Expand Down
2 changes: 2 additions & 0 deletions src/sage/libs/pari/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# sage.doctest: needs sage.rings.real_mpfr
"""
Interface between Sage and PARI

Expand Down Expand Up @@ -51,6 +52,7 @@
functions). For instance, if we want to use the PARI library to compute
``sqrt(pi)`` with a precision of 100 bits::

sage: # needs sage.symbolic
sage: R = RealField(100)
sage: s = R(pi); s
3.1415926535897932384626433833
Expand Down
2 changes: 1 addition & 1 deletion src/sage/libs/pari/convert_gmp.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ cdef Gen rational_matrix(mpq_t** B, long nr, long nc) noexcept:

EXAMPLES::

sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest
sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest # needs sage.modules
[1, 2, 3; 4, 5, 6]
"""
sig_on()
Expand Down
157 changes: 45 additions & 112 deletions src/sage/libs/pari/convert_sage.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,30 @@ from sage.libs.pari.convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t, new_gen_
from sage.ext.stdsage cimport PY_NEW
from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_sgn, mpz_get_ui, mpz_set, mpz_set_si, mpz_set_ui
from sage.libs.gmp.mpq cimport mpq_denref, mpq_numref
from sage.misc.lazy_import import LazyImport
from sage.rings.integer cimport smallInteger
from sage.rings.real_mpfr import RealField
from sage.rings.complex_mpfr import ComplexField
from sage.rings.number_field.number_field import QuadraticField
from sage.matrix.args cimport (MatrixArgs, MA_ENTRIES_SEQ_SEQ,
MA_ENTRIES_SEQ_FLAT, MA_ENTRIES_CALLABLE,
MA_ENTRIES_UNKNOWN, MA_ENTRIES_SCALAR)
from sage.rings.padics.factory import Qp
from sage.rings.infinity import Infinity

try:
from sage.rings.real_mpfr import RealField
from sage.rings.complex_mpfr import ComplexField
except ImportError:
pass

try:
from sage.rings.number_field.number_field import QuadraticField
except ImportError:
pass
else:
QQi = QuadraticField(-1, 'i')

try:
from sage.rings.padics.factory import Qp
except ImportError:
pass

pari_typ_to_entries_type = LazyImport('sage.libs.pari.convert_sage_matrix', 'pari_typ_to_entries_type')


cpdef gen_to_sage(Gen z, locals=None) noexcept:
"""
Expand Down Expand Up @@ -117,15 +131,15 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
15
sage: z = pari('1.234'); z
1.234000000000000000000000000000000000000000000000000000000000000000000
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
1.234000000000000000000000000000000000000000000000000000000000000000000000000
sage: a.parent()
sage: a.parent() # needs sage.rings.real_mpfr
Real Field with 256 bits of precision
sage: pari.set_real_precision(15)
70
sage: a = gen_to_sage(pari('1.234')); a
sage: a = gen_to_sage(pari('1.234')); a # needs sage.rings.real_mpfr
1.23400000000000000
sage: a.parent()
sage: a.parent() # needs sage.rings.real_mpfr
Real Field with 64 bits of precision

For complex numbers, the parent depends on the PARI type::
Expand All @@ -134,37 +148,37 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
3 + I
sage: z.type()
't_COMPLEX'
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.number_field
i + 3
sage: a.parent()
sage: a.parent() # needs sage.rings.number_field
Number Field in i with defining polynomial x^2 + 1 with i = 1*I

sage: z = pari('(3+I)/2'); z
3/2 + 1/2*I
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.number_field
1/2*i + 3/2
sage: a.parent()
sage: a.parent() # needs sage.rings.number_field
Number Field in i with defining polynomial x^2 + 1 with i = 1*I

sage: z = pari('1.0 + 2.0*I'); z
1.00000000000000 + 2.00000000000000*I
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
1.00000000000000000 + 2.00000000000000000*I
sage: a.parent()
sage: a.parent() # needs sage.rings.real_mpfr
Complex Field with 64 bits of precision

sage: z = pari('1 + 1.0*I'); z
1 + 1.00000000000000*I
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
1.00000000000000000 + 1.00000000000000000*I
sage: a.parent()
sage: a.parent() # needs sage.rings.real_mpfr
Complex Field with 64 bits of precision

sage: z = pari('1.0 + 1*I'); z
1.00000000000000 + I
sage: a = gen_to_sage(z); a
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
1.00000000000000000 + 1.00000000000000000*I
sage: a.parent()
sage: a.parent() # needs sage.rings.real_mpfr
Complex Field with 64 bits of precision

Converting polynomials::
Expand All @@ -179,6 +193,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
sage: parent(gen_to_sage(f, {'x': x, 'y': y}))
Multivariate Polynomial Ring in x, y over Rational Field

sage: # needs sage.symbolic
sage: x,y = SR.var('x,y')
sage: gen_to_sage(f, {'x': x, 'y': y})
2/3*x^3 + x + y - 5/7
Expand All @@ -192,6 +207,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:

Converting vectors::

sage: # needs sage.rings.number_field sage.rings.real_mpfr
sage: z1 = pari('[-3, 2.1, 1+I]'); z1
[-3, 2.10000000000000, 1 + I]
sage: z2 = pari('[1.0*I, [1,2]]~'); z2
Expand Down Expand Up @@ -224,6 +240,8 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
sage: z = pari('[1,2;3,4]')
sage: z.type()
't_MAT'

sage: # needs sage.modules
sage: a = gen_to_sage(z); a
[1 2]
[3 4]
Expand All @@ -232,6 +250,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:

Conversion of p-adics::

sage: # needs sage.rings.padics
sage: z = pari('569 + O(7^8)'); z
2 + 4*7 + 4*7^2 + 7^3 + O(7^8)
sage: a = gen_to_sage(z); a
Expand Down Expand Up @@ -294,20 +313,14 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
C = ComplexField(sage_prec)
return C(R(real), R(imag))
else:
K = QuadraticField(-1, 'i')
return K([gen_to_sage(real), gen_to_sage(imag)])
return QQi([gen_to_sage(real), gen_to_sage(imag)])
elif t == t_VEC or t == t_COL:
return [gen_to_sage(x, locals) for x in z.python_list()]
elif t == t_VECSMALL:
return z.python_list_small()
elif t == t_MAT:
nc = lg(g) - 1
nr = 0 if nc == 0 else lg(gel(g,1)) - 1
ma = MatrixArgs.__new__(MatrixArgs)
ma.nrows = nr
ma.ncols = nc
ma.entries = [gen_to_sage(z[i,j], locals) for i in range(nr) for j in range(nc)]
return ma.matrix()
from .convert_sage_matrix import gen_to_sage_matrix
return gen_to_sage_matrix(z, locals)
elif t == t_PADIC:
p = z.padicprime()
K = Qp(Integer(p), precp(g))
Expand All @@ -330,7 +343,7 @@ cpdef set_integer_from_gen(Integer self, Gen x) noexcept:
r"""
EXAMPLES::

sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]]
sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] # needs sage.rings.finite_rings
[1, 1152921504606846976, 2, 1, 2]
sage: Integer(pari(2.1)) # indirect doctest
Traceback (most recent call last):
Expand Down Expand Up @@ -390,7 +403,7 @@ cpdef set_rational_from_gen(Rational self, Gen x) noexcept:
r"""
EXAMPLES::

sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2)]]
sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] # needs sage.rings.finite_rings
[1, 1/2, 1152921504606846976, 2, 1, 2]
sage: Rational(pari(2.1)) # indirect doctest
Traceback (most recent call last):
Expand Down Expand Up @@ -576,83 +589,3 @@ cpdef list pari_prime_range(long c_start, long c_stop, bint py_ints=False) noexc
res.append(z)
NEXT_PRIME_VIADIFF(p, pari_prime_ptr)
return res


def pari_typ_to_entries_type(MatrixArgs self):
"""
Determine the ``entries_type`` of a :class:`sage.matrix.args.MatrixArgs`
with PARI entries.

This will modify the entries.

TESTS:

``MA_ENTRIES_SEQ_SEQ``::

sage: from sage.libs.pari.convert_sage import pari_typ_to_entries_type
sage: from sage.matrix.args import MatrixArgs
sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]"))
sage: 0x10_03 == pari_typ_to_entries_type(ma)
True

``MA_ENTRIES_SEQ_FLAT``::

sage: ma = MatrixArgs(QQ, entries=pari("[1,2]"))
sage: 0x10_04 == pari_typ_to_entries_type(ma)
True
sage: ma = MatrixArgs(QQ, entries=pari(vector([1,2])))
sage: 0x10_04 == pari_typ_to_entries_type(ma)
True
sage: ma = MatrixArgs(QQ, entries=pari(matrix(2, range(4))[0]))
sage: 0x10_04 == pari_typ_to_entries_type(ma)
True

``MA_ENTRIES_CALLABLE``::

sage: ma = MatrixArgs(QQ, entries=pari(lambda x: x))
sage: 0x13_06 == pari_typ_to_entries_type(ma)
True

``MA_ENTRIES_SCALAR``::

sage: ma = MatrixArgs(QQ, entries=pari(1/2))
sage: 0x17_02 == pari_typ_to_entries_type(ma)
True

``MA_ENTRIES_UNKNOWN``::

sage: ma = MatrixArgs(QQ, entries=pari('"2"'))
sage: 0 == pari_typ_to_entries_type(ma)
True

A second call gives an error::

sage: ma = MatrixArgs(QQ, entries=pari("[1,2]"))
sage: 0x10_04 == pari_typ_to_entries_type(ma)
True
sage: 0x10_04 == pari_typ_to_entries_type(ma)
Traceback (most recent call last):
...
ValueError: entries are not a PARI generator
"""
if not isinstance(self.entries, Gen):
raise ValueError("entries are not a PARI generator")
cdef long t = typ((<Gen>self.entries).g)
if t == t_MAT:
R = self.base
if R is None:
self.entries = self.entries.Col().sage()
else:
self.entries = [[R(x) for x in v]
for v in self.entries.mattranspose()]
return MA_ENTRIES_SEQ_SEQ
elif t in [t_VEC, t_COL, t_VECSMALL, t_LIST]:
self.entries = self.entries.sage()
return MA_ENTRIES_SEQ_FLAT
elif t == t_CLOSURE:
return MA_ENTRIES_CALLABLE
elif t == t_STR:
return MA_ENTRIES_UNKNOWN
else:
self.entries = self.entries.sage()
return MA_ENTRIES_SCALAR
4 changes: 3 additions & 1 deletion src/sage/libs/pari/convert_sage_complex_double.pyx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# sage.doctest: needs sage.rings.complex_double

from cysignals.signals cimport sig_on, sig_off

from sage.libs.gsl.complex cimport *
Expand Down Expand Up @@ -25,7 +27,7 @@ cpdef ComplexDoubleElement pari_to_cdf(Gen g) noexcept:
Traceback (most recent call last):
...
PariError: overflow in t_REAL->double conversion
sage: CDF(pari(x^2 + 5))
sage: CDF(pari(x^2 + 5)) # needs sage.symbolic
Traceback (most recent call last):
...
PariError: incorrect type in gtofp (t_POL)
Expand Down
Loading
Loading