Ticket #864: trac_864-pari_long_conversion.patch

File trac_864-pari_long_conversion.patch, 3.9 KB (added by pbruin, 8 years ago)
  • sage/libs/pari/gen.pyx

    # HG changeset patch
    # User Peter Bruin <P.Bruin@warwick.ac.uk>
    # Date 1378750492 -3600
    # Node ID ca70c9ef183ffca18c0f7ba56e70f98738e4f5ab
    # Parent  ce63d87766b71f37321b71f7f126f5f72b8ca3f4
    Trac 864: speed up conversion from PARI to Python long
    
    diff --git a/sage/libs/pari/gen.pyx b/sage/libs/pari/gen.pyx
    a b  
    181181include 'sage/ext/python.pxi'
    182182
    183183cdef extern from "mpz_pylong.h":
     184    cdef object mpz_get_pylong(mpz_t z)
    184185    cdef int mpz_set_pylong(mpz_t dst, src) except -1
    185186
     187cdef extern from 'convert.h':
     188    cdef void t_INT_to_ZZ(mpz_t value, GEN g)
     189
    186190# Make sure we don't use mpz_t_offset before initializing it by
    187191# putting in a value that's likely to provoke a segmentation fault,
    188192# rather than silently corrupting memory.
     
    15961600       
    15971601    def __int__(gen self):
    15981602        """
    1599         Return Python int. Very fast, and if the number is too large to fit
    1600         into a C int, a Python long is returned instead.
     1603        Convert ``self`` to a Python integer.
     1604
     1605        If the number is too large to fit into a Pyhon ``int``, a
     1606        Python ``long`` is returned instead.
    16011607       
    16021608        EXAMPLES::
    16031609       
     
    16181624            sage: int(pari("Pol(10)"))
    16191625            10
    16201626        """
    1621         cdef GEN x
    1622         cdef long lx, *xp
    1623         if  typ(self.g)==t_POL and self.poldegree()<=0:
    1624             # Change a constant polynomial to its constant term
    1625             x = constant_term(self.g)
    1626         else:
    1627             x = self.g
    1628         if typ(x) != t_INT:
    1629             raise TypeError, "gen must be of PARI type t_INT or t_POL of degree 0"
    1630         if not signe(x):
    1631             return 0
    1632         lx = lgefint(x)-3   # take 1 to account for the MSW
    1633         xp = int_MSW(x)
    1634         # special case 1 word so we return int if it fits
    1635         if not lx:
    1636             if   signe(x) |  xp[0] > 0:     # both positive
    1637                 return xp[0]
    1638             elif signe(x) & -xp[0] < 0:     # both negative
    1639                 return -xp[0]
    1640         i = <ulong>xp[0]
    1641         while lx:
    1642             xp = int_precW(xp)
    1643             i = i << BITS_IN_LONG | <ulong>xp[0]
    1644             lx = lx-1
    1645         if signe(x) > 0:
    1646             return i
    1647         else:
    1648             return -i
    1649         # NOTE: Could use int_unsafe below, which would be much faster, but
    1650         # the default PARI prints annoying stuff to the screen when
    1651         # the number is large.
     1627        return int(long(self))
    16521628
    16531629    def int_unsafe(gen self):
    16541630        """
     
    18201796   
    18211797    def __long__(gen self):
    18221798        """
    1823         Return Python long.
    1824         """
    1825         return long(int(self))
     1799        Convert ``self`` to a Python ``long``.
     1800
     1801        EXAMPLES::
     1802
     1803            sage: long(pari(0))
     1804            0L
     1805            sage: long(pari(10))
     1806            10L
     1807            sage: long(pari(-10))
     1808            -10L
     1809            sage: long(pari(123456789012345678901234567890))
     1810            123456789012345678901234567890L
     1811            sage: long(pari(-123456789012345678901234567890))
     1812            -123456789012345678901234567890L
     1813            sage: long(pari(2^31-1))
     1814            2147483647L
     1815            sage: long(pari(-2^31))
     1816            -2147483648L
     1817            sage: long(pari("Pol(10)"))
     1818            10L
     1819        """
     1820        cdef GEN x
     1821        cdef mpz_t x_mpz
     1822        if typ(self.g) == t_POL and self.poldegree() <= 0:
     1823            # Change a constant polynomial to its constant term
     1824            x = constant_term(self.g)
     1825        else:
     1826            x = self.g
     1827        if typ(x) != t_INT:
     1828            raise TypeError("gen must be of PARI type t_INT or t_POL of degree 0")
     1829        if not signe(x):
     1830            return 0
     1831        mpz_init(x_mpz)
     1832        t_INT_to_ZZ(x_mpz, x)
     1833        # mpz_get_pylong always returns a Python long
     1834        result = mpz_get_pylong(x_mpz)
     1835        mpz_clear(x_mpz)
     1836        return result
    18261837   
    18271838    def __float__(gen self):
    18281839        """