diff options
author | Stefan Behnel <stefan_ml@behnel.de> | 2018-12-14 15:40:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-14 15:40:59 +0100 |
commit | d3aeb4317bb70a1f923c19752e1dd0f4adda6c7a (patch) | |
tree | 113c2a0e93ab2e3156a63773c6c8b56c484eee5e | |
parent | 71b36d793610a2f3f081c140fad0b575b46af0cf (diff) | |
parent | efa49ca0d63726d907ae6f1497b3cdf3a186f6df (diff) | |
download | cython-d3aeb4317bb70a1f923c19752e1dd0f4adda6c7a.tar.gz |
Merge pull request #2748 from QuLogic/abs-nogil
Mark optimized abs as being nogil-safe.
-rw-r--r-- | Cython/Compiler/Builtin.py | 14 | ||||
-rw-r--r-- | Cython/Compiler/TypeSlots.py | 6 | ||||
-rw-r--r-- | tests/run/builtin_abs.pyx | 131 |
3 files changed, 143 insertions, 8 deletions
diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 1bdc643aa..0e01c5bcc 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -30,17 +30,19 @@ builtin_utility_code = { class _BuiltinOverride(object): def __init__(self, py_name, args, ret_type, cname, py_equiv="*", utility_code=None, sig=None, func_type=None, - is_strict_signature=False, builtin_return_type=None): + is_strict_signature=False, builtin_return_type=None, + nogil=None): self.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv self.args, self.ret_type = args, ret_type self.func_type, self.sig = func_type, sig self.builtin_return_type = builtin_return_type self.is_strict_signature = is_strict_signature self.utility_code = utility_code + self.nogil = nogil def build_func_type(self, sig=None, self_arg=None): if sig is None: - sig = Signature(self.args, self.ret_type) + sig = Signature(self.args, self.ret_type, nogil=self.nogil) sig.exception_check = False # not needed for the current builtins func_type = sig.function_type(self_arg) if self.is_strict_signature: @@ -92,13 +94,13 @@ class BuiltinMethod(_BuiltinOverride): builtin_function_table = [ # name, args, return, C API func, py equiv = "*" BuiltinFunction('abs', "d", "d", "fabs", - is_strict_signature = True), + is_strict_signature=True, nogil=True), BuiltinFunction('abs', "f", "f", "fabsf", - is_strict_signature = True), + is_strict_signature=True, nogil=True), BuiltinFunction('abs', "i", "i", "abs", - is_strict_signature = True), + is_strict_signature=True, nogil=True), BuiltinFunction('abs', "l", "l", "labs", - is_strict_signature = True), + is_strict_signature=True, nogil=True), BuiltinFunction('abs', None, None, "__Pyx_abs_longlong", utility_code = UtilityCode.load("abs_longlong", "Builtins.c"), func_type = PyrexTypes.CFuncType( diff --git a/Cython/Compiler/TypeSlots.py b/Cython/Compiler/TypeSlots.py index 7cf6cc4fb..caef40465 100644 --- a/Cython/Compiler/TypeSlots.py +++ b/Cython/Compiler/TypeSlots.py @@ -86,7 +86,7 @@ class Signature(object): 'z': "-1", } - def __init__(self, arg_format, ret_format): + def __init__(self, arg_format, ret_format, nogil=0): self.has_dummy_arg = 0 self.has_generic_args = 0 if arg_format[:1] == '-': @@ -100,6 +100,7 @@ class Signature(object): self.error_value = self.error_value_map.get(ret_format, None) self.exception_check = ret_format != 'r' and self.error_value is not None self.is_staticmethod = False + self.nogil = nogil def __repr__(self): return '<Signature[%s(%s%s)]>' % ( @@ -149,7 +150,8 @@ class Signature(object): exc_value = self.exception_value() return PyrexTypes.CFuncType( ret_type, args, exception_value=exc_value, - exception_check=self.exception_check) + exception_check=self.exception_check, + nogil=self.nogil) def method_flags(self): if self.ret_format == "O": diff --git a/tests/run/builtin_abs.pyx b/tests/run/builtin_abs.pyx index 13079a8fc..21bea7df2 100644 --- a/tests/run/builtin_abs.pyx +++ b/tests/run/builtin_abs.pyx @@ -59,6 +59,27 @@ def int_abs(int a): """ return abs(a) +@cython.overflowcheck(True) +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'abs']") +cdef int c_int_abs(int a) nogil except *: + return abs(a) + +def test_c_int_abs(int a): + """ + >>> test_c_int_abs(-5) == 5 + True + >>> test_c_int_abs(-5.1) == 5 + True + >>> test_c_int_abs(-max_int-1) #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + OverflowError: ... + >>> test_c_int_abs(max_int) == abs(max_int) or (max_int, test_c_int_abs(max_int), abs(max_int)) + True + """ + return c_int_abs(a) + @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']") @cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = 'labs']") @@ -69,6 +90,19 @@ def uint_abs(unsigned 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 = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'labs']") +cdef unsigned int c_uint_abs(unsigned int a) nogil: + return abs(a) + +def test_c_uint_abs(unsigned int a): + """ + >>> test_c_uint_abs(max_int) == abs(max_int) or (max_int, test_c_uint_abs(max_int), abs(max_int)) + True + """ + return c_uint_abs(a) + @cython.overflowcheck(True) @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = 'labs']") @@ -87,6 +121,27 @@ def long_abs(long a): """ return abs(a) +@cython.overflowcheck(True) +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'labs']") +cdef long c_long_abs(long a) nogil except *: + return abs(a) + +def test_c_long_abs(long a): + """ + >>> test_c_long_abs(-5) == 5 + True + >>> test_c_long_abs(-5.1) == 5 + True + >>> test_c_long_abs(-max_long-1) #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + OverflowError: ... + >>> test_c_long_abs(max_long) == abs(max_long) or (max_long, test_c_long_abs(max_long), abs(max_long)) + True + """ + return c_long_abs(a) + @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']") @cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = 'labs']") @@ -99,6 +154,21 @@ def ulong_abs(unsigned 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 = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'labs']") +cdef unsigned long c_ulong_abs(unsigned long a) nogil: + return abs(a) + +def test_c_ulong_abs(unsigned long a): + """ + >>> test_c_ulong_abs(max_long) == abs(max_long) or (max_int, test_c_ulong_abs(max_long), abs(max_long)) + True + >>> test_c_ulong_abs(max_long + 5) == abs(max_long + 5) or (max_long + 5, test_c_ulong_abs(max_long + 5), abs(max_long + 5)) + True + """ + return c_ulong_abs(a) + @cython.overflowcheck(True) @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']") @@ -115,6 +185,25 @@ def long_long_abs(long long a): """ return abs(a) +@cython.overflowcheck(True) +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']") +cdef long long c_long_long_abs(long long a) nogil except *: + return abs(a) + +def test_c_long_long_abs(long long a): + """ + >>> test_c_long_long_abs(-(2**33)) == 2**33 + True + >>> test_c_long_long_abs(-max_long_long-1) #doctest: +ELLIPSIS + Traceback (most recent call last): + ... + OverflowError: ... + >>> test_c_long_long_abs(max_long_long) == abs(max_long_long) or (max_long_long, test_c_long_long_abs(max_long_long), abs(max_long_long)) + True + """ + return c_long_long_abs(a) + @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = 'fabs']") def double_abs(double a): @@ -127,6 +216,20 @@ def double_abs(double a): return abs(a) @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'fabs']") +cdef double c_double_abs(double a) nogil: + return abs(a) + +def test_c_double_abs(double a): + """ + >>> test_c_double_abs(-5) + 5.0 + >>> test_c_double_abs(-5.5) + 5.5 + """ + return c_double_abs(a) + +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = 'fabsf']") def float_abs(float a): """ @@ -138,6 +241,20 @@ def float_abs(float a): return abs(a) @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = 'fabsf']") +cdef float c_float_abs(float a) nogil: + return abs(a) + +def test_c_float_abs(float a): + """ + >>> test_c_float_abs(-5) + 5.0 + >>> test_c_float_abs(-5.5) + 5.5 + """ + return c_float_abs(a) + +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']") def complex_abs(complex a): """ @@ -147,3 +264,17 @@ def complex_abs(complex a): 5.5 """ return abs(a) + +@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", + "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']") +cdef double c_complex_abs(complex a) nogil: + return abs(a) + +def test_c_complex_abs(complex a): + """ + >>> test_c_complex_abs(-5j) + 5.0 + >>> test_c_complex_abs(-5.5j) + 5.5 + """ + return c_complex_abs(a) |