Optimize.c 25.2 KB
Newer Older
1 2 3 4 5 6 7 8
/*
 * Optional optimisations of built-in functions and methods.
 *
 * Required replacements of builtins are in Builtins.c.
 *
 * General object operations and protocols are in ObjectHandling.c.
 */

9 10
/////////////// append.proto ///////////////

11
static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x); /*proto*/
12 13

/////////////// append ///////////////
14
//@requires: ListAppend
15
//@requires: ObjectHandling.c::PyObjectCallMethod1
16

17
static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x) {
18
    if (likely(PyList_CheckExact(L))) {
19
        if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return -1;
20
    } else {
21 22 23 24
        PyObject* retval = __Pyx_PyObject_CallMethod1(L, PYIDENT("append"), x);
        if (unlikely(!retval))
            return -1;
        Py_DECREF(retval);
25
    }
26
    return 0;
27 28
}

29
/////////////// ListAppend.proto ///////////////
30 31 32 33 34

#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) {
    PyListObject* L = (PyListObject*) list;
    Py_ssize_t len = Py_SIZE(list);
35
    if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) {
36 37 38 39 40 41 42 43 44 45
        Py_INCREF(x);
        PyList_SET_ITEM(list, len, x);
        Py_SIZE(list) = len+1;
        return 0;
    }
    return PyList_Append(list, x);
}
#else
#define __Pyx_PyList_Append(L,x) PyList_Append(L,x)
#endif
46

47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
/////////////// ListCompAppend.proto ///////////////

#if CYTHON_COMPILING_IN_CPYTHON
static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) {
    PyListObject* L = (PyListObject*) list;
    Py_ssize_t len = Py_SIZE(list);
    if (likely(L->allocated > len)) {
        Py_INCREF(x);
        PyList_SET_ITEM(list, len, x);
        Py_SIZE(list) = len+1;
        return 0;
    }
    return PyList_Append(list, x);
}
#else
#define __Pyx_ListComp_Append(L,x) PyList_Append(L,x)
#endif

Stefan Behnel's avatar
Stefan Behnel committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78
//////////////////// ListExtend.proto ////////////////////

static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) {
#if CYTHON_COMPILING_IN_CPYTHON
    PyObject* none = _PyList_Extend((PyListObject*)L, v);
    if (unlikely(!none))
        return -1;
    Py_DECREF(none);
    return 0;
#else
    return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v);
#endif
}

79 80
/////////////// pop.proto ///////////////

81 82 83 84 85
#define __Pyx_PyObject_Pop(L) (PyList_CheckExact(L) ? \
    __Pyx_PyList_Pop(L) : __Pyx__PyObject_Pop(L))

static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/
static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/
86 87

/////////////// pop ///////////////
88
//@requires: ObjectHandling.c::PyObjectCallMethod0
89

90
static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) {
91
#if CYTHON_COMPILING_IN_CPYTHON
92 93 94 95 96 97 98 99
    if (Py_TYPE(L) == &PySet_Type) {
        return PySet_Pop(L);
    }
#endif
    return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop"));
}

static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) {
100
#if CYTHON_COMPILING_IN_CPYTHON
101 102
    /* Check that both the size is positive and no reallocation shrinking needs to be done. */
    if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
103 104 105 106
        Py_SIZE(L) -= 1;
        return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
    }
#endif
107
    return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop"));
108
}
109 110 111 112


/////////////// pop_index.proto ///////////////

113 114
#define __Pyx_PyObject_PopIndex(L, ix, is_signed, type, to_py_func) ( \
    (PyList_CheckExact(L) && __Pyx_fits_Py_ssize_t(ix, type, is_signed)) ? \
115
        __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix)))
116

117 118
#define __Pyx_PyList_PopIndex(L, ix, is_signed, type, to_py_func) ( \
    __Pyx_fits_Py_ssize_t(ix, type, is_signed) ? \
119 120 121 122
        __Pyx__PyList_PopIndex(L, ix) : __Pyx__PyObject_PopIndex(L, to_py_func(ix)))

static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix); /*proto*/
static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/
123 124

/////////////// pop_index ///////////////
125
//@requires: ObjectHandling.c::PyObjectCallMethod1
126

127 128 129
static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) {
    PyObject *r;
    if (unlikely(!py_ix)) return NULL;
130 131
    r = __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix);
    Py_DECREF(py_ix);
132 133
    return r;
}
134

135
static PyObject* __Pyx__PyList_PopIndex(PyObject* L, Py_ssize_t ix) {
136 137 138 139 140 141 142 143 144 145 146
#if CYTHON_COMPILING_IN_CPYTHON
    Py_ssize_t size = PyList_GET_SIZE(L);
    if (likely(size > (((PyListObject*)L)->allocated >> 1))) {
        Py_ssize_t cix = ix;
        if (cix < 0) {
            cix += size;
        }
        if (likely(0 <= cix && cix < size)) {
            PyObject* v = PyList_GET_ITEM(L, cix);
            Py_SIZE(L) -= 1;
            size -= 1;
147
            memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*));
148 149 150 151
            return v;
        }
    }
#endif
152
    return __Pyx__PyObject_PopIndex(L, PyInt_FromSsize_t(ix));
153 154
}

155 156 157

/////////////// dict_getitem_default.proto ///////////////

158 159 160 161
static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value); /*proto*/

/////////////// dict_getitem_default ///////////////

162 163
static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value) {
    PyObject* value;
164
#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
    value = PyDict_GetItemWithError(d, key);
    if (unlikely(!value)) {
        if (unlikely(PyErr_Occurred()))
            return NULL;
        value = default_value;
    }
    Py_INCREF(value);
#else
    if (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key)) {
        /* these presumably have safe hash functions */
        value = PyDict_GetItem(d, key);
        if (unlikely(!value)) {
            value = default_value;
        }
        Py_INCREF(value);
    } else {
181 182 183 184
        if (default_value == Py_None)
            default_value = NULL;
        value = PyObject_CallMethodObjArgs(
            d, PYIDENT("get"), key, default_value, NULL);
185 186 187 188 189 190 191 192
    }
#endif
    return value;
}


/////////////// dict_setdefault.proto ///////////////

193
static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value, int is_safe_type); /*proto*/
194 195

/////////////// dict_setdefault ///////////////
196
//@requires: ObjectHandling.c::PyObjectCallMethod2
197

198 199
static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value,
                                                       CYTHON_UNUSED int is_safe_type) {
200
    PyObject* value;
201 202 203 204 205 206 207
#if PY_VERSION_HEX >= 0x030400A0
    // we keep the method call at the end to avoid "unused" C compiler warnings
    if (1) {
        value = PyDict_SetDefault(d, key, default_value);
        if (unlikely(!value)) return NULL;
        Py_INCREF(value);
#else
208
    if (is_safe_type == 1 || (is_safe_type == -1 &&
209
        /* the following builtins presumably have repeatably safe and fast hash functions */
210
#if PY_MAJOR_VERSION >= 3 && !CYTHON_COMPILING_IN_PYPY
211
            (PyUnicode_CheckExact(key) || PyString_CheckExact(key) || PyLong_CheckExact(key)))) {
212 213 214 215 216 217 218 219 220
        value = PyDict_GetItemWithError(d, key);
        if (unlikely(!value)) {
            if (unlikely(PyErr_Occurred()))
                return NULL;
            if (unlikely(PyDict_SetItem(d, key, default_value) == -1))
                return NULL;
            value = default_value;
        }
        Py_INCREF(value);
221
#else
222
            (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key) || PyLong_CheckExact(key)))) {
223 224 225 226 227 228 229
        value = PyDict_GetItem(d, key);
        if (unlikely(!value)) {
            if (unlikely(PyDict_SetItem(d, key, default_value) == -1))
                return NULL;
            value = default_value;
        }
        Py_INCREF(value);
230
#endif
231
#endif
232
    } else {
233
        value = __Pyx_PyObject_CallMethod2(d, PYIDENT("setdefault"), key, default_value);
234 235 236 237 238 239 240
    }
    return value;
}


/////////////// py_dict_clear.proto ///////////////

241
#define __Pyx_PyDict_Clear(d) (PyDict_Clear(d), 0)
242

243 244
/////////////// dict_iter.proto ///////////////

245 246
static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* dict, int is_dict, PyObject* method_name,
                                                   Py_ssize_t* p_orig_length, int* p_is_dict);
247 248 249 250 251
static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* dict_or_iter, Py_ssize_t orig_length, Py_ssize_t* ppos,
                                              PyObject** pkey, PyObject** pvalue, PyObject** pitem, int is_dict);

/////////////// dict_iter ///////////////
//@requires: ObjectHandling.c::UnpackTuple2
252
//@requires: ObjectHandling.c::IterFinish
253
//@requires: ObjectHandling.c::PyObjectCallMethod0
254

255
static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name,
256 257 258
                                                   Py_ssize_t* p_orig_length, int* p_source_is_dict) {
    is_dict = is_dict || likely(PyDict_CheckExact(iterable));
    *p_source_is_dict = is_dict;
259
#if !CYTHON_COMPILING_IN_PYPY
260
    if (is_dict) {
261 262 263
        *p_orig_length = PyDict_Size(iterable);
        Py_INCREF(iterable);
        return iterable;
264 265
    }
#endif
266
    *p_orig_length = 0;
267
    if (method_name) {
Stefan Behnel's avatar
Stefan Behnel committed
268
        PyObject* iter;
269
        iterable = __Pyx_PyObject_CallMethod0(iterable, method_name);
270
        if (!iterable)
271
            return NULL;
272 273 274 275
#if !CYTHON_COMPILING_IN_PYPY
        if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable))
            return iterable;
#endif
Stefan Behnel's avatar
Stefan Behnel committed
276 277 278
        iter = PyObject_GetIter(iterable);
        Py_DECREF(iterable);
        return iter;
279
    }
280
    return PyObject_GetIter(iterable);
281 282
}

283
static CYTHON_INLINE int __Pyx_dict_iter_next(PyObject* iter_obj, Py_ssize_t orig_length, Py_ssize_t* ppos,
284
                                              PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) {
285
    PyObject* next_item;
286
#if !CYTHON_COMPILING_IN_PYPY
287
    if (source_is_dict) {
288
        PyObject *key, *value;
289
        if (unlikely(orig_length != PyDict_Size(iter_obj))) {
290 291 292
            PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration");
            return -1;
        }
293
        if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) {
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
            return 0;
        }
        if (pitem) {
            PyObject* tuple = PyTuple_New(2);
            if (unlikely(!tuple)) {
                return -1;
            }
            Py_INCREF(key);
            Py_INCREF(value);
            PyTuple_SET_ITEM(tuple, 0, key);
            PyTuple_SET_ITEM(tuple, 1, value);
            *pitem = tuple;
        } else {
            if (pkey) {
                Py_INCREF(key);
                *pkey = key;
            }
            if (pvalue) {
                Py_INCREF(value);
                *pvalue = value;
            }
        }
        return 1;
317 318 319 320 321 322 323 324 325 326 327 328 329
    } else if (PyTuple_CheckExact(iter_obj)) {
        Py_ssize_t pos = *ppos;
        if (unlikely(pos >= PyTuple_GET_SIZE(iter_obj))) return 0;
        *ppos = pos + 1;
        next_item = PyTuple_GET_ITEM(iter_obj, pos);
        Py_INCREF(next_item);
    } else if (PyList_CheckExact(iter_obj)) {
        Py_ssize_t pos = *ppos;
        if (unlikely(pos >= PyList_GET_SIZE(iter_obj))) return 0;
        *ppos = pos + 1;
        next_item = PyList_GET_ITEM(iter_obj, pos);
        Py_INCREF(next_item);
    } else
330 331
#endif
    {
332
        next_item = PyIter_Next(iter_obj);
333
        if (unlikely(!next_item)) {
334
            return __Pyx_IterFinish();
335 336
        }
    }
337 338 339
    if (pitem) {
        *pitem = next_item;
    } else if (pkey && pvalue) {
340
        if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1))
341 342 343 344 345 346 347
            return -1;
    } else if (pkey) {
        *pkey = next_item;
    } else {
        *pvalue = next_item;
    }
    return 1;
348
}
349

350 351 352 353 354 355 356 357 358 359 360

/////////////// unicode_iter.proto ///////////////

static CYTHON_INLINE int __Pyx_init_unicode_iteration(
    PyObject* ustring, Py_ssize_t *length, void** data, int *kind); /* proto */

/////////////// unicode_iter ///////////////

static CYTHON_INLINE int __Pyx_init_unicode_iteration(
    PyObject* ustring, Py_ssize_t *length, void** data, int *kind) {
#if CYTHON_PEP393_ENABLED
361
    if (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return -1;
Stefan Behnel's avatar
Stefan Behnel committed
362
    *kind   = PyUnicode_KIND(ustring);
363 364 365 366 367 368 369 370 371 372
    *length = PyUnicode_GET_LENGTH(ustring);
    *data   = PyUnicode_DATA(ustring);
#else
    *kind   = 0;
    *length = PyUnicode_GET_SIZE(ustring);
    *data   = (void*)PyUnicode_AS_UNICODE(ustring);
#endif
    return 0;
}

373 374 375 376
/////////////// pyobject_as_double.proto ///////////////

static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */

377 378 379 380 381 382
#if CYTHON_COMPILING_IN_PYPY
#define __Pyx_PyObject_AsDouble(obj) \
(likely(PyFloat_CheckExact(obj)) ? PyFloat_AS_DOUBLE(obj) : \
 likely(PyInt_CheckExact(obj)) ? \
 PyFloat_AsDouble(obj) : __Pyx__PyObject_AsDouble(obj))
#else
Robert Bradshaw's avatar
Robert Bradshaw committed
383 384
#define __Pyx_PyObject_AsDouble(obj) \
((likely(PyFloat_CheckExact(obj))) ? \
385
 PyFloat_AS_DOUBLE(obj) : __Pyx__PyObject_AsDouble(obj))
386 387
#endif

388 389 390 391
/////////////// pyobject_as_double ///////////////

static double __Pyx__PyObject_AsDouble(PyObject* obj) {
    PyObject* float_value;
392 393 394
#if CYTHON_COMPILING_IN_PYPY
    float_value = PyNumber_Float(obj);
#else
395 396 397 398 399 400 401 402 403 404
    PyNumberMethods *nb = Py_TYPE(obj)->tp_as_number;
    if (likely(nb) && likely(nb->nb_float)) {
        float_value = nb->nb_float(obj);
        if (likely(float_value) && unlikely(!PyFloat_Check(float_value))) {
            PyErr_Format(PyExc_TypeError,
                "__float__ returned non-float (type %.200s)",
                Py_TYPE(float_value)->tp_name);
            Py_DECREF(float_value);
            goto bad;
        }
405 406 407 408 409 410 411 412 413 414 415 416 417 418
    } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) {
#if PY_MAJOR_VERSION >= 3
        float_value = PyFloat_FromString(obj);
#else
        float_value = PyFloat_FromString(obj, 0);
#endif
    } else {
        PyObject* args = PyTuple_New(1);
        if (unlikely(!args)) goto bad;
        PyTuple_SET_ITEM(args, 0, obj);
        float_value = PyObject_Call((PyObject*)&PyFloat_Type, args, 0);
        PyTuple_SET_ITEM(args, 0, 0);
        Py_DECREF(args);
    }
419
#endif
420 421 422 423 424 425 426 427
    if (likely(float_value)) {
        double value = PyFloat_AS_DOUBLE(float_value);
        Py_DECREF(float_value);
        return value;
    }
bad:
    return (double)-1;
}
428 429 430 431 432 433 434 435 436 437


/////////////// PyNumberPow2.proto ///////////////

#define __Pyx_PyNumber_InPlacePowerOf2(a, b, c) __Pyx__PyNumber_PowerOf2(a, b, c, 1)
#define __Pyx_PyNumber_PowerOf2(a, b, c) __Pyx__PyNumber_PowerOf2(a, b, c, 0)

static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace); /*proto*/

/////////////// PyNumberPow2 ///////////////
438
//@requires: TypeConversion.c::PyLongInternals
439 440 441

static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace) {
// in CPython, 1<<N is substantially faster than 2**N
442
// see http://bugs.python.org/issue21420
443 444
#if CYTHON_COMPILING_IN_CPYTHON
    Py_ssize_t shiftby;
445 446 447 448 449
#if PY_MAJOR_VERSION < 3
    if (likely(PyInt_CheckExact(exp))) {
        shiftby = PyInt_AS_LONG(exp);
    } else
#endif
450
    if (likely(PyLong_CheckExact(exp))) {
451
        #if CYTHON_USE_PYLONG_INTERNALS
452 453 454 455 456 457 458 459
        switch (Py_SIZE(exp)) {
            case  0: shiftby = 0; break;
            case  1: shiftby = ((PyLongObject*)exp)->ob_digit[0]; break;
            default:
                if (unlikely(Py_SIZE(exp) < 0)) goto fallback;
                shiftby = PyLong_AsSsize_t(exp); break;
        }
        #else
460
        shiftby = PyLong_AsSsize_t(exp);
461
        #endif
462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
    } else {
        goto fallback;
    }
    if (likely(shiftby >= 0)) {
        if ((size_t)shiftby <= sizeof(long) * 8 - 2) {
            long value = 1L << shiftby;
            return PyInt_FromLong(value);
        } else {
            PyObject *one = PyInt_FromLong(1L);
            if (unlikely(!one)) return NULL;
            return PyNumber_Lshift(one, exp);
        }
    } else if (shiftby == -1 && PyErr_Occurred()) {
        PyErr_Clear();
    }
fallback:
#endif
    return (inplace ? PyNumber_InPlacePower : PyNumber_Power)(two, exp, none);
}
481 482


483
/////////////// PyIntBinop.proto ///////////////
484

485
#if CYTHON_COMPILING_IN_CPYTHON
486
static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace); /*proto*/
487 488 489 490
#else
#define __Pyx_PyInt_{{op}}{{order}}(op1, op2, intval, inplace) \
    ((inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2))
#endif
491

492
/////////////// PyIntBinop ///////////////
493 494
//@requires: TypeConversion.c::PyLongInternals

495
#if CYTHON_COMPILING_IN_CPYTHON
496
{{py: from Cython.Utility import pylong_join }}
497
{{py: pyval, ival = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
498 499 500 501 502
{{py: slot_name = {'TrueDivide': 'true_divide', 'FloorDivide': 'floor_divide'}.get(op, op.lower()) }}
{{py:
c_op = {'Add': '+', 'Subtract': '-', 'Remainder': '%', 'TrueDivide': '/', 'FloorDivide': '/',
        'Or': '|', 'Xor': '^', 'And': '&', 'Rshift': '>>'}[op]
}}
503

Stefan Behnel's avatar
Stefan Behnel committed
504
static PyObject* __Pyx_PyInt_{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, int inplace) {
505 506
    #if PY_MAJOR_VERSION < 3
    if (likely(PyInt_CheckExact({{pyval}}))) {
Stefan Behnel's avatar
Stefan Behnel committed
507
        const long {{'a' if order == 'CObj' else 'b'}} = intval;
508
        {{if c_op in '+-%' or op == 'FloorDivide'}}
509 510 511 512
        long x;
        {{endif}}
        long {{ival}} = PyInt_AS_LONG({{pyval}});

Stefan Behnel's avatar
Stefan Behnel committed
513 514 515 516 517 518
        {{if c_op in '+-'}}
            // adapted from intobject.c in Py2.7:
            // casts in the line below avoid undefined behaviour on overflow
            x = (long)((unsigned long)a {{c_op}} b);
            if (likely((x^a) >= 0 || (x^{{ '~' if op == 'Subtract' else '' }}b) >= 0))
                return PyInt_FromLong(x);
519
            return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
520 521 522 523 524 525 526 527 528
        {{elif c_op == '%'}}
            // modulus with differing signs isn't safely portable, emulate CPython
            if (unlikely(a < 0)) {
                x = (-a) % b;
                if (x) x = b - x;
            } else {
                x = a % b;
            }
            return PyInt_FromLong(x);
529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552
        {{elif op == 'TrueDivide'}}
            if (8 * sizeof(long) <= 53 || likely({{ival}} <= (1L << 53) && {{ival}} >= (-(1L << 53)))) {
                return PyFloat_FromDouble((double)a / (double)b);
            }
            // let Python do the rounding
            return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
        {{elif op == 'FloorDivide'}}
            if ((a^b) >= 0) {
                {{if order == 'ObjC'}}
                // INT_MIN / -1  is the only case that overflows
                if (unlikely(b == -1 && ((unsigned long)a) == 0-(unsigned long)a))
                    return PyInt_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
                {{endif}}
                x = a / b;
            } else {
                // use manual rounding when result is negative (signs differ)
                long la = labs(a), lb = labs(b);
                x = la / lb;
                if (x * lb != la)
                    x = -x - 1;
                else
                    x = -x;
            }
            return PyInt_FromLong(x);
553
        {{else}}
Stefan Behnel's avatar
Stefan Behnel committed
554 555
            // other operations are safe, no overflow
            return PyInt_FromLong(a {{c_op}} b);
556
        {{endif}}
557 558 559
    }
    #endif

560
    #if CYTHON_USE_PYLONG_INTERNALS
561
    if (likely(PyLong_CheckExact({{pyval}}))) {
Stefan Behnel's avatar
Stefan Behnel committed
562
        const long {{'a' if order == 'CObj' else 'b'}} = intval;
563
        long x, {{ival}};
564
        const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
565 566 567
        const Py_ssize_t size = Py_SIZE({{pyval}});
        switch (size) {
            case  0: {{ival}} = 0; break;
568
            case -1: {{if c_op != '%'}}
569
                {{ival}} = -(sdigit)digits[0]; break;
570 571
                {{endif}}
                // fall through to positive calculation for '%'
572 573 574 575
            case  1: {{ival}} = digits[0]; break;
            {{for _size in (2, 3, 4)}}
            {{for _case in (-_size, _size)}}
            case {{_case}}: {{if c_op != '%' or _case > 0}}
576
                if (8 * sizeof(long) - 1 > {{_size}} * PyLong_SHIFT{{if op == 'TrueDivide'}} && {{_size-1}} * PyLong_SHIFT < 53{{endif}}) {
577
                    {{ival}} = {{'-' if _case < 0 else ''}}(long) {{pylong_join(_size, 'digits')}};
578 579 580
                    break;
                }
                {{endif}}
581
                // in negative case, fall through to positive calculation for '%' and '//'
Stefan Behnel's avatar
Stefan Behnel committed
582
                // if size doesn't fit into a long anymore, fall through to default
583 584
            {{endfor}}
            {{endfor}}
585
            default: return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
586
        }
587
        {{if c_op == '%'}}
588 589 590
            x = a % b;
            if (unlikely(size < 0) && x) {
                x = b - x;
591
            }
592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
        {{elif op == 'TrueDivide'}}
            if (8 * sizeof(long) <= 53 || (size >= -52 / PyLong_SHIFT && size <= 52 / PyLong_SHIFT) || likely({{ival}} <= (1L << 53) && {{ival}} >= (-(1L << 53)))) {
                return PyFloat_FromDouble((double)a / (double)b);
            }
            return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2);
        {{elif op == 'FloorDivide'}}
            if ((a^b) >= 0) {
                x = a / b;
            } else {
                // use manual rounding when result is negative (signs differ)
                long {{'la = %s(a), lb = %s(b)' % (('', 'labs') if order == 'ObjC' else ('labs', ''))}};
                x = la / lb;
                if (x * lb != la)
                    x = -x - 1;
                else
                    x = -x;
            }
609 610 611 612
        {{else}}
            x = a {{c_op}} b;
        {{endif}}
        return PyLong_FromLong(x);
613 614 615
    }
    #endif

616
    {{if c_op in '+-' or op == 'TrueDivide'}}
617
    if (PyFloat_CheckExact({{pyval}})) {
Stefan Behnel's avatar
Stefan Behnel committed
618
        const long {{'a' if order == 'CObj' else 'b'}} = intval;
619
        double result;
620
        double {{ival}} = PyFloat_AS_DOUBLE({{pyval}});
Stefan Behnel's avatar
Stefan Behnel committed
621
        // copied from floatobject.c in Py3.5:
622
        PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
623
        result = ((double)a) {{c_op}} (double)b;
624 625
        PyFPE_END_PROTECT(result)
        return PyFloat_FromDouble(result);
626
    }
627
    {{endif}}
628 629
    return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2);
}
630
#endif
631 632 633

/////////////// PyFloatBinop.proto ///////////////

634
#if CYTHON_COMPILING_IN_CPYTHON
635
static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace); /*proto*/
636 637 638 639
#else
#define __Pyx_PyFloat_{{op}}{{order}}(op1, op2, floatval, inplace) \
    ((inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2))
#endif
640 641 642 643

/////////////// PyFloatBinop ///////////////
//@requires: TypeConversion.c::PyLongInternals

644
#if CYTHON_COMPILING_IN_CPYTHON
645
{{py: from Cython.Utility import pylong_join }}
646
{{py: pyval, fval = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }}
647
{{py: c_op = {'Add': '+', 'Subtract': '-', 'TrueDivide': '/'}[op] }}
648

649
static PyObject* __Pyx_PyFloat_{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace) {
650
    const double {{'a' if order == 'CObj' else 'b'}} = floatval;
651
    double result, {{fval}};
652 653 654 655

    if (likely(PyFloat_CheckExact({{pyval}}))) {
        {{fval}} = PyFloat_AS_DOUBLE({{pyval}});
    } else
656

657 658 659 660 661
    #if PY_MAJOR_VERSION < 3
    if (likely(PyInt_CheckExact({{pyval}}))) {
        {{fval}} = (double) PyInt_AS_LONG({{pyval}});
    } else
    #endif
662

663
    if (likely(PyLong_CheckExact({{pyval}}))) {
664
        #if CYTHON_USE_PYLONG_INTERNALS
665
        const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
666 667
        const Py_ssize_t size = Py_SIZE({{pyval}});
        switch (size) {
668
            case  0: {{fval}} = 0.0; break;
669 670 671 672 673 674 675
            case -1: {{fval}} = -(double) digits[0]; break;
            case  1: {{fval}} = (double) digits[0]; break;
            {{for _size in (2, 3, 4)}}
            case -{{_size}}:
            case {{_size}}:
                if (8 * sizeof(unsigned long) > {{_size}} * PyLong_SHIFT && ((8 * sizeof(unsigned long) < 53) || ({{_size-1}} * PyLong_SHIFT < 53))) {
                    {{fval}} = (double) {{pylong_join(_size, 'digits')}};
Stefan Behnel's avatar
Stefan Behnel committed
676
                    // let CPython do its own float rounding from 2**53 on (max. consecutive integer in double float)
677 678
                    if ((8 * sizeof(unsigned long) < 53) || ({{_size}} * PyLong_SHIFT < 53) || ({{fval}} < (double) (1L<<53))) {
                        if (size == {{-_size}})
679
                            {{fval}} = -{{fval}};
680 681
                        break;
                    }
682
                }
Stefan Behnel's avatar
Stefan Behnel committed
683 684 685 686 687
                // Fall through if size doesn't fit safely into a double anymore.
                // It may not be obvious that this is a safe fall-through given the "fval < 2**53"
                // check above.  However, the number of digits that CPython uses for a given PyLong
                // value is minimal, and together with the "(size-1) * SHIFT < 53" check above,
                // this should make it safe.
688
            {{endfor}}
689 690 691
            default: {{fval}} = PyLong_AsDouble({{pyval}});
                if (unlikely({{fval}} == -1 && PyErr_Occurred())) return NULL;
                break;
692
        }
693 694
        #else
        {{fval}} = PyLong_AsDouble({{pyval}});
Stefan Behnel's avatar
Stefan Behnel committed
695
        if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL;
696
        #endif
Stefan Behnel's avatar
Stefan Behnel committed
697
    } else {
698
        return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2);
Stefan Behnel's avatar
Stefan Behnel committed
699
    }
700

Stefan Behnel's avatar
Stefan Behnel committed
701
    // copied from floatobject.c in Py3.5:
702
    PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL)
703
    result = a {{c_op}} b;
704 705
    PyFPE_END_PROTECT(result)
    return PyFloat_FromDouble(result);
706
}
707
#endif