diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index abee1fb141c..a5c8b3c56b4 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -31,7 +31,9 @@ from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_sgn, mpz_get_ui, mpz_set, m from sage.libs.gmp.mpq cimport mpq_denref, mpq_numref from sage.rings.integer cimport smallInteger from sage.rings.all import RealField, ComplexField, QuadraticField -from sage.matrix.args cimport MatrixArgs +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 @@ -574,3 +576,83 @@ cpdef list pari_prime_range(long c_start, long c_stop, bint py_ints=False): 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((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 diff --git a/src/sage/matrix/args.pyx b/src/sage/matrix/args.pyx index 112b2663e24..4d2a114328e 100644 --- a/src/sage/matrix/args.pyx +++ b/src/sage/matrix/args.pyx @@ -17,8 +17,6 @@ Helpers for creating matrices cimport cython from cpython.sequence cimport PySequence_Fast from cysignals.signals cimport sig_check -from cypari2.gen cimport Gen -from cypari2.types cimport typ, t_MAT, t_VEC, t_COL, t_VECSMALL, t_LIST, t_STR, t_CLOSURE MatrixSpace = None @@ -33,6 +31,12 @@ from sage.misc.misc_c import sized_iter from sage.categories import monoids +try: + from cypari2.gen import Gen +except ImportError: + Gen = () + + CommutativeMonoids = monoids.Monoids().Commutative() @@ -1250,25 +1254,8 @@ cdef class MatrixArgs: return MA_ENTRIES_NDARRAY return MA_ENTRIES_SCALAR if isinstance(self.entries, Gen): # PARI object - t = typ((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 + from sage.libs.pari.convert_sage import pari_typ_to_entries_type + return pari_typ_to_entries_type(self) if isinstance(self.entries, MatrixArgs): # Prevent recursion return MA_ENTRIES_UNKNOWN