Spaces:
Runtime error
Runtime error
| /* | |
| * 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. | |
| */ | |
| /////////////// append.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x); /*proto*/ | |
| /////////////// append /////////////// | |
| //@requires: ListAppend | |
| //@requires: ObjectHandling.c::PyObjectCallMethod1 | |
| static CYTHON_INLINE int __Pyx_PyObject_Append(PyObject* L, PyObject* x) { | |
| if (likely(PyList_CheckExact(L))) { | |
| if (unlikely(__Pyx_PyList_Append(L, x) < 0)) return -1; | |
| } else { | |
| PyObject* retval = __Pyx_PyObject_CallMethod1(L, PYIDENT("append"), x); | |
| if (unlikely(!retval)) | |
| return -1; | |
| Py_DECREF(retval); | |
| } | |
| return 0; | |
| } | |
| /////////////// ListAppend.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_PyList_Append(PyObject* list, PyObject* x) { | |
| PyListObject* L = (PyListObject*) list; | |
| Py_ssize_t len = Py_SIZE(list); | |
| if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) { | |
| Py_INCREF(x); | |
| PyList_SET_ITEM(list, len, x); | |
| __Pyx_SET_SIZE(list, len + 1); | |
| return 0; | |
| } | |
| return PyList_Append(list, x); | |
| } | |
| /////////////// ListCompAppend.proto /////////////// | |
| 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); | |
| __Pyx_SET_SIZE(list, len + 1); | |
| return 0; | |
| } | |
| return PyList_Append(list, x); | |
| } | |
| //////////////////// ListExtend.proto //////////////////// | |
| static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) { | |
| PyObject* none = _PyList_Extend((PyListObject*)L, v); | |
| if (unlikely(!none)) | |
| return -1; | |
| Py_DECREF(none); | |
| return 0; | |
| return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v); | |
| } | |
| /////////////// pop.proto /////////////// | |
| static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L); /*proto*/ | |
| static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L); /*proto*/ | |
| /////////////// pop /////////////// | |
| //@requires: ObjectHandling.c::PyObjectCallMethod0 | |
| static CYTHON_INLINE PyObject* __Pyx__PyObject_Pop(PyObject* L) { | |
| if (Py_TYPE(L) == &PySet_Type) { | |
| return PySet_Pop(L); | |
| } | |
| return __Pyx_PyObject_CallMethod0(L, PYIDENT("pop")); | |
| } | |
| static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) { | |
| /* 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))) { | |
| __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); | |
| return PyList_GET_ITEM(L, PyList_GET_SIZE(L)); | |
| } | |
| return CALL_UNBOUND_METHOD(PyList_Type, "pop", L); | |
| } | |
| /////////////// pop_index.proto /////////////// | |
| static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix); /*proto*/ | |
| static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix); /*proto*/ | |
| static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix); /*proto*/ | |
| /////////////// pop_index /////////////// | |
| //@requires: ObjectHandling.c::PyObjectCallMethod1 | |
| static PyObject* __Pyx__PyObject_PopNewIndex(PyObject* L, PyObject* py_ix) { | |
| PyObject *r; | |
| if (unlikely(!py_ix)) return NULL; | |
| r = __Pyx__PyObject_PopIndex(L, py_ix); | |
| Py_DECREF(py_ix); | |
| return r; | |
| } | |
| static PyObject* __Pyx__PyObject_PopIndex(PyObject* L, PyObject* py_ix) { | |
| return __Pyx_PyObject_CallMethod1(L, PYIDENT("pop"), py_ix); | |
| } | |
| static PyObject* __Pyx__PyList_PopIndex(PyObject* L, PyObject* py_ix, Py_ssize_t ix) { | |
| 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(__Pyx_is_valid_index(cix, size))) { | |
| PyObject* v = PyList_GET_ITEM(L, cix); | |
| __Pyx_SET_SIZE(L, Py_SIZE(L) - 1); | |
| size -= 1; | |
| memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), (size_t)(size-cix)*sizeof(PyObject*)); | |
| return v; | |
| } | |
| } | |
| if (py_ix == Py_None) { | |
| return __Pyx__PyObject_PopNewIndex(L, PyInt_FromSsize_t(ix)); | |
| } else { | |
| return __Pyx__PyObject_PopIndex(L, py_ix); | |
| } | |
| } | |
| /////////////// dict_getitem_default.proto /////////////// | |
| static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value); /*proto*/ | |
| /////////////// dict_getitem_default /////////////// | |
| static PyObject* __Pyx_PyDict_GetItemDefault(PyObject* d, PyObject* key, PyObject* default_value) { | |
| PyObject* value; | |
| value = PyDict_GetItemWithError(d, key); | |
| if (unlikely(!value)) { | |
| if (unlikely(PyErr_Occurred())) | |
| return NULL; | |
| value = default_value; | |
| } | |
| Py_INCREF(value); | |
| // avoid C compiler warning about unused utility functions | |
| if ((1)); | |
| 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 { | |
| if (default_value == Py_None) | |
| value = CALL_UNBOUND_METHOD(PyDict_Type, "get", d, key); | |
| else | |
| value = CALL_UNBOUND_METHOD(PyDict_Type, "get", d, key, default_value); | |
| } | |
| return value; | |
| } | |
| /////////////// dict_setdefault.proto /////////////// | |
| static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value, int is_safe_type); /*proto*/ | |
| /////////////// dict_setdefault /////////////// | |
| static CYTHON_INLINE PyObject *__Pyx_PyDict_SetDefault(PyObject *d, PyObject *key, PyObject *default_value, | |
| CYTHON_UNUSED int is_safe_type) { | |
| PyObject* value; | |
| // 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); | |
| if (is_safe_type == 1 || (is_safe_type == -1 && | |
| /* the following builtins presumably have repeatably safe and fast hash functions */ | |
| (PyUnicode_CheckExact(key) || PyString_CheckExact(key) || PyLong_CheckExact(key)))) { | |
| 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); | |
| (PyString_CheckExact(key) || PyUnicode_CheckExact(key) || PyInt_CheckExact(key) || PyLong_CheckExact(key)))) { | |
| 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); | |
| } else { | |
| value = CALL_UNBOUND_METHOD(PyDict_Type, "setdefault", d, key, default_value); | |
| } | |
| return value; | |
| } | |
| /////////////// py_dict_clear.proto /////////////// | |
| /////////////// py_dict_pop.proto /////////////// | |
| static CYTHON_INLINE PyObject *__Pyx_PyDict_Pop(PyObject *d, PyObject *key, PyObject *default_value); /*proto*/ | |
| /////////////// py_dict_pop /////////////// | |
| static CYTHON_INLINE PyObject *__Pyx_PyDict_Pop(PyObject *d, PyObject *key, PyObject *default_value) { | |
| if ((1)) { | |
| return _PyDict_Pop(d, key, default_value); | |
| } else | |
| // avoid "function unused" warnings | |
| if (default_value) { | |
| return CALL_UNBOUND_METHOD(PyDict_Type, "pop", d, key, default_value); | |
| } else { | |
| return CALL_UNBOUND_METHOD(PyDict_Type, "pop", d, key); | |
| } | |
| } | |
| /////////////// dict_iter.proto /////////////// | |
| 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); | |
| 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 | |
| //@requires: ObjectHandling.c::IterFinish | |
| //@requires: ObjectHandling.c::PyObjectCallMethod0 | |
| static CYTHON_INLINE PyObject* __Pyx_dict_iterator(PyObject* iterable, int is_dict, PyObject* method_name, | |
| 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; | |
| if (is_dict) { | |
| *p_orig_length = PyDict_Size(iterable); | |
| Py_INCREF(iterable); | |
| return iterable; | |
| // On PyPy3, we need to translate manually a few method names. | |
| // This logic is not needed on CPython thanks to the fast case above. | |
| static PyObject *py_items = NULL, *py_keys = NULL, *py_values = NULL; | |
| PyObject **pp = NULL; | |
| if (method_name) { | |
| const char *name = PyUnicode_AsUTF8(method_name); | |
| if (strcmp(name, "iteritems") == 0) pp = &py_items; | |
| else if (strcmp(name, "iterkeys") == 0) pp = &py_keys; | |
| else if (strcmp(name, "itervalues") == 0) pp = &py_values; | |
| if (pp) { | |
| if (!*pp) { | |
| *pp = PyUnicode_FromString(name + 4); | |
| if (!*pp) | |
| return NULL; | |
| } | |
| method_name = *pp; | |
| } | |
| } | |
| } | |
| *p_orig_length = 0; | |
| if (method_name) { | |
| PyObject* iter; | |
| iterable = __Pyx_PyObject_CallMethod0(iterable, method_name); | |
| if (!iterable) | |
| return NULL; | |
| if (PyTuple_CheckExact(iterable) || PyList_CheckExact(iterable)) | |
| return iterable; | |
| iter = PyObject_GetIter(iterable); | |
| Py_DECREF(iterable); | |
| return iter; | |
| } | |
| return PyObject_GetIter(iterable); | |
| } | |
| static CYTHON_INLINE int __Pyx_dict_iter_next( | |
| PyObject* iter_obj, CYTHON_NCP_UNUSED Py_ssize_t orig_length, CYTHON_NCP_UNUSED Py_ssize_t* ppos, | |
| PyObject** pkey, PyObject** pvalue, PyObject** pitem, int source_is_dict) { | |
| PyObject* next_item; | |
| if (source_is_dict) { | |
| PyObject *key, *value; | |
| if (unlikely(orig_length != PyDict_Size(iter_obj))) { | |
| PyErr_SetString(PyExc_RuntimeError, "dictionary changed size during iteration"); | |
| return -1; | |
| } | |
| if (unlikely(!PyDict_Next(iter_obj, ppos, &key, &value))) { | |
| 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; | |
| } 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 | |
| { | |
| next_item = PyIter_Next(iter_obj); | |
| if (unlikely(!next_item)) { | |
| return __Pyx_IterFinish(); | |
| } | |
| } | |
| if (pitem) { | |
| *pitem = next_item; | |
| } else if (pkey && pvalue) { | |
| if (__Pyx_unpack_tuple2(next_item, pkey, pvalue, source_is_dict, source_is_dict, 1)) | |
| return -1; | |
| } else if (pkey) { | |
| *pkey = next_item; | |
| } else { | |
| *pvalue = next_item; | |
| } | |
| return 1; | |
| } | |
| /////////////// set_iter.proto /////////////// | |
| static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set, | |
| Py_ssize_t* p_orig_length, int* p_source_is_set); /*proto*/ | |
| static CYTHON_INLINE int __Pyx_set_iter_next( | |
| PyObject* iter_obj, Py_ssize_t orig_length, | |
| Py_ssize_t* ppos, PyObject **value, | |
| int source_is_set); /*proto*/ | |
| /////////////// set_iter /////////////// | |
| //@requires: ObjectHandling.c::IterFinish | |
| static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set, | |
| Py_ssize_t* p_orig_length, int* p_source_is_set) { | |
| is_set = is_set || likely(PySet_CheckExact(iterable) || PyFrozenSet_CheckExact(iterable)); | |
| *p_source_is_set = is_set; | |
| if (likely(is_set)) { | |
| *p_orig_length = PySet_Size(iterable); | |
| Py_INCREF(iterable); | |
| return iterable; | |
| } | |
| (void)is_set; | |
| *p_source_is_set = 0; | |
| *p_orig_length = 0; | |
| return PyObject_GetIter(iterable); | |
| } | |
| static CYTHON_INLINE int __Pyx_set_iter_next( | |
| PyObject* iter_obj, Py_ssize_t orig_length, | |
| Py_ssize_t* ppos, PyObject **value, | |
| int source_is_set) { | |
| if (!CYTHON_COMPILING_IN_CPYTHON || unlikely(!source_is_set)) { | |
| *value = PyIter_Next(iter_obj); | |
| if (unlikely(!*value)) { | |
| return __Pyx_IterFinish(); | |
| } | |
| (void)orig_length; | |
| (void)ppos; | |
| return 1; | |
| } | |
| if (unlikely(PySet_GET_SIZE(iter_obj) != orig_length)) { | |
| PyErr_SetString( | |
| PyExc_RuntimeError, | |
| "set changed size during iteration"); | |
| return -1; | |
| } | |
| { | |
| Py_hash_t hash; | |
| int ret = _PySet_NextEntry(iter_obj, ppos, value, &hash); | |
| // CPython does not raise errors here, only if !isinstance(iter_obj, set/frozenset) | |
| assert (ret != -1); | |
| if (likely(ret)) { | |
| Py_INCREF(*value); | |
| return 1; | |
| } | |
| } | |
| return 0; | |
| } | |
| /////////////// py_set_discard_unhashable /////////////// | |
| //@requires: Builtins.c::pyfrozenset_new | |
| static int __Pyx_PySet_DiscardUnhashable(PyObject *set, PyObject *key) { | |
| PyObject *tmpkey; | |
| int rv; | |
| if (likely(!PySet_Check(key) || !PyErr_ExceptionMatches(PyExc_TypeError))) | |
| return -1; | |
| PyErr_Clear(); | |
| tmpkey = __Pyx_PyFrozenSet_New(key); | |
| if (tmpkey == NULL) | |
| return -1; | |
| rv = PySet_Discard(set, tmpkey); | |
| Py_DECREF(tmpkey); | |
| return rv; | |
| } | |
| /////////////// py_set_discard.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_PySet_Discard(PyObject *set, PyObject *key); /*proto*/ | |
| /////////////// py_set_discard /////////////// | |
| //@requires: py_set_discard_unhashable | |
| static CYTHON_INLINE int __Pyx_PySet_Discard(PyObject *set, PyObject *key) { | |
| int found = PySet_Discard(set, key); | |
| // Convert *key* to frozenset if necessary | |
| if (unlikely(found < 0)) { | |
| found = __Pyx_PySet_DiscardUnhashable(set, key); | |
| } | |
| // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works | |
| return found; | |
| } | |
| /////////////// py_set_remove.proto /////////////// | |
| static CYTHON_INLINE int __Pyx_PySet_Remove(PyObject *set, PyObject *key); /*proto*/ | |
| /////////////// py_set_remove /////////////// | |
| //@requires: py_set_discard_unhashable | |
| static int __Pyx_PySet_RemoveNotFound(PyObject *set, PyObject *key, int found) { | |
| // Convert *key* to frozenset if necessary | |
| if (unlikely(found < 0)) { | |
| found = __Pyx_PySet_DiscardUnhashable(set, key); | |
| } | |
| if (likely(found == 0)) { | |
| // Not found | |
| PyObject *tup; | |
| tup = PyTuple_Pack(1, key); | |
| if (!tup) | |
| return -1; | |
| PyErr_SetObject(PyExc_KeyError, tup); | |
| Py_DECREF(tup); | |
| return -1; | |
| } | |
| // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works | |
| return found; | |
| } | |
| static CYTHON_INLINE int __Pyx_PySet_Remove(PyObject *set, PyObject *key) { | |
| int found = PySet_Discard(set, key); | |
| if (unlikely(found != 1)) { | |
| // note: returns -1 on error, 0 (not found) or 1 (found) otherwise => error check for -1 or < 0 works | |
| return __Pyx_PySet_RemoveNotFound(set, key, found); | |
| } | |
| return 0; | |
| } | |
| /////////////// 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 (unlikely(__Pyx_PyUnicode_READY(ustring) < 0)) return -1; | |
| *kind = PyUnicode_KIND(ustring); | |
| *length = PyUnicode_GET_LENGTH(ustring); | |
| *data = PyUnicode_DATA(ustring); | |
| *kind = 0; | |
| *length = PyUnicode_GET_SIZE(ustring); | |
| *data = (void*)PyUnicode_AS_UNICODE(ustring); | |
| return 0; | |
| } | |
| /////////////// pyobject_as_double.proto /////////////// | |
| static double __Pyx__PyObject_AsDouble(PyObject* obj); /* proto */ | |
| /////////////// pyobject_as_double /////////////// | |
| static double __Pyx__PyObject_AsDouble(PyObject* obj) { | |
| PyObject* float_value; | |
| float_value = PyNumber_Float(obj); if ((0)) goto bad; | |
| 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; | |
| } | |
| } else if (PyUnicode_CheckExact(obj) || PyBytes_CheckExact(obj)) { | |
| float_value = PyFloat_FromString(obj); | |
| float_value = PyFloat_FromString(obj, 0); | |
| } 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); | |
| } | |
| if (likely(float_value)) { | |
| double value = PyFloat_AS_DOUBLE(float_value); | |
| Py_DECREF(float_value); | |
| return value; | |
| } | |
| bad: | |
| return (double)-1; | |
| } | |
| /////////////// PyNumberPow2.proto /////////////// | |
| static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace); /*proto*/ | |
| /////////////// PyNumberPow2 /////////////// | |
| static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject *none, int inplace) { | |
| // in CPython, 1<<N is substantially faster than 2**N | |
| // see http://bugs.python.org/issue21420 | |
| Py_ssize_t shiftby; | |
| if (likely(PyInt_CheckExact(exp))) { | |
| shiftby = PyInt_AS_LONG(exp); | |
| } else | |
| if (likely(PyLong_CheckExact(exp))) { | |
| const Py_ssize_t size = Py_SIZE(exp); | |
| // tuned to optimise branch prediction | |
| if (likely(size == 1)) { | |
| shiftby = ((PyLongObject*)exp)->ob_digit[0]; | |
| } else if (size == 0) { | |
| return PyInt_FromLong(1L); | |
| } else if (unlikely(size < 0)) { | |
| goto fallback; | |
| } else { | |
| shiftby = PyLong_AsSsize_t(exp); | |
| } | |
| shiftby = PyLong_AsSsize_t(exp); | |
| } else { | |
| goto fallback; | |
| } | |
| if (likely(shiftby >= 0)) { | |
| if ((size_t)shiftby <= sizeof(long) * 8 - 2) { | |
| long value = 1L << shiftby; | |
| return PyInt_FromLong(value); | |
| } else if ((size_t)shiftby <= sizeof(unsigned PY_LONG_LONG) * 8 - 1) { | |
| unsigned PY_LONG_LONG value = ((unsigned PY_LONG_LONG)1) << shiftby; | |
| return PyLong_FromUnsignedLongLong(value); | |
| } else { | |
| PyObject *result, *one = PyInt_FromLong(1L); | |
| if (unlikely(!one)) return NULL; | |
| result = PyNumber_Lshift(one, exp); | |
| Py_DECREF(one); | |
| return result; | |
| } | |
| } else if (shiftby == -1 && PyErr_Occurred()) { | |
| PyErr_Clear(); | |
| } | |
| fallback: | |
| return (inplace ? PyNumber_InPlacePower : PyNumber_Power)(two, exp, none); | |
| } | |
| /////////////// PyIntCompare.proto /////////////// | |
| {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} | |
| static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, long inplace); /*proto*/ | |
| /////////////// PyIntCompare /////////////// | |
| {{py: pyval, ival = ('op2', 'b') if order == 'CObj' else ('op1', 'a') }} | |
| {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} | |
| {{py: return_true = 'Py_RETURN_TRUE' if ret_type.is_pyobject else 'return 1'}} | |
| {{py: return_false = 'Py_RETURN_FALSE' if ret_type.is_pyobject else 'return 0'}} | |
| {{py: slot_name = op.lower() }} | |
| {{py: c_op = {'Eq': '==', 'Ne': '!='}[op] }} | |
| {{py: | |
| return_compare = ( | |
| (lambda a,b,c_op, return_true=return_true, return_false=return_false: "if ({a} {c_op} {b}) {return_true}; else {return_false};".format( | |
| a=a, b=b, c_op=c_op, return_true=return_true, return_false=return_false)) | |
| if ret_type.is_pyobject else | |
| (lambda a,b,c_op: "return ({a} {c_op} {b});".format(a=a, b=b, c_op=c_op)) | |
| ) | |
| }} | |
| static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, CYTHON_UNUSED long intval, CYTHON_UNUSED long inplace) { | |
| if (op1 == op2) { | |
| {{return_true if op == 'Eq' else return_false}}; | |
| } | |
| if (likely(PyInt_CheckExact({{pyval}}))) { | |
| const long {{'a' if order == 'CObj' else 'b'}} = intval; | |
| long {{ival}} = PyInt_AS_LONG({{pyval}}); | |
| {{return_compare('a', 'b', c_op)}} | |
| } | |
| if (likely(PyLong_CheckExact({{pyval}}))) { | |
| int unequal; | |
| unsigned long uintval; | |
| Py_ssize_t size = Py_SIZE({{pyval}}); | |
| const digit* digits = ((PyLongObject*){{pyval}})->ob_digit; | |
| if (intval == 0) { | |
| // == 0 => Py_SIZE(pyval) == 0 | |
| {{return_compare('size', '0', c_op)}} | |
| } else if (intval < 0) { | |
| // < 0 => Py_SIZE(pyval) < 0 | |
| if (size >= 0) | |
| {{return_false if op == 'Eq' else return_true}}; | |
| // both are negative => can use absolute values now. | |
| intval = -intval; | |
| size = -size; | |
| } else { | |
| // > 0 => Py_SIZE(pyval) > 0 | |
| if (size <= 0) | |
| {{return_false if op == 'Eq' else return_true}}; | |
| } | |
| // After checking that the sign is the same (and excluding 0), now compare the absolute values. | |
| // When inlining, the C compiler should select exactly one line from this unrolled loop. | |
| uintval = (unsigned long) intval; | |
| {{for _size in range(4, 0, -1)}} | |
| if (uintval >> (PyLong_SHIFT * {{_size}})) { | |
| // The C integer value is between (PyLong_BASE ** _size) and MIN(PyLong_BASE ** _size, LONG_MAX). | |
| unequal = (size != {{_size+1}}) || (digits[0] != (uintval & (unsigned long) PyLong_MASK)) | |
| {{for _i in range(1, _size+1)}} | (digits[{{_i}}] != ((uintval >> ({{_i}} * PyLong_SHIFT)) & (unsigned long) PyLong_MASK)){{endfor}}; | |
| } else | |
| {{endfor}} | |
| unequal = (size != 1) || (((unsigned long) digits[0]) != (uintval & (unsigned long) PyLong_MASK)); | |
| {{return_compare('unequal', '0', c_op)}} | |
| } | |
| if (PyFloat_CheckExact({{pyval}})) { | |
| const long {{'a' if order == 'CObj' else 'b'}} = intval; | |
| double {{ival}} = PyFloat_AS_DOUBLE({{pyval}}); | |
| {{return_compare('(double)a', '(double)b', c_op)}} | |
| } | |
| return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( | |
| PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); | |
| } | |
| /////////////// PyIntBinop.proto /////////////// | |
| {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} | |
| static {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, long intval, int inplace, int zerodivision_check); /*proto*/ | |
| CYTHON_FALLTHROUGH; | |
| {{endfor}} | |
| {{endfor}} | |
| {{if op in ('Eq', 'Ne')}} | |
| // unusual setup - your fault | |
| default: return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( | |
| PyLong_Type.tp_richcompare({{'op1, op2' if order == 'ObjC' else 'op2, op1'}}, Py_{{op.upper()}})); | |
| // too large for the long values we allow => definitely not equal | |
| default: {{return_false if op == 'Eq' else return_true}}; | |
| {{else}} | |
| default: return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); | |
| {{endif}} | |
| } | |
| } | |
| {{if op in ('Eq', 'Ne')}} | |
| if (a {{c_op}} b) { | |
| {{return_true}}; | |
| } else { | |
| {{return_false}}; | |
| } | |
| {{else}} | |
| {{if c_op == '%'}} | |
| {{zerodiv_check('b')}} | |
| // see ExprNodes.py :: mod_int_utility_code | |
| x = a % b; | |
| x += ((x != 0) & ((x ^ b) < 0)) * b; | |
| {{elif op == 'TrueDivide'}} | |
| {{zerodiv_check('b')}} | |
| if ((8 * sizeof(long) <= 53 || likely(labs({{ival}}) <= ((PY_LONG_LONG)1 << 53))) | |
| || __Pyx_sst_abs(size) <= 52 / PyLong_SHIFT) { | |
| return PyFloat_FromDouble((double)a / (double)b); | |
| } | |
| return PyLong_Type.tp_as_number->nb_{{slot_name}}(op1, op2); | |
| {{elif op == 'FloorDivide'}} | |
| {{zerodiv_check('b')}} | |
| { | |
| long q, r; | |
| // see ExprNodes.py :: div_int_utility_code | |
| q = a / b; | |
| r = a - q*b; | |
| q -= ((r != 0) & ((r ^ b) < 0)); | |
| x = q; | |
| } | |
| {{else}} | |
| x = a {{c_op}} b; | |
| {{if op == 'Lshift'}} | |
| if (unlikely(!(b < (long) (sizeof(long)*8) && a == x >> b)) && a) { | |
| ll{{ival}} = {{ival}}; | |
| goto long_long; | |
| } | |
| if (likely(b < (long) (sizeof(long)*8) && a == x >> b) || !a) /* execute return statement below */ | |
| {{endif}} | |
| {{endif}} | |
| return PyLong_FromLong(x); | |
| {{if op != 'TrueDivide'}} | |
| long_long: | |
| {{if c_op == '%'}} | |
| // see ExprNodes.py :: mod_int_utility_code | |
| llx = lla % llb; | |
| llx += ((llx != 0) & ((llx ^ llb) < 0)) * llb; | |
| {{elif op == 'FloorDivide'}} | |
| { | |
| PY_LONG_LONG q, r; | |
| // see ExprNodes.py :: div_int_utility_code | |
| q = lla / llb; | |
| r = lla - q*llb; | |
| q -= ((r != 0) & ((r ^ llb) < 0)); | |
| llx = q; | |
| } | |
| {{else}} | |
| llx = lla {{c_op}} llb; | |
| {{if op == 'Lshift'}} | |
| if (likely(lla == llx >> llb)) /* then execute 'return' below */ | |
| {{endif}} | |
| {{endif}} | |
| return PyLong_FromLongLong(llx); | |
| {{endif}}{{ | |
| {{endif}}{{ | |
| } | |
| {{if c_op in '+-' or op in ('TrueDivide', 'Eq', 'Ne')}} | |
| if (PyFloat_CheckExact({{pyval}})) { | |
| const long {{'a' if order == 'CObj' else 'b'}} = intval; | |
| double {{ival}} = PyFloat_AS_DOUBLE({{pyval}}); | |
| {{if op in ('Eq', 'Ne')}} | |
| if ((double)a {{c_op}} (double)b) { | |
| {{return_true}}; | |
| } else { | |
| {{return_false}}; | |
| } | |
| {{else}} | |
| double result; | |
| {{if op == 'TrueDivide'}} | |
| if (unlikely(zerodivision_check && b == 0)) { | |
| PyErr_SetString(PyExc_ZeroDivisionError, "float division by zero"); | |
| return NULL; | |
| } | |
| {{endif}} | |
| // copied from floatobject.c in Py3.5: | |
| PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL) | |
| result = ((double)a) {{c_op}} (double)b; | |
| PyFPE_END_PROTECT(result) | |
| return PyFloat_FromDouble(result); | |
| {{endif}} | |
| } | |
| {{endif}} | |
| {{if op in ('Eq', 'Ne')}} | |
| return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( | |
| PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); | |
| {{else}} | |
| return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2); | |
| {{endif}} | |
| } | |
| /////////////// PyFloatBinop.proto /////////////// | |
| {{py: c_ret_type = 'PyObject*' if ret_type.is_pyobject else 'int'}} | |
| static {{c_ret_type}} __Pyx_PyFloat_{{'' if ret_type.is_pyobject else 'Bool'}}{{op}}{{order}}(PyObject *op1, PyObject *op2, double floatval, int inplace, int zerodivision_check); /*proto*/ | |
| // 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. | |
| CYTHON_FALLTHROUGH; | |
| {{endfor}} | |
| default: | |
| { | |
| {{if op in ('Eq', 'Ne')}} | |
| return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( | |
| PyFloat_Type.tp_richcompare({{'op1, op2' if order == 'CObj' else 'op2, op1'}}, Py_{{op.upper()}})); | |
| {{else}} | |
| {{fval}} = PyLong_AsDouble({{pyval}}); | |
| if (unlikely({{fval}} == -1.0 && PyErr_Occurred())) return NULL; | |
| {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check(fval)}}{{endif}} | |
| {{endif}} | |
| } | |
| } else { | |
| {{if op in ('Eq', 'Ne')}} | |
| return {{'' if ret_type.is_pyobject else '__Pyx_PyObject_IsTrueAndDecref'}}( | |
| PyObject_RichCompare(op1, op2, Py_{{op.upper()}})); | |
| {{elif op == 'Divide'}} | |
| return (inplace ? __Pyx_PyNumber_InPlaceDivide(op1, op2) : __Pyx_PyNumber_Divide(op1, op2)); | |
| {{else}} | |
| return (inplace ? PyNumber_InPlace{{op}} : PyNumber_{{op}})(op1, op2); | |
| {{endif}} | |
| } | |
| {{if op in ('Eq', 'Ne')}} | |
| if (a {{c_op}} b) { | |
| {{return_true}}; | |
| } else { | |
| {{return_false}}; | |
| } | |
| {{else}} | |
| // copied from floatobject.c in Py3.5: | |
| {{if order == 'CObj' and c_op in '%/'}}{{zerodiv_check('b')}}{{endif}} | |
| PyFPE_START_PROTECT("{{op.lower() if not op.endswith('Divide') else 'divide'}}", return NULL) | |
| {{if c_op == '%'}} | |
| result = fmod(a, b); | |
| if (result) | |
| result += ((result < 0) ^ (b < 0)) * b; | |
| else | |
| result = copysign(0.0, b); | |
| {{else}} | |
| result = a {{c_op}} b; | |
| {{endif}} | |
| PyFPE_END_PROTECT(result) | |
| return PyFloat_FromDouble(result); | |
| {{endif}} | |
| } | |