Commit 1d47a9ef authored by Robert Bradshaw's avatar Robert Bradshaw

Require GIL for pythonic division, check for division overflow

parent bf6d9824
......@@ -4247,6 +4247,8 @@ class DivNode(NumBinopNode):
# Need to check ahead of time to warn or raise zero division error
self.operand1 = self.operand1.coerce_to_simple(env)
self.operand2 = self.operand2.coerce_to_simple(env)
if env.nogil:
error(self.pos, "Pythonic division not allowed without gil, consider using cython.cdivision(True)")
def zero_division_message(self):
if self.type.is_int:
......@@ -4272,6 +4274,15 @@ class DivNode(NumBinopNode):
code.putln('PyErr_Format(PyExc_ZeroDivisionError, "%s");' % self.zero_division_message())
code.putln(code.error_goto(self.pos))
code.putln("}")
if self.type.is_int and self.type.signed and self.operator != '%':
code.globalstate.use_utility_code(division_overflow_test_code)
code.putln("else if (sizeof(%s) == sizeof(long) && unlikely(%s == -1) && unlikely(UNARY_NEG_WOULD_OVERFLOW(%s))) {" % (
self.type.declaration_code(''),
self.operand2.result(),
self.operand1.result()))
code.putln('PyErr_Format(PyExc_OverflowError, "value too large to perform division");')
code.putln(code.error_goto(self.pos))
code.putln("}")
if code.globalstate.directives['cdivision_warnings']:
code.globalstate.use_utility_code(cdivision_warning_utility_code)
code.putln("if ((%s < 0) ^ (%s < 0)) {" % (
......@@ -5772,3 +5783,10 @@ static int __Pyx_cdivision_warning(void) {
'MODULENAME': Naming.modulename_cname,
'LINENO': Naming.lineno_cname,
})
# from intobject.c
division_overflow_test_code = UtilityCode(
proto="""
#define UNARY_NEG_WOULD_OVERFLOW(x) \
(((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
""")
......@@ -64,6 +64,14 @@ verbose_call(5)
'float division'
>>> mod_div_zero_float(25, 0, 0)
'float divmod()'
>>> import sys
>>> py_div_long(-5, -1)
5
>>> py_div_long(-sys.maxint-1, -1)
Traceback (most recent call last):
...
OverflowError: value too large to perform division
"""
cimport cython
......@@ -147,3 +155,7 @@ def mod_div_zero_float(float a, float b, float c):
return (a % b) / c
except ZeroDivisionError, ex:
return ex.message
@cython.cdivision(False)
def py_div_long(long a, long b):
return a / b
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