Commit d3aeb431 authored by Stefan Behnel's avatar Stefan Behnel Committed by GitHub

Merge pull request #2748 from QuLogic/abs-nogil

Mark optimized abs as being nogil-safe.
parents 71b36d79 efa49ca0
...@@ -30,17 +30,19 @@ builtin_utility_code = { ...@@ -30,17 +30,19 @@ builtin_utility_code = {
class _BuiltinOverride(object): class _BuiltinOverride(object):
def __init__(self, py_name, args, ret_type, cname, py_equiv="*", def __init__(self, py_name, args, ret_type, cname, py_equiv="*",
utility_code=None, sig=None, func_type=None, 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.py_name, self.cname, self.py_equiv = py_name, cname, py_equiv
self.args, self.ret_type = args, ret_type self.args, self.ret_type = args, ret_type
self.func_type, self.sig = func_type, sig self.func_type, self.sig = func_type, sig
self.builtin_return_type = builtin_return_type self.builtin_return_type = builtin_return_type
self.is_strict_signature = is_strict_signature self.is_strict_signature = is_strict_signature
self.utility_code = utility_code self.utility_code = utility_code
self.nogil = nogil
def build_func_type(self, sig=None, self_arg=None): def build_func_type(self, sig=None, self_arg=None):
if sig is 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 sig.exception_check = False # not needed for the current builtins
func_type = sig.function_type(self_arg) func_type = sig.function_type(self_arg)
if self.is_strict_signature: if self.is_strict_signature:
...@@ -92,13 +94,13 @@ class BuiltinMethod(_BuiltinOverride): ...@@ -92,13 +94,13 @@ class BuiltinMethod(_BuiltinOverride):
builtin_function_table = [ builtin_function_table = [
# name, args, return, C API func, py equiv = "*" # name, args, return, C API func, py equiv = "*"
BuiltinFunction('abs', "d", "d", "fabs", BuiltinFunction('abs', "d", "d", "fabs",
is_strict_signature = True), is_strict_signature=True, nogil=True),
BuiltinFunction('abs', "f", "f", "fabsf", BuiltinFunction('abs', "f", "f", "fabsf",
is_strict_signature = True), is_strict_signature=True, nogil=True),
BuiltinFunction('abs', "i", "i", "abs", BuiltinFunction('abs', "i", "i", "abs",
is_strict_signature = True), is_strict_signature=True, nogil=True),
BuiltinFunction('abs', "l", "l", "labs", BuiltinFunction('abs', "l", "l", "labs",
is_strict_signature = True), is_strict_signature=True, nogil=True),
BuiltinFunction('abs', None, None, "__Pyx_abs_longlong", BuiltinFunction('abs', None, None, "__Pyx_abs_longlong",
utility_code = UtilityCode.load("abs_longlong", "Builtins.c"), utility_code = UtilityCode.load("abs_longlong", "Builtins.c"),
func_type = PyrexTypes.CFuncType( func_type = PyrexTypes.CFuncType(
......
...@@ -86,7 +86,7 @@ class Signature(object): ...@@ -86,7 +86,7 @@ class Signature(object):
'z': "-1", '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_dummy_arg = 0
self.has_generic_args = 0 self.has_generic_args = 0
if arg_format[:1] == '-': if arg_format[:1] == '-':
...@@ -100,6 +100,7 @@ class Signature(object): ...@@ -100,6 +100,7 @@ class Signature(object):
self.error_value = self.error_value_map.get(ret_format, None) 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.exception_check = ret_format != 'r' and self.error_value is not None
self.is_staticmethod = False self.is_staticmethod = False
self.nogil = nogil
def __repr__(self): def __repr__(self):
return '<Signature[%s(%s%s)]>' % ( return '<Signature[%s(%s%s)]>' % (
...@@ -149,7 +150,8 @@ class Signature(object): ...@@ -149,7 +150,8 @@ class Signature(object):
exc_value = self.exception_value() exc_value = self.exception_value()
return PyrexTypes.CFuncType( return PyrexTypes.CFuncType(
ret_type, args, exception_value=exc_value, ret_type, args, exception_value=exc_value,
exception_check=self.exception_check) exception_check=self.exception_check,
nogil=self.nogil)
def method_flags(self): def method_flags(self):
if self.ret_format == "O": if self.ret_format == "O":
......
...@@ -59,6 +59,27 @@ def int_abs(int a): ...@@ -59,6 +59,27 @@ def int_abs(int a):
""" """
return abs(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_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']", @cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'labs']") "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
...@@ -69,6 +90,19 @@ def uint_abs(unsigned int a): ...@@ -69,6 +90,19 @@ def uint_abs(unsigned int a):
""" """
return abs(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.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'labs']") "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
...@@ -87,6 +121,27 @@ def long_abs(long a): ...@@ -87,6 +121,27 @@ def long_abs(long a):
""" """
return abs(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_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']")
@cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']", @cython.test_fail_if_path_exists("//ReturnStatNode//NameNode[@entry.cname = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'labs']") "//ReturnStatNode//NameNode[@entry.cname = 'labs']")
...@@ -99,6 +154,21 @@ def ulong_abs(unsigned long a): ...@@ -99,6 +154,21 @@ def ulong_abs(unsigned long a):
""" """
return abs(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.overflowcheck(True)
@cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']") "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_abs_longlong']")
...@@ -115,6 +185,25 @@ def long_long_abs(long long a): ...@@ -115,6 +185,25 @@ def long_long_abs(long long a):
""" """
return abs(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']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'fabs']") "//ReturnStatNode//NameNode[@entry.cname = 'fabs']")
def double_abs(double a): def double_abs(double a):
...@@ -126,6 +215,20 @@ def double_abs(double a): ...@@ -126,6 +215,20 @@ def double_abs(double a):
""" """
return abs(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']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = 'fabsf']") "//ReturnStatNode//NameNode[@entry.cname = 'fabsf']")
def float_abs(float a): def float_abs(float a):
...@@ -137,6 +240,20 @@ def float_abs(float a): ...@@ -137,6 +240,20 @@ def float_abs(float a):
""" """
return abs(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']", @cython.test_assert_path_exists("//ReturnStatNode//NameNode[@entry.name = 'abs']",
"//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']") "//ReturnStatNode//NameNode[@entry.cname = '__Pyx_c_abs_double']")
def complex_abs(complex a): def complex_abs(complex a):
...@@ -147,3 +264,17 @@ def complex_abs(complex a): ...@@ -147,3 +264,17 @@ def complex_abs(complex a):
5.5 5.5
""" """
return abs(a) 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)
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