123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /*
- These functions provide integer arithmetic with integer checking. They do not
- actually raise an exception when an overflow is detected, but rather set a bit
- in the overflow parameter. (This parameter may be re-used across several
- arithmetic operations, so should be or-ed rather than assigned to.)
- The implementation is divided into two parts, the signed and unsigned basecases,
- which is where the magic happens, and a generic template matching a specific
- type to an implementation based on its (c-compile-time) size and signedness.
- When possible, branching is avoided, and preference is given to speed over
- accuracy (a low rate of falsely "detected" overflows are acceptable,
- undetected overflows are not).
- TODO: Hook up checking.
- TODO: Conditionally support 128-bit with intmax_t?
- */
- /////////////// Common.proto ///////////////
- static int __Pyx_check_twos_complement(void) {
- if ((-1 != ~0)) {
- PyErr_SetString(PyExc_RuntimeError, "Two's complement required for overflow checks.");
- return 1;
- } else if ((sizeof(short) == sizeof(int))) {
- PyErr_SetString(PyExc_RuntimeError, "sizeof(short) < sizeof(int) required for overflow checks.");
- return 1;
- } else {
- return 0;
- }
- }
- #define __PYX_IS_UNSIGNED(type) ((((type) -1) > 0))
- #define __PYX_SIGN_BIT(type) ((((unsigned type) 1) << (sizeof(type) * 8 - 1)))
- #define __PYX_HALF_MAX(type) ((((type) 1) << (sizeof(type) * 8 - 2)))
- #define __PYX_MIN(type) ((__PYX_IS_UNSIGNED(type) ? (type) 0 : 0 - __PYX_HALF_MAX(type) - __PYX_HALF_MAX(type)))
- #define __PYX_MAX(type) ((~__PYX_MIN(type)))
- #define __Pyx_add_no_overflow(a, b, overflow) ((a) + (b))
- #define __Pyx_add_const_no_overflow(a, b, overflow) ((a) + (b))
- #define __Pyx_sub_no_overflow(a, b, overflow) ((a) - (b))
- #define __Pyx_sub_const_no_overflow(a, b, overflow) ((a) - (b))
- #define __Pyx_mul_no_overflow(a, b, overflow) ((a) * (b))
- #define __Pyx_mul_const_no_overflow(a, b, overflow) ((a) * (b))
- #define __Pyx_div_no_overflow(a, b, overflow) ((a) / (b))
- #define __Pyx_div_const_no_overflow(a, b, overflow) ((a) / (b))
- /////////////// Common.init ///////////////
- //@substitute: naming
- // FIXME: Propagate the error here instead of just printing it.
- if (unlikely(__Pyx_check_twos_complement())) {
- PyErr_WriteUnraisable($module_cname);
- }
- /////////////// BaseCaseUnsigned.proto ///////////////
- static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
- static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
- static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
- static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow);
- // Use these when b is known at compile time.
- #define __Pyx_add_const_{{NAME}}_checking_overflow __Pyx_add_{{NAME}}_checking_overflow
- #define __Pyx_sub_const_{{NAME}}_checking_overflow __Pyx_sub_{{NAME}}_checking_overflow
- static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} constant, int *overflow);
- #define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow
- /////////////// BaseCaseUnsigned ///////////////
- static CYTHON_INLINE {{UINT}} __Pyx_add_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- {{UINT}} r = a + b;
- *overflow |= r < a;
- return r;
- }
- static CYTHON_INLINE {{UINT}} __Pyx_sub_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- {{UINT}} r = a - b;
- *overflow |= r > a;
- return r;
- }
- static CYTHON_INLINE {{UINT}} __Pyx_mul_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- if ((sizeof({{UINT}}) < sizeof(unsigned long))) {
- unsigned long big_r = ((unsigned long) a) * ((unsigned long) b);
- {{UINT}} r = ({{UINT}}) big_r;
- *overflow |= big_r != r;
- return r;
- #ifdef HAVE_LONG_LONG
- } else if ((sizeof({{UINT}}) < sizeof(unsigned PY_LONG_LONG))) {
- unsigned PY_LONG_LONG big_r = ((unsigned PY_LONG_LONG) a) * ((unsigned PY_LONG_LONG) b);
- {{UINT}} r = ({{UINT}}) big_r;
- *overflow |= big_r != r;
- return r;
- #endif
- } else {
- {{UINT}} prod = a * b;
- double dprod = ((double) a) * ((double) b);
- // 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;
- }
- }
- static CYTHON_INLINE {{UINT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- if (b > 1) {
- *overflow |= a > __PYX_MAX({{UINT}}) / b;
- }
- return a * b;
- }
- static CYTHON_INLINE {{UINT}} __Pyx_div_{{NAME}}_checking_overflow({{UINT}} a, {{UINT}} b, int *overflow) {
- if (b == 0) {
- *overflow |= 1;
- return 0;
- }
- return a / b;
- }
- /////////////// BaseCaseSigned.proto ///////////////
- static CYTHON_INLINE {{INT}} __Pyx_add_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- static CYTHON_INLINE {{INT}} __Pyx_mul_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- // Use when b is known at compile time.
- static CYTHON_INLINE {{INT}} __Pyx_add_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- static CYTHON_INLINE {{INT}} __Pyx_sub_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow);
- static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} constant, int *overflow);
- #define __Pyx_div_const_{{NAME}}_checking_overflow __Pyx_div_{{NAME}}_checking_overflow
- /////////////// BaseCaseSigned ///////////////
- 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 r;
- #ifdef HAVE_LONG_LONG
- } else if ((sizeof({{INT}}) < sizeof(PY_LONG_LONG))) {
- PY_LONG_LONG big_r = ((PY_LONG_LONG) a) + ((PY_LONG_LONG) b);
- {{INT}} r = ({{INT}}) big_r;
- *overflow |= big_r != r;
- return r;
- #endif
- } else {
- // 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;
- {{INT}} sign_r = __PYX_SIGN_BIT({{INT}}) & r;
- *overflow |= (sign_a == sign_b) & (sign_a != sign_r);
- return r;
- }
- }
- static CYTHON_INLINE {{INT}} __Pyx_add_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- if (b > 0) {
- *overflow |= a > __PYX_MAX({{INT}}) - b;
- } else if (b < 0) {
- *overflow |= a < __PYX_MIN({{INT}}) - b;
- }
- return a + b;
- }
- static CYTHON_INLINE {{INT}} __Pyx_sub_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- *overflow |= b == __PYX_MIN({{INT}});
- return __Pyx_add_{{NAME}}_checking_overflow(a, -b, overflow);
- }
- static CYTHON_INLINE {{INT}} __Pyx_sub_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- *overflow |= b == __PYX_MIN({{INT}});
- return __Pyx_add_const_{{NAME}}_checking_overflow(a, -b, overflow);
- }
- static CYTHON_INLINE {{INT}} __Pyx_mul_{{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;
- #ifdef HAVE_LONG_LONG
- } else if ((sizeof({{INT}}) < sizeof(PY_LONG_LONG))) {
- PY_LONG_LONG big_r = ((PY_LONG_LONG) a) * ((PY_LONG_LONG) b);
- {{INT}} r = ({{INT}}) big_r;
- *overflow |= big_r != r;
- return ({{INT}}) r;
- #endif
- } else {
- {{INT}} prod = a * b;
- double dprod = ((double) a) * ((double) b);
- // 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;
- }
- }
- static CYTHON_INLINE {{INT}} __Pyx_mul_const_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- if (b > 1) {
- *overflow |= a > __PYX_MAX({{INT}}) / b;
- *overflow |= a < __PYX_MIN({{INT}}) / b;
- } else if (b == -1) {
- *overflow |= a == __PYX_MIN({{INT}});
- } else if (b < -1) {
- *overflow |= a > __PYX_MIN({{INT}}) / b;
- *overflow |= a < __PYX_MAX({{INT}}) / b;
- }
- return a * b;
- }
- static CYTHON_INLINE {{INT}} __Pyx_div_{{NAME}}_checking_overflow({{INT}} a, {{INT}} b, int *overflow) {
- if (b == 0) {
- *overflow |= 1;
- return 0;
- }
- *overflow |= (a == __PYX_MIN({{INT}})) & (b == -1);
- return a / b;
- }
- /////////////// SizeCheck.init ///////////////
- //@substitute: naming
- // FIXME: Propagate the error here instead of just printing it.
- if (unlikely(__Pyx_check_sane_{{NAME}}())) {
- PyErr_WriteUnraisable($module_cname);
- }
- /////////////// SizeCheck.proto ///////////////
- static int __Pyx_check_sane_{{NAME}}(void) {
- if (((sizeof({{TYPE}}) <= sizeof(int)) ||
- #ifdef HAVE_LONG_LONG
- (sizeof({{TYPE}}) == sizeof(PY_LONG_LONG)) ||
- #endif
- (sizeof({{TYPE}}) == sizeof(long)))) {
- return 0;
- } else {
- PyErr_Format(PyExc_RuntimeError, \
- "Bad size for int type %.{{max(60, len(TYPE))}}s: %d", "{{TYPE}}", (int) sizeof({{TYPE}}));
- return 1;
- }
- }
- /////////////// Binop.proto ///////////////
- static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow);
- /////////////// Binop ///////////////
- static CYTHON_INLINE {{TYPE}} __Pyx_{{BINOP}}_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow) {
- if ((sizeof({{TYPE}}) < sizeof(int))) {
- return __Pyx_{{BINOP}}_no_overflow(a, b, overflow);
- } else if (__PYX_IS_UNSIGNED({{TYPE}})) {
- if ((sizeof({{TYPE}}) == sizeof(unsigned int))) {
- return __Pyx_{{BINOP}}_unsigned_int_checking_overflow(a, b, overflow);
- } else if ((sizeof({{TYPE}}) == sizeof(unsigned long))) {
- return __Pyx_{{BINOP}}_unsigned_long_checking_overflow(a, b, overflow);
- #ifdef HAVE_LONG_LONG
- } else if ((sizeof({{TYPE}}) == sizeof(unsigned PY_LONG_LONG))) {
- return __Pyx_{{BINOP}}_unsigned_long_long_checking_overflow(a, b, overflow);
- #endif
- } else {
- abort(); return 0; /* handled elsewhere */
- }
- } else {
- if ((sizeof({{TYPE}}) == sizeof(int))) {
- return __Pyx_{{BINOP}}_int_checking_overflow(a, b, overflow);
- } else if ((sizeof({{TYPE}}) == sizeof(long))) {
- return __Pyx_{{BINOP}}_long_checking_overflow(a, b, overflow);
- #ifdef HAVE_LONG_LONG
- } else if ((sizeof({{TYPE}}) == sizeof(PY_LONG_LONG))) {
- return __Pyx_{{BINOP}}_long_long_checking_overflow(a, b, overflow);
- #endif
- } else {
- abort(); return 0; /* handled elsewhere */
- }
- }
- }
- /////////////// LeftShift.proto ///////////////
- static CYTHON_INLINE {{TYPE}} __Pyx_lshift_{{NAME}}_checking_overflow({{TYPE}} a, {{TYPE}} b, int *overflow) {
- *overflow |=
- #if {{SIGNED}}
- (b < 0) |
- #endif
- (b > ({{TYPE}}) (8 * sizeof({{TYPE}}))) | (a > (__PYX_MAX({{TYPE}}) >> b));
- return a << b;
- }
- #define __Pyx_lshift_const_{{NAME}}_checking_overflow __Pyx_lshift_{{NAME}}_checking_overflow
- /////////////// UnaryNegOverflows.proto ///////////////
- //FIXME: shouldn't the macro name be prefixed by "__Pyx_" ? Too late now, I guess...
- // from intobject.c
- #define UNARY_NEG_WOULD_OVERFLOW(x) \
- (((x) < 0) & ((unsigned long)(x) == 0-(unsigned long)(x)))
|