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

Commit

Permalink
Trac 18358: better pyobject_to_long
Browse files Browse the repository at this point in the history
  • Loading branch information
videlec committed May 6, 2015
1 parent 98008da commit c7b741f
Showing 1 changed file with 43 additions and 8 deletions.
51 changes: 43 additions & 8 deletions src/sage/misc/long.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,64 @@ Fast conversion macro to long

from libc.limits cimport LONG_MIN

from cpython.int cimport PyInt_CheckExact, PyInt_AS_LONG
from cpython.long cimport PyLong_CheckExact, PyLong_AsLong
from cpython.int cimport PyInt_AS_LONG
from cpython.long cimport PyLong_AsLong
from cpython.number cimport PyNumber_Index

from sage.libs.gmp.mpz cimport mpz_fits_slong_p, mpz_get_si

from sage.rings.integer cimport Integer

cdef inline long pyobject_to_long(x) except LONG_MIN:
cdef inline long pyobject_to_long(x) except? LONG_MIN:
r"""
Given a Python object ``x`` cast it quickly to a C long.
If it fails, it either raises a ``TypeError`` or a ``OverflowError`` (and
the exceptional value is `LONG_MIN`)
A ``TypeError`` is raised if the input can not be converted to an integer or
an ``OverflowError`` is raied if it does not fit into a C long.
TESTS:
We test indirectly that ``Integer.__pow__`` and ``Rational.__pow__`` work::
sage: tens = [10r, 10l, 10, 10/1]
sage: a = 10
sage: a^10
10000000000
sage: a^(10r)
10000000000
sage: a^(10l)
10000000000
sage: a^(10/1)
10000000000
sage: a^(2**258)
Traceback (most recent call last):
...
RuntimeError: exponent must be at most 2147483647 # 32-bit
RuntimeError: exponent must be at most 9223372036854775807 # 64-bit
sage: b = 1/2
sage: b^10
1/1024
sage: b^(10r)
1/1024
sage: b^(10l)
1/1024
sage: b^(10/1)
1/1024
sage: b^(2**258)
Traceback (most recent call last):
...
RuntimeError: exponent must be at most 2147483647 # 32-bit
RuntimeError: exponent must be at most 9223372036854775807 # 64-bit
"""
if PyInt_CheckExact(x):
if isinstance(x, int):
return PyInt_AS_LONG(x)
elif type(x) is Integer:
if mpz_fits_slong_p((<Integer>x).value):
return mpz_get_si((<Integer>x).value)
else:
raise OverflowError
elif PyLong_CheckExact(x):
raise OverflowError("Sage Integer too large to convert to C long")
elif isinstance(x, long):
return PyLong_AsLong(x)

return PyNumber_Index(x)

0 comments on commit c7b741f

Please sign in to comment.