diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2013-01-21 07:18:17 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2013-01-21 07:18:17 +0100 |
commit | 43fe5b88813bb051e89d9be61373cdc3b098d624 (patch) | |
tree | 8a89d8ccc2f41b56d2c6f4b9ea9e43dfb914e43d | |
parent | 9f9652896bc4ed62e7480513d803b5e01eac256c (diff) | |
download | cython-43fe5b88813bb051e89d9be61373cdc3b098d624.tar.gz |
simplify abs() optimisation for C integers and fix it for the most negative int/long value
-rw-r--r-- | Cython/Compiler/Builtin.py | 20 | ||||
-rw-r--r-- | tests/run/builtin_abs.pyx | 20 |
2 files changed, 30 insertions, 10 deletions
diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 757a2287f..23815fc1a 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -19,16 +19,16 @@ proto = """ abs_int_utility_code = UtilityCode( proto = ''' -#if HAVE_LONG_LONG && defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -#define __Pyx_abs_int(x) \ - ((sizeof(x) <= sizeof(int)) ? ((unsigned int)abs(x)) : \ - ((sizeof(x) <= sizeof(long)) ? ((unsigned long)labs(x)) : \ - ((unsigned PY_LONG_LONG)llabs(x)))) -#else -#define __Pyx_abs_int(x) \ - ((sizeof(x) <= sizeof(int)) ? ((unsigned int)abs(x)) : ((unsigned long)labs(x))) -#endif -#define __Pyx_abs_long(x) __Pyx_abs_int(x) +static CYTHON_INLINE unsigned int __Pyx_abs_int(int x) { + if (unlikely(x == -INT_MAX-1)) + return ((unsigned int)INT_MAX) + 1U; + return (unsigned int) abs(x); +} +static CYTHON_INLINE unsigned long __Pyx_abs_long(long x) { + if (unlikely(x == -LONG_MAX-1)) + return ((unsigned long)LONG_MAX) + 1U; + return (unsigned long) labs(x); +} ''') iter_next_utility_code = UtilityCode.load_cached("IterNext", "ObjectHandling.c") diff --git a/tests/run/builtin_abs.pyx b/tests/run/builtin_abs.pyx index ebeade154..87aedbb36 100644 --- a/tests/run/builtin_abs.pyx +++ b/tests/run/builtin_abs.pyx @@ -47,6 +47,16 @@ def int_abs(int a): """ return abs(a) +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']") +@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_int']", + "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_long']") +def uint_abs(unsigned int a): + """ + >>> uint_abs(max_int) == abs(max_int) or (max_int, uint_abs(max_int), abs(max_int)) + True + """ + return abs(a) + @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_long']") def long_abs(long a): @@ -64,6 +74,16 @@ def long_abs(long a): """ return abs(a) +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']") +@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_int']", + "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_long']") +def ulong_abs(unsigned long a): + """ + >>> ulong_abs(max_long) == abs(max_long) or (max_int, ulong_abs(max_long), abs(max_long)) + True + """ + return abs(a) + def long_long_abs(long long a): """ >>> long_long_abs(-(2**33)) == 2**33 |