summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2013-01-21 07:18:17 +0100
committerStefan Behnel <stefan_ml@behnel.de>2013-01-21 07:18:17 +0100
commit43fe5b88813bb051e89d9be61373cdc3b098d624 (patch)
tree8a89d8ccc2f41b56d2c6f4b9ea9e43dfb914e43d
parent9f9652896bc4ed62e7480513d803b5e01eac256c (diff)
downloadcython-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.py20
-rw-r--r--tests/run/builtin_abs.pyx20
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