return
if self.type.is_complex:
self.infix = False
- if self.type.is_int and self.operator in ('+', '-', '*', '/'):
+ if self.type.is_int and env.directives['overflowcheck'] and self.operator in ('+', '-', '*'):
self.overflow_check = True
- binop = {'+': 'add', '-': 'sub', '*': 'mul', '/': 'div'}[self.operator]
- self.func = self.type.overflow_check_binop(binop, env)
+ self.func = self.type.overflow_check_binop(self.op_names[self.operator], env)
self.is_temp = True
if not self.infix or (type1.is_numeric and type2.is_numeric):
self.operand1 = self.operand1.coerce_to(self.type, env)
"%": "PyNumber_Remainder",
"**": "PyNumber_Power"
}
+
+ op_names = {
+ "+": "add",
+ "-": "sub",
+ "*": "mul",
+ }
class IntBinopNode(NumBinopNode):
# Binary operation taking integer arguments.
unsigned long big_r = ((unsigned long) a) * ((unsigned long) b);
{{UINT}} r = ({{UINT}}) big_r;
*overflow |= big_r != r;
- return ({{UINT}}) r;
+ return r;
} else if (sizeof({{UINT}}) < sizeof(long long)) {
unsigned long long big_r = ((unsigned long long) a) * ((unsigned long long) b);
{{UINT}} r = ({{UINT}}) big_r;
*overflow |= big_r != r;
- return ({{UINT}}) r;
+ return r;
} else {
{{UINT}} prod = a * b;
double dprod = ((double) a) * ((double) b);
- // False positives. Yes, the equality is required to avoid false negatives.
- *overflow |= dprod >= (double) __PYX_MAX({{UINT}});
+ // Overflow results in an error of at least 2^sizeof(UINT),
+ // whereas rounding represents an error on the order of 2^(sizeof(UINT)-53).
+ *overflow |= fabs(dprod - prod) > (__PYX_MAX({{UINT}}) / 2);
return prod;
}
}
/////////////// BaseCaseSigned ///////////////
-#define TOP_TWO_BITS(value, type) (value & ((unsigned type)3 << (sizeof(type) * 8 - 2)))
-
static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
if (sizeof({{INT}}) < sizeof(long)) {
long big_r = ((long) a) + ((long) b);
{{INT}} r = ({{INT}}) big_r;
*overflow |= big_r != r;
- return ({{INT}}) r;
+ return r;
} else if (sizeof({{INT}}) < sizeof(long long)) {
long long big_r = ((long long) a) + ((long long) b);
{{INT}} r = ({{INT}}) big_r;
*overflow |= big_r != r;
- return ({{INT}}) r;
+ return r;
} else {
- // Signed overflow undefined, but unsigned is well defined.
+ // Signed overflow undefined, but unsigned overflow is well defined.
{{INT}} r = ({{INT}}) ((unsigned {{INT}}) a + (unsigned {{INT}}) b);
+ // Overflow happened if the operands have the same sign, but the result
+ // has opposite sign.
// sign(a) == sign(b) != sign(r)
{{INT}} sign_a = __PYX_SIGN_BIT({{INT}}) & a;
{{INT}} sign_b = __PYX_SIGN_BIT({{INT}}) & b;
} else {
{{INT}} prod = a * b;
double dprod = ((double) a) * ((double) b);
- // False positives.
- *overflow |= fabs(dprod) > (double) __PYX_MAX({{INT}});
+ // Overflow results in an error of at least 2^sizeof(INT),
+ // whereas rounding represents an error on the order of 2^(sizeof(INT)-53).
+ *overflow |= fabs(dprod - prod) > (__PYX_MAX({{INT}}) / 2);
return prod;
}
}