Commit 6b36a27e authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

merge

parents 35fd3ad0 2779f4bd
...@@ -4249,7 +4249,7 @@ class DivNode(NumBinopNode): ...@@ -4249,7 +4249,7 @@ class DivNode(NumBinopNode):
or not self.type.signed or not self.type.signed
or self.type.is_float) or self.type.is_float)
if not self.cdivision: if not self.cdivision:
code.globalstate.use_utility_code(div_utility_code.specialize(self.type)) code.globalstate.use_utility_code(div_int_utility_code.specialize(self.type))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']: if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
self.generate_div_warning_code(code) self.generate_div_warning_code(code)
...@@ -4265,7 +4265,11 @@ class DivNode(NumBinopNode): ...@@ -4265,7 +4265,11 @@ class DivNode(NumBinopNode):
code.putln("}") code.putln("}")
def calculate_result_code(self): def calculate_result_code(self):
if self.cdivision: if self.type.is_float and self.operator == '//':
return "floor(%s / %s)" % (
self.operand1.result(),
self.operand2.result())
elif self.cdivision:
return "(%s / %s)" % ( return "(%s / %s)" % (
self.operand1.result(), self.operand1.result(),
self.operand2.result()) self.operand2.result())
...@@ -4290,11 +4294,10 @@ class ModNode(DivNode): ...@@ -4290,11 +4294,10 @@ class ModNode(DivNode):
self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed self.cdivision = code.globalstate.directives['cdivision'] or not self.type.signed
if not self.cdivision: if not self.cdivision:
if self.type.is_int: if self.type.is_int:
code.globalstate.use_utility_code(mod_int_helper_macro) code.globalstate.use_utility_code(mod_int_utility_code.specialize(self.type))
math_h_modifier = '__Pyx_INT'
else: else:
math_h_modifier = self.type.math_h_modifier code.globalstate.use_utility_code(
code.globalstate.use_utility_code(mod_utility_code.specialize(self.type, math_h_modifier=math_h_modifier)) mod_float_utility_code.specialize(self.type, math_h_modifier=self.type.math_h_modifier))
NumBinopNode.generate_evaluation_code(self, code) NumBinopNode.generate_evaluation_code(self, code)
if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']: if not self.type.is_pyobject and code.globalstate.directives['cdivision_warnings']:
self.generate_div_warning_code(code) self.generate_div_warning_code(code)
...@@ -5690,32 +5693,40 @@ static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) { ...@@ -5690,32 +5693,40 @@ static INLINE %(type)s %(func_name)s(%(type)s b, %(type)s e) {
# ------------------------------ Division ------------------------------------ # ------------------------------ Division ------------------------------------
# This is so we can treat floating point and integer mod simultaneously. div_int_utility_code = UtilityCode(
mod_int_helper_macro = UtilityCode(proto=""" proto="""
#define fmod__Pyx_INT(a, b) ((a) % (b)) static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */
""",
impl="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s q = a / b;
%(type)s r = a - q*b;
q -= ((r != 0) & ((r ^ b) < 0));
return q;
}
""") """)
mod_utility_code = UtilityCode( mod_int_utility_code = UtilityCode(
proto=""" proto="""
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */ static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
""", """,
impl=""" impl="""
static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) { static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s res = fmod%(math_h_modifier)s(a, b); %(type)s r = a %% b;
res += ((res < 0) ^ (b < 0)) * b; r += ((r != 0) & ((r ^ b) < 0)) * b;
return res; return r;
} }
""") """)
div_utility_code = UtilityCode( mod_float_utility_code = UtilityCode(
proto=""" proto="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s, %(type)s); /* proto */ static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s, %(type)s); /* proto */
""", """,
impl=""" impl="""
static INLINE %(type)s __Pyx_div_%(type_name)s(%(type)s a, %(type)s b) { static INLINE %(type)s __Pyx_mod_%(type_name)s(%(type)s a, %(type)s b) {
%(type)s res = a / b; %(type)s r = fmod%(math_h_modifier)s(a, b);
res -= (res < 0); r += ((r != 0) & ((r < 0) ^ (b < 0))) * b;
return res; return r;
} }
""") """)
......
__doc__ = u"""
>>> cdiv_decorator(-12, 5)
-2
>>> pydiv_decorator(-12, 5)
-3
"""
cimport cython
@cython.cdivision(True)
cpdef cdiv_decorator(int a, int b):
return a / b
@cython.cdivision(False)
cpdef pydiv_decorator(int a, int b):
return a / b
...@@ -27,6 +27,10 @@ True ...@@ -27,6 +27,10 @@ True
>>> [test_cdiv_cmod(a, b) for a, b in v] >>> [test_cdiv_cmod(a, b) for a, b in v]
[(1, 7), (-1, -7), (1, -7), (-1, 7)] [(1, 7), (-1, -7), (1, -7), (-1, 7)]
>>> all([mod_int_py(a,b) == a % b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
>>> all([div_int_py(a,b) == a // b for a in range(-10, 10) for b in range(-10, 10) if b != 0])
True
>>> def simple_warn(msg, *args): print msg >>> def simple_warn(msg, *args): print msg
>>> import warnings >>> import warnings
......
__doc__ = u"""
>>> floor_div_float(2, 1.5)
1.0
>>> floor_div_float(2, -1.5)
-2.0
>>> floor_div_float(-2.3, 1.5)
-2.0
>>> floor_div_float(1e10, 1e-10)
1e+20
"""
def floor_div_float(double a, double 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