Skip to content

Commit 37a2501

Browse files
author
Release Manager
committed
gh-36645: `sage.libs.pari`, `sage.rings.real_mpfr`: Modularization fixes <!-- ^^^^^ Please provide a concise, informative and self-explanatory title. Don't put issue numbers in there, do this in the PR body below. For example, instead of "Fixes #1234" use "Introduce new method to calculate 1+1" --> <!-- Describe your changes here in detail --> Main change: Eliminate the compile-time dependency of `sage.rings.real_mpfr` on PARI. <!-- Why is this change required? What problem does it solve? --> <!-- If this PR resolves an open issue, please link to it here. For example "Fixes #12345". --> - Cherry-picked from #35095 <!-- If your change requires a documentation PR, please link it appropriately. --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> <!-- If your change requires a documentation PR, please link it appropriately --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> <!-- Feel free to remove irrelevant items. --> - [x] The title is concise, informative, and self-explanatory. - [ ] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [ ] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on - #12345: short description why this is a dependency - #34567: ... --> <!-- If you're unsure about any of these, don't hesitate to ask. We're here to help! --> URL: #36645 Reported by: Matthias Köppe Reviewer(s): Kwankyu Lee
2 parents d15e490 + 241ac56 commit 37a2501

File tree

14 files changed

+439
-317
lines changed

14 files changed

+439
-317
lines changed

src/sage/interfaces/gp.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# sage_setup: distribution = sagemath-pari
21
# sage.doctest: needs sage.libs.pari
32
r"""
43
Interface to the GP calculator of PARI/GP
@@ -142,14 +141,18 @@
142141
##########################################################################
143142
import os
144143

144+
import sage.interfaces.abc
145+
145146
from sage.env import DOT_SAGE
146-
from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement
147-
from sage.misc.verbose import verbose
148147
from sage.interfaces.tab_completion import ExtraTabCompletion
149148
from sage.libs.pari.all import pari
150-
import sage.rings.complex_mpfr
151149
from sage.misc.instancedoc import instancedoc
152-
import sage.interfaces.abc
150+
from sage.misc.lazy_import import lazy_import
151+
from sage.misc.verbose import verbose
152+
153+
lazy_import('sage.rings.cc', 'CC')
154+
155+
from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement
153156

154157

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

993996
def __len__(self):

src/sage/libs/pari/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# sage.doctest: needs sage.rings.real_mpfr
12
"""
23
Interface between Sage and PARI
34
@@ -51,6 +52,7 @@
5152
functions). For instance, if we want to use the PARI library to compute
5253
``sqrt(pi)`` with a precision of 100 bits::
5354
55+
sage: # needs sage.symbolic
5456
sage: R = RealField(100)
5557
sage: s = R(pi); s
5658
3.1415926535897932384626433833

src/sage/libs/pari/convert_gmp.pyx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ cdef Gen rational_matrix(mpq_t** B, long nr, long nc) noexcept:
172172
173173
EXAMPLES::
174174
175-
sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest
175+
sage: matrix(QQ,2,[1..6]).__pari__() # indirect doctest # needs sage.modules
176176
[1, 2, 3; 4, 5, 6]
177177
"""
178178
sig_on()

src/sage/libs/pari/convert_sage.pyx

Lines changed: 45 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -27,16 +27,30 @@ from sage.libs.pari.convert_gmp cimport INT_to_mpz, new_gen_from_mpz_t, new_gen_
2727
from sage.ext.stdsage cimport PY_NEW
2828
from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_sgn, mpz_get_ui, mpz_set, mpz_set_si, mpz_set_ui
2929
from sage.libs.gmp.mpq cimport mpq_denref, mpq_numref
30+
from sage.misc.lazy_import import LazyImport
3031
from sage.rings.integer cimport smallInteger
31-
from sage.rings.real_mpfr import RealField
32-
from sage.rings.complex_mpfr import ComplexField
33-
from sage.rings.number_field.number_field import QuadraticField
34-
from sage.matrix.args cimport (MatrixArgs, MA_ENTRIES_SEQ_SEQ,
35-
MA_ENTRIES_SEQ_FLAT, MA_ENTRIES_CALLABLE,
36-
MA_ENTRIES_UNKNOWN, MA_ENTRIES_SCALAR)
37-
from sage.rings.padics.factory import Qp
3832
from sage.rings.infinity import Infinity
3933

34+
try:
35+
from sage.rings.real_mpfr import RealField
36+
from sage.rings.complex_mpfr import ComplexField
37+
except ImportError:
38+
pass
39+
40+
try:
41+
from sage.rings.number_field.number_field import QuadraticField
42+
except ImportError:
43+
pass
44+
else:
45+
QQi = QuadraticField(-1, 'i')
46+
47+
try:
48+
from sage.rings.padics.factory import Qp
49+
except ImportError:
50+
pass
51+
52+
pari_typ_to_entries_type = LazyImport('sage.libs.pari.convert_sage_matrix', 'pari_typ_to_entries_type')
53+
4054

4155
cpdef gen_to_sage(Gen z, locals=None) noexcept:
4256
"""
@@ -117,15 +131,15 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
117131
15
118132
sage: z = pari('1.234'); z
119133
1.234000000000000000000000000000000000000000000000000000000000000000000
120-
sage: a = gen_to_sage(z); a
134+
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
121135
1.234000000000000000000000000000000000000000000000000000000000000000000000000
122-
sage: a.parent()
136+
sage: a.parent() # needs sage.rings.real_mpfr
123137
Real Field with 256 bits of precision
124138
sage: pari.set_real_precision(15)
125139
70
126-
sage: a = gen_to_sage(pari('1.234')); a
140+
sage: a = gen_to_sage(pari('1.234')); a # needs sage.rings.real_mpfr
127141
1.23400000000000000
128-
sage: a.parent()
142+
sage: a.parent() # needs sage.rings.real_mpfr
129143
Real Field with 64 bits of precision
130144
131145
For complex numbers, the parent depends on the PARI type::
@@ -134,37 +148,37 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
134148
3 + I
135149
sage: z.type()
136150
't_COMPLEX'
137-
sage: a = gen_to_sage(z); a
151+
sage: a = gen_to_sage(z); a # needs sage.rings.number_field
138152
i + 3
139-
sage: a.parent()
153+
sage: a.parent() # needs sage.rings.number_field
140154
Number Field in i with defining polynomial x^2 + 1 with i = 1*I
141155
142156
sage: z = pari('(3+I)/2'); z
143157
3/2 + 1/2*I
144-
sage: a = gen_to_sage(z); a
158+
sage: a = gen_to_sage(z); a # needs sage.rings.number_field
145159
1/2*i + 3/2
146-
sage: a.parent()
160+
sage: a.parent() # needs sage.rings.number_field
147161
Number Field in i with defining polynomial x^2 + 1 with i = 1*I
148162
149163
sage: z = pari('1.0 + 2.0*I'); z
150164
1.00000000000000 + 2.00000000000000*I
151-
sage: a = gen_to_sage(z); a
165+
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
152166
1.00000000000000000 + 2.00000000000000000*I
153-
sage: a.parent()
167+
sage: a.parent() # needs sage.rings.real_mpfr
154168
Complex Field with 64 bits of precision
155169
156170
sage: z = pari('1 + 1.0*I'); z
157171
1 + 1.00000000000000*I
158-
sage: a = gen_to_sage(z); a
172+
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
159173
1.00000000000000000 + 1.00000000000000000*I
160-
sage: a.parent()
174+
sage: a.parent() # needs sage.rings.real_mpfr
161175
Complex Field with 64 bits of precision
162176
163177
sage: z = pari('1.0 + 1*I'); z
164178
1.00000000000000 + I
165-
sage: a = gen_to_sage(z); a
179+
sage: a = gen_to_sage(z); a # needs sage.rings.real_mpfr
166180
1.00000000000000000 + 1.00000000000000000*I
167-
sage: a.parent()
181+
sage: a.parent() # needs sage.rings.real_mpfr
168182
Complex Field with 64 bits of precision
169183
170184
Converting polynomials::
@@ -179,6 +193,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
179193
sage: parent(gen_to_sage(f, {'x': x, 'y': y}))
180194
Multivariate Polynomial Ring in x, y over Rational Field
181195
196+
sage: # needs sage.symbolic
182197
sage: x,y = SR.var('x,y')
183198
sage: gen_to_sage(f, {'x': x, 'y': y})
184199
2/3*x^3 + x + y - 5/7
@@ -192,6 +207,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
192207
193208
Converting vectors::
194209
210+
sage: # needs sage.rings.number_field sage.rings.real_mpfr
195211
sage: z1 = pari('[-3, 2.1, 1+I]'); z1
196212
[-3, 2.10000000000000, 1 + I]
197213
sage: z2 = pari('[1.0*I, [1,2]]~'); z2
@@ -224,6 +240,8 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
224240
sage: z = pari('[1,2;3,4]')
225241
sage: z.type()
226242
't_MAT'
243+
244+
sage: # needs sage.modules
227245
sage: a = gen_to_sage(z); a
228246
[1 2]
229247
[3 4]
@@ -232,6 +250,7 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
232250
233251
Conversion of p-adics::
234252
253+
sage: # needs sage.rings.padics
235254
sage: z = pari('569 + O(7^8)'); z
236255
2 + 4*7 + 4*7^2 + 7^3 + O(7^8)
237256
sage: a = gen_to_sage(z); a
@@ -294,20 +313,14 @@ cpdef gen_to_sage(Gen z, locals=None) noexcept:
294313
C = ComplexField(sage_prec)
295314
return C(R(real), R(imag))
296315
else:
297-
K = QuadraticField(-1, 'i')
298-
return K([gen_to_sage(real), gen_to_sage(imag)])
316+
return QQi([gen_to_sage(real), gen_to_sage(imag)])
299317
elif t == t_VEC or t == t_COL:
300318
return [gen_to_sage(x, locals) for x in z.python_list()]
301319
elif t == t_VECSMALL:
302320
return z.python_list_small()
303321
elif t == t_MAT:
304-
nc = lg(g) - 1
305-
nr = 0 if nc == 0 else lg(gel(g,1)) - 1
306-
ma = MatrixArgs.__new__(MatrixArgs)
307-
ma.nrows = nr
308-
ma.ncols = nc
309-
ma.entries = [gen_to_sage(z[i,j], locals) for i in range(nr) for j in range(nc)]
310-
return ma.matrix()
322+
from .convert_sage_matrix import gen_to_sage_matrix
323+
return gen_to_sage_matrix(z, locals)
311324
elif t == t_PADIC:
312325
p = z.padicprime()
313326
K = Qp(Integer(p), precp(g))
@@ -330,7 +343,7 @@ cpdef set_integer_from_gen(Integer self, Gen x) noexcept:
330343
r"""
331344
EXAMPLES::
332345
333-
sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]]
346+
sage: [Integer(pari(x)) for x in [1, 2^60, 2., GF(3)(1), GF(9,'a')(2)]] # needs sage.rings.finite_rings
334347
[1, 1152921504606846976, 2, 1, 2]
335348
sage: Integer(pari(2.1)) # indirect doctest
336349
Traceback (most recent call last):
@@ -390,7 +403,7 @@ cpdef set_rational_from_gen(Rational self, Gen x) noexcept:
390403
r"""
391404
EXAMPLES::
392405
393-
sage: [Rational(pari(x)) for x in [1, 1/2, 2^60, 2., GF(3)(1), GF(9,'a')(2)]]
406+
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
394407
[1, 1/2, 1152921504606846976, 2, 1, 2]
395408
sage: Rational(pari(2.1)) # indirect doctest
396409
Traceback (most recent call last):
@@ -576,83 +589,3 @@ cpdef list pari_prime_range(long c_start, long c_stop, bint py_ints=False) noexc
576589
res.append(z)
577590
NEXT_PRIME_VIADIFF(p, pari_prime_ptr)
578591
return res
579-
580-
581-
def pari_typ_to_entries_type(MatrixArgs self):
582-
"""
583-
Determine the ``entries_type`` of a :class:`sage.matrix.args.MatrixArgs`
584-
with PARI entries.
585-
586-
This will modify the entries.
587-
588-
TESTS:
589-
590-
``MA_ENTRIES_SEQ_SEQ``::
591-
592-
sage: from sage.libs.pari.convert_sage import pari_typ_to_entries_type
593-
sage: from sage.matrix.args import MatrixArgs
594-
sage: ma = MatrixArgs(QQ, entries=pari("[1,2;3,4]"))
595-
sage: 0x10_03 == pari_typ_to_entries_type(ma)
596-
True
597-
598-
``MA_ENTRIES_SEQ_FLAT``::
599-
600-
sage: ma = MatrixArgs(QQ, entries=pari("[1,2]"))
601-
sage: 0x10_04 == pari_typ_to_entries_type(ma)
602-
True
603-
sage: ma = MatrixArgs(QQ, entries=pari(vector([1,2])))
604-
sage: 0x10_04 == pari_typ_to_entries_type(ma)
605-
True
606-
sage: ma = MatrixArgs(QQ, entries=pari(matrix(2, range(4))[0]))
607-
sage: 0x10_04 == pari_typ_to_entries_type(ma)
608-
True
609-
610-
``MA_ENTRIES_CALLABLE``::
611-
612-
sage: ma = MatrixArgs(QQ, entries=pari(lambda x: x))
613-
sage: 0x13_06 == pari_typ_to_entries_type(ma)
614-
True
615-
616-
``MA_ENTRIES_SCALAR``::
617-
618-
sage: ma = MatrixArgs(QQ, entries=pari(1/2))
619-
sage: 0x17_02 == pari_typ_to_entries_type(ma)
620-
True
621-
622-
``MA_ENTRIES_UNKNOWN``::
623-
624-
sage: ma = MatrixArgs(QQ, entries=pari('"2"'))
625-
sage: 0 == pari_typ_to_entries_type(ma)
626-
True
627-
628-
A second call gives an error::
629-
630-
sage: ma = MatrixArgs(QQ, entries=pari("[1,2]"))
631-
sage: 0x10_04 == pari_typ_to_entries_type(ma)
632-
True
633-
sage: 0x10_04 == pari_typ_to_entries_type(ma)
634-
Traceback (most recent call last):
635-
...
636-
ValueError: entries are not a PARI generator
637-
"""
638-
if not isinstance(self.entries, Gen):
639-
raise ValueError("entries are not a PARI generator")
640-
cdef long t = typ((<Gen>self.entries).g)
641-
if t == t_MAT:
642-
R = self.base
643-
if R is None:
644-
self.entries = self.entries.Col().sage()
645-
else:
646-
self.entries = [[R(x) for x in v]
647-
for v in self.entries.mattranspose()]
648-
return MA_ENTRIES_SEQ_SEQ
649-
elif t in [t_VEC, t_COL, t_VECSMALL, t_LIST]:
650-
self.entries = self.entries.sage()
651-
return MA_ENTRIES_SEQ_FLAT
652-
elif t == t_CLOSURE:
653-
return MA_ENTRIES_CALLABLE
654-
elif t == t_STR:
655-
return MA_ENTRIES_UNKNOWN
656-
else:
657-
self.entries = self.entries.sage()
658-
return MA_ENTRIES_SCALAR

src/sage/libs/pari/convert_sage_complex_double.pyx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
# sage.doctest: needs sage.rings.complex_double
2+
13
from cysignals.signals cimport sig_on, sig_off
24

35
from sage.libs.gsl.complex cimport *
@@ -25,7 +27,7 @@ cpdef ComplexDoubleElement pari_to_cdf(Gen g) noexcept:
2527
Traceback (most recent call last):
2628
...
2729
PariError: overflow in t_REAL->double conversion
28-
sage: CDF(pari(x^2 + 5))
30+
sage: CDF(pari(x^2 + 5)) # needs sage.symbolic
2931
Traceback (most recent call last):
3032
...
3133
PariError: incorrect type in gtofp (t_POL)

0 commit comments

Comments
 (0)