Commit 44694afc authored by Stefan Behnel's avatar Stefan Behnel

inline PyLong type conversion also for very large integer types and test with int128 in gcc

parent fdac73d6
......@@ -602,8 +602,12 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
{{for _size in (2, 3, 4)}}
case {{_size}}:
if ((8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT) && (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
if (8 * sizeof({{TYPE}}) > {{_size-1}} * PyLong_SHIFT) {
if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, unsigned long, {{pylong_join(_size, 'digits')}})
} else if (8 * sizeof({{TYPE}}) >= {{_size}} * PyLong_SHIFT) {
return {{pylong_join(_size, 'digits', TYPE)}};
}
}
break;
{{endfor}}
......@@ -639,8 +643,12 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
{{for _size in (2, 3, 4)}}
{{for _case in (-_size, _size)}}
case {{_case}}:
if ((8 * sizeof({{TYPE}}) > {{_size if _case < 0 else _size-1}} * PyLong_SHIFT) && (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT)) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
if (8 * sizeof({{TYPE}}){{' - 1' if _case < 0 else ''}} > {{_size-1}} * PyLong_SHIFT) {
if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT) {
__PYX_VERIFY_RETURN_INT({{TYPE}}, {{'long' if _case < 0 else 'unsigned long'}}, {{'-(long) ' if _case < 0 else ''}}{{pylong_join(_size, 'digits')}})
} else if (8 * sizeof({{TYPE}}) - 1 > {{_size}} * PyLong_SHIFT) {
return {{'-' if _case < 0 else ''}}{{pylong_join(_size, 'digits', TYPE)}};
}
}
break;
{{endfor}}
......
......@@ -271,6 +271,10 @@ def get_openmp_compiler_flags(language):
if not gcc_version:
return None # not gcc - FIXME: do something about other compilers
# gcc defines "__int128_t", assume that at least all 64 bit architectures have it
global COMPILER_HAS_INT128
COMPILER_HAS_INT128 = getattr(sys, 'maxsize', getattr(sys, 'maxint', 0)) > 2**60
compiler_version = gcc_version.group(1)
if compiler_version and compiler_version.split('.') >= ['4', '2']:
return '-fopenmp', '-fopenmp'
......@@ -280,6 +284,8 @@ try:
except locale.Error:
pass
COMPILER = None
COMPILER_HAS_INT128 = False
OPENMP_C_COMPILER_FLAGS = get_openmp_compiler_flags('c')
OPENMP_CPP_COMPILER_FLAGS = get_openmp_compiler_flags('cpp')
......@@ -327,7 +333,6 @@ VER_DEP_MODULES = {
]),
}
COMPILER = None
INCLUDE_DIRS = [ d for d in os.getenv('INCLUDE', '').split(os.pathsep) if d ]
CFLAGS = os.getenv('CFLAGS', '').split()
CCACHE = os.getenv('CYTHON_RUNTESTS_CCACHE', '').split()
......@@ -1941,6 +1946,9 @@ def runtests(options, cmd_args, coverage=None):
if options.exclude:
exclude_selectors += [ string_selector(r) for r in options.exclude ]
if not COMPILER_HAS_INT128 or not IS_CPYTHON:
exclude_selectors += [RegExSelector('int128')]
if options.shard_num > -1:
exclude_selectors.append(ShardExcludeSelector(options.shard_num, options.shard_count))
......
cdef extern from *:
ctypedef long long int128_t "__int128_t"
ctypedef unsigned long long uint128_t "__uint128_t"
def bigint(x):
print(str(x).rstrip('L'))
def unsigned_conversion(x):
"""
>>> bigint(unsigned_conversion(0))
0
>>> bigint(unsigned_conversion(2))
2
>>> unsigned_conversion(-2) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: can't convert negative value to ...uint128_t
>>> unsigned_conversion(-2**120) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: can't convert negative value to ...uint128_t
>>> unsigned_conversion(-2**127) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: can't convert negative value to ...uint128_t
>>> unsigned_conversion(-2**128) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: can't convert negative value to ...uint128_t
>>> bigint(unsigned_conversion(2**20))
1048576
>>> bigint(unsigned_conversion(2**30-1))
1073741823
>>> bigint(unsigned_conversion(2**30))
1073741824
>>> bigint(unsigned_conversion(2**30+1))
1073741825
>>> bigint(2**60)
1152921504606846976
>>> bigint(unsigned_conversion(2**60-1))
1152921504606846975
>>> bigint(unsigned_conversion(2**60))
1152921504606846976
>>> bigint(unsigned_conversion(2**60+1))
1152921504606846977
>>> bigint(2**64)
18446744073709551616
>>> bigint(unsigned_conversion(2**64))
18446744073709551616
>>> bigint(2**120)
1329227995784915872903807060280344576
>>> bigint(unsigned_conversion(2**120))
1329227995784915872903807060280344576
>>> bigint(2**128-1)
340282366920938463463374607431768211455
>>> bigint(unsigned_conversion(2**128-1))
340282366920938463463374607431768211455
>>> bigint(unsigned_conversion(2**128)) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: ... too big to convert
"""
cdef uint128_t n = x
return n
def signed_conversion(x):
"""
>>> bigint(signed_conversion(0))
0
>>> bigint(signed_conversion(2))
2
>>> bigint(signed_conversion(-2))
-2
>>> bigint(signed_conversion(2**20))
1048576
>>> bigint(signed_conversion(2**32))
4294967296
>>> bigint(2**64)
18446744073709551616
>>> bigint(signed_conversion(2**64))
18446744073709551616
>>> bigint(signed_conversion(-2**64))
-18446744073709551616
>>> bigint(2**118)
332306998946228968225951765070086144
>>> bigint(signed_conversion(2**118))
332306998946228968225951765070086144
>>> bigint(signed_conversion(-2**118))
-332306998946228968225951765070086144
>>> bigint(2**120)
1329227995784915872903807060280344576
>>> bigint(signed_conversion(2**120))
1329227995784915872903807060280344576
>>> bigint(signed_conversion(-2**120))
-1329227995784915872903807060280344576
>>> bigint(2**127-1)
170141183460469231731687303715884105727
>>> bigint(signed_conversion(2**127-2))
170141183460469231731687303715884105726
>>> bigint(signed_conversion(2**127-1))
170141183460469231731687303715884105727
>>> bigint(signed_conversion(2**127)) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: ... too big to convert
>>> bigint(signed_conversion(-2**127))
-170141183460469231731687303715884105728
>>> bigint(signed_conversion(-2**127-1)) # doctest: +ELLIPSIS
Traceback (most recent call last):
OverflowError: ... too big to convert
"""
cdef int128_t n = x
return n
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment