diff --git a/src/csrc/casts.cpp b/src/csrc/casts.cpp index 8f15e46..9370e79 100644 --- a/src/csrc/casts.cpp +++ b/src/csrc/casts.cpp @@ -15,6 +15,7 @@ extern "C" { } #include #include +#include #include #include "sleef.h" #include "sleefquad.h" @@ -240,10 +241,13 @@ unicode_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMet PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + if (!PyArray_ISNBO(given_descrs[0]->byteorder)) { loop_descrs[0] = PyArray_DescrNewByteorder(given_descrs[0], NPY_NATIVE); if (loop_descrs[0] == nullptr) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -254,8 +258,7 @@ unicode_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMet if (given_descrs[1] == NULL) { loop_descrs[1] = (PyArray_Descr *)new_quaddtype_instance(BACKEND_SLEEF); if (loop_descrs[1] == nullptr) { - Py_DECREF(loop_descrs[0]); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -350,6 +353,9 @@ quad_to_unicode_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMet PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + npy_intp required_size_chars = QUAD_STR_WIDTH; npy_intp required_size_bytes = required_size_chars * 4; // UCS4 = 4 bytes per char @@ -360,8 +366,7 @@ quad_to_unicode_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMet // Create descriptor with required size PyArray_Descr *unicode_descr = PyArray_DescrNewFromType(NPY_UNICODE); if (unicode_descr == nullptr) { - Py_DECREF(loop_descrs[0]); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } unicode_descr->elsize = required_size_bytes; @@ -373,8 +378,7 @@ quad_to_unicode_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMet if (!PyArray_ISNBO(given_descrs[1]->byteorder)) { loop_descrs[1] = PyArray_DescrNewByteorder(given_descrs[1], NPY_NATIVE); if (loop_descrs[1] == nullptr) { - Py_DECREF(loop_descrs[0]); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -545,6 +549,9 @@ bytes_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + // Bytes dtype doesn't have byte order concerns like Unicode Py_INCREF(given_descrs[0]); loop_descrs[0] = given_descrs[0]; @@ -552,8 +559,7 @@ bytes_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta if (given_descrs[1] == NULL) { loop_descrs[1] = (PyArray_Descr *)new_quaddtype_instance(BACKEND_SLEEF); if (loop_descrs[1] == nullptr) { - Py_DECREF(loop_descrs[0]); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -650,12 +656,15 @@ quad_to_bytes_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + npy_intp required_size_bytes = QUAD_STR_WIDTH; if (given_descrs[1] == NULL) { PyArray_Descr *new_descr = PyArray_DescrNewFromType(NPY_STRING); if (new_descr == NULL) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } new_descr->elsize = required_size_bytes; loop_descrs[1] = new_descr; @@ -731,10 +740,13 @@ stringdtype_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTyp PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + if (given_descrs[1] == NULL) { loop_descrs[1] = (PyArray_Descr *)new_quaddtype_instance(BACKEND_SLEEF); if (loop_descrs[1] == nullptr) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -813,12 +825,15 @@ quad_to_stringdtype_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTyp PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + if (given_descrs[1] == NULL) { // Default StringDType() already has coerce=True loop_descrs[1] = (PyArray_Descr *)PyObject_CallNoArgs( (PyObject *)&PyArray_StringDType); if (loop_descrs[1] == NULL) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -1164,11 +1179,14 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + // todo: here it is converting this to SLEEF, losing data and getting 0 if (given_descrs[1] == NULL) { loop_descrs[1] = (PyArray_Descr *)new_quaddtype_instance(BACKEND_SLEEF); if (loop_descrs[1] == nullptr) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } } else { @@ -1177,6 +1195,9 @@ numpy_to_quad_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta } loop_descrs[0] = PyArray_GetDefaultDescr(dtypes[0]); + if (loop_descrs[0] == nullptr) { + return quad_resolve_descrs_fail(loop_descrs, 2); + } // since QUAD precision is the highest precision, we can always cast to it return static_cast(NPY_SAFE_CASTING | NPY_SAME_VALUE_CASTING_FLAG); } @@ -1485,10 +1506,16 @@ quad_to_numpy_resolve_descriptors(PyObject *NPY_UNUSED(self), PyArray_DTypeMeta PyArray_Descr *given_descrs[2], PyArray_Descr *loop_descrs[2], npy_intp *view_offset) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + Py_INCREF(given_descrs[0]); loop_descrs[0] = given_descrs[0]; loop_descrs[1] = PyArray_GetDefaultDescr(dtypes[1]); + if (loop_descrs[1] == nullptr) { + return quad_resolve_descrs_fail(loop_descrs, 2); + } // For floating-point types: same_kind casting (precision loss but same kind) if constexpr (is_float_type::value) { return static_cast(NPY_SAME_KIND_CASTING | NPY_SAME_VALUE_CASTING_FLAG); @@ -1802,7 +1829,7 @@ init_casts(void) try { return init_casts_internal(); } - catch (int e) { + catch (const std::bad_alloc &) { PyErr_NoMemory(); return nullptr; } diff --git a/src/csrc/dtype.c b/src/csrc/dtype.c index 67ba982..cfe654f 100644 --- a/src/csrc/dtype.c +++ b/src/csrc/dtype.c @@ -628,8 +628,7 @@ QuadPrecDType_new(PyTypeObject *NPY_UNUSED(cls), PyObject *args, PyObject *kwds) return NULL; } - return (PyObject *)quadprec_discover_descriptor_from_pyobject( - &QuadPrecDType, (PyObject *)QuadPrecision_raw_new(backend)); + return (PyObject *)new_quaddtype_instance(backend); } static PyObject * @@ -707,10 +706,12 @@ init_quadprec_dtype(void) ((PyTypeObject *)&QuadPrecDType)->tp_base = &PyArrayDescr_Type; if (PyType_Ready((PyTypeObject *)&QuadPrecDType) < 0) { + free_casts(); return -1; } if (PyArrayInitDTypeMeta_FromSpec(&QuadPrecDType, &QuadPrecDType_DTypeSpec) < 0) { + free_casts(); return -1; } diff --git a/src/csrc/lock.c b/src/csrc/lock.c index 929966b..850bbc2 100644 --- a/src/csrc/lock.c +++ b/src/csrc/lock.c @@ -6,12 +6,14 @@ PyThread_type_lock sleef_lock = NULL; PyMutex sleef_lock = {0}; #endif -void init_sleef_locks(void) +int init_sleef_locks(void) { #if PY_VERSION_HEX < 0x30d00b3 sleef_lock = PyThread_allocate_lock(); if (!sleef_lock) { PyErr_NoMemory(); + return -1; } #endif + return 0; } \ No newline at end of file diff --git a/src/csrc/quaddtype_main.c b/src/csrc/quaddtype_main.c index c15b864..58b37f4 100644 --- a/src/csrc/quaddtype_main.c +++ b/src/csrc/quaddtype_main.c @@ -102,18 +102,19 @@ PyInit__quaddtype_main(void) PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED); #endif - init_sleef_locks(); + if (init_sleef_locks() < 0) + goto error; if (init_quadprecision_scalar() < 0) goto error; - if (PyModule_AddObject(m, "QuadPrecision", (PyObject *)&QuadPrecision_Type) < 0) + if (PyModule_AddObjectRef(m, "QuadPrecision", (PyObject *)&QuadPrecision_Type) < 0) goto error; if (init_quadprec_dtype() < 0) goto error; - if (PyModule_AddObject(m, "QuadPrecDType", (PyObject *)&QuadPrecDType) < 0) + if (PyModule_AddObjectRef(m, "QuadPrecDType", (PyObject *)&QuadPrecDType) < 0) goto error; if (init_quad_umath() < 0) { diff --git a/src/csrc/scalar.c b/src/csrc/scalar.c index 86cb49e..13f5ff8 100644 --- a/src/csrc/scalar.c +++ b/src/csrc/scalar.c @@ -200,6 +200,10 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend) } else if (PyUnicode_Check(value)) { const char *s = PyUnicode_AsUTF8(value); + if (s == NULL) { + Py_DECREF(self); + return NULL; + } char *endptr = NULL; int err = NumPyOS_ascii_strtoq(s, backend, &self->value, &endptr); if (err < 0) { @@ -248,6 +252,9 @@ QuadPrecision_from_object(PyObject *value, QuadBackendType backend) QuadPrecisionObject *quad_obj = (QuadPrecisionObject *)value; // create a new one with the same backend QuadPrecisionObject *self = QuadPrecision_raw_new(quad_obj->backend); + if (self == NULL) { + return NULL; + } if (quad_obj->backend == BACKEND_SLEEF) { self->value.sleef_value = quad_obj->value.sleef_value; } @@ -620,7 +627,10 @@ QuadPrecision_as_integer_ratio(QuadPrecisionObject *self, PyObject *Py_UNUSED(ig } Py_DECREF(py_exp); - return PyTuple_Pack(2, numerator, denominator); + PyObject *ratio = PyTuple_Pack(2, numerator, denominator); + Py_DECREF(numerator); + Py_DECREF(denominator); + return ratio; } static int diff --git a/src/csrc/scalar_ops.cpp b/src/csrc/scalar_ops.cpp index 8690658..33cf624 100644 --- a/src/csrc/scalar_ops.cpp +++ b/src/csrc/scalar_ops.cpp @@ -78,6 +78,7 @@ quad_binary_func(PyObject *op1, PyObject *op2) other_quad = (QuadPrecisionObject *)other; if (other_quad->backend != backend) { PyErr_SetString(PyExc_TypeError, "Cannot mix QuadPrecision backends"); + Py_DECREF(other_quad); Py_DECREF(other); return NULL; } diff --git a/src/csrc/umath/binary_ops.cpp b/src/csrc/umath/binary_ops.cpp index 9f27ee6..588a3f7 100644 --- a/src/csrc/umath/binary_ops.cpp +++ b/src/csrc/umath/binary_ops.cpp @@ -26,6 +26,10 @@ quad_binary_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtyp PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + QuadPrecDTypeObject *descr_in1 = (QuadPrecDTypeObject *)given_descrs[0]; QuadPrecDTypeObject *descr_in2 = (QuadPrecDTypeObject *)given_descrs[1]; QuadBackendType target_backend; @@ -45,7 +49,7 @@ quad_binary_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtyp if (((QuadPrecDTypeObject *)given_descrs[i])->backend != target_backend) { loop_descrs[i] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[i]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { @@ -58,7 +62,7 @@ quad_binary_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtyp if (given_descrs[2] == NULL) { loop_descrs[2] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { @@ -66,7 +70,7 @@ quad_binary_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtyp if (descr_out->backend != target_backend) { loop_descrs[2] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { @@ -151,6 +155,10 @@ quad_binary_op_2out_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 4; i++) { + loop_descrs[i] = NULL; + } + QuadPrecDTypeObject *descr_in1 = (QuadPrecDTypeObject *)given_descrs[0]; QuadPrecDTypeObject *descr_in2 = (QuadPrecDTypeObject *)given_descrs[1]; QuadBackendType target_backend; @@ -170,7 +178,7 @@ quad_binary_op_2out_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const if (((QuadPrecDTypeObject *)given_descrs[i])->backend != target_backend) { loop_descrs[i] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[i]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 4); } } else { @@ -184,7 +192,7 @@ quad_binary_op_2out_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const if (given_descrs[i] == NULL) { loop_descrs[i] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[i]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 4); } } else { @@ -192,7 +200,7 @@ quad_binary_op_2out_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const if (descr_out->backend != target_backend) { loop_descrs[i] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[i]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 4); } } else { @@ -288,6 +296,10 @@ quad_ldexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[] PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + QuadPrecDTypeObject *descr_in1 = (QuadPrecDTypeObject *)given_descrs[0]; QuadBackendType target_backend = descr_in1->backend; @@ -297,19 +309,22 @@ quad_ldexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[] // Input 1: Use NPY_INTP to match the registered PyArray_IntpDType loop_descrs[1] = PyArray_DescrFromType(NPY_INTP); + if (!loop_descrs[1]) { + return quad_resolve_descrs_fail(loop_descrs, 3); + } // Output: QuadPrecDType with same backend as input if (given_descrs[2] == NULL) { loop_descrs[2] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { QuadPrecDTypeObject *descr_out = (QuadPrecDTypeObject *)given_descrs[2]; if (descr_out->backend != target_backend) { loop_descrs[2] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { Py_INCREF(given_descrs[2]); diff --git a/src/csrc/umath/comparison_ops.cpp b/src/csrc/umath/comparison_ops.cpp index 9924bd3..a2ad501 100644 --- a/src/csrc/umath/comparison_ops.cpp +++ b/src/csrc/umath/comparison_ops.cpp @@ -29,6 +29,10 @@ quad_comparison_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + QuadPrecDTypeObject *descr_in1 = (QuadPrecDTypeObject *)given_descrs[0]; QuadPrecDTypeObject *descr_in2 = (QuadPrecDTypeObject *)given_descrs[1]; QuadBackendType target_backend; @@ -48,7 +52,7 @@ quad_comparison_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const if (((QuadPrecDTypeObject *)given_descrs[i])->backend != target_backend) { loop_descrs[i] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[i]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { @@ -60,7 +64,7 @@ quad_comparison_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const // Set up output descriptor loop_descrs[2] = PyArray_DescrFromType(NPY_BOOL); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } return casting; } @@ -152,6 +156,10 @@ quad_comparison_reduce_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *co PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + NPY_CASTING casting = NPY_SAFE_CASTING; for (int i = 0; i < 2; i++) { @@ -162,7 +170,7 @@ quad_comparison_reduce_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *co // Set up output descriptor loop_descrs[2] = PyArray_DescrFromType(NPY_BOOL); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } return casting; } diff --git a/src/csrc/umath/matmul.cpp b/src/csrc/umath/matmul.cpp index 6d4b5de..6cd9533 100644 --- a/src/csrc/umath/matmul.cpp +++ b/src/csrc/umath/matmul.cpp @@ -31,6 +31,10 @@ quad_matmul_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[ PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + QuadPrecDTypeObject *descr_in1 = (QuadPrecDTypeObject *)given_descrs[0]; QuadPrecDTypeObject *descr_in2 = (QuadPrecDTypeObject *)given_descrs[1]; @@ -39,7 +43,7 @@ quad_matmul_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[ PyErr_SetString(PyExc_NotImplementedError, "QBLAS-accelerated matmul only supports SLEEF backend. " "Please raise the issue at SwayamInSync/QBLAS for longdouble support"); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } // Both inputs must use SLEEF backend @@ -56,7 +60,7 @@ quad_matmul_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[ if (given_descrs[2] == NULL) { loop_descrs[2] = (PyArray_Descr *)new_quaddtype_instance(target_backend); if (!loop_descrs[2]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } } else { @@ -65,7 +69,7 @@ quad_matmul_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[ PyErr_SetString(PyExc_NotImplementedError, "QBLAS-accelerated matmul only supports SLEEF backend. " "Please raise the issue at SwayamInSync/QBLAS for longdouble support"); - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 3); } else { Py_INCREF(given_descrs[2]); diff --git a/src/csrc/umath/unary_ops.cpp b/src/csrc/umath/unary_ops.cpp index 7061294..2fbc9e8 100644 --- a/src/csrc/umath/unary_ops.cpp +++ b/src/csrc/umath/unary_ops.cpp @@ -150,13 +150,16 @@ quad_unary_logical_op_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *con PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + Py_INCREF(given_descrs[0]); loop_descrs[0] = given_descrs[0]; // Output is always bool loop_descrs[1] = PyArray_DescrFromType(NPY_BOOL); if (!loop_descrs[1]) { - return (NPY_CASTING)-1; + return quad_resolve_descrs_fail(loop_descrs, 2); } return NPY_NO_CASTING; @@ -419,6 +422,10 @@ quad_frexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[] PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + for (int i = 0; i < 3; i++) { + loop_descrs[i] = NULL; + } + // Input descriptor Py_INCREF(given_descrs[0]); loop_descrs[0] = given_descrs[0]; @@ -436,6 +443,9 @@ quad_frexp_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dtypes[] // Output 2: exponent (int32) if (given_descrs[2] == NULL) { loop_descrs[2] = PyArray_DescrFromType(NPY_INT32); + if (!loop_descrs[2]) { + return quad_resolve_descrs_fail(loop_descrs, 3); + } } else { Py_INCREF(given_descrs[2]); diff --git a/src/csrc/umath/unary_props.cpp b/src/csrc/umath/unary_props.cpp index 5f06039..98bfe95 100644 --- a/src/csrc/umath/unary_props.cpp +++ b/src/csrc/umath/unary_props.cpp @@ -25,10 +25,16 @@ quad_unary_prop_resolve_descriptors(PyObject *self, PyArray_DTypeMeta *const dty PyArray_Descr *const given_descrs[], PyArray_Descr *loop_descrs[], npy_intp *NPY_UNUSED(view_offset)) { + loop_descrs[0] = NULL; + loop_descrs[1] = NULL; + Py_INCREF(given_descrs[0]); loop_descrs[0] = given_descrs[0]; loop_descrs[1] = PyArray_DescrFromType(NPY_BOOL); + if (!loop_descrs[1]) { + return quad_resolve_descrs_fail(loop_descrs, 2); + } return NPY_NO_CASTING; } diff --git a/src/include/dtype.h b/src/include/dtype.h index 77a6544..5396e1c 100644 --- a/src/include/dtype.h +++ b/src/include/dtype.h @@ -20,6 +20,16 @@ extern PyArray_DTypeMeta QuadPrecDType; QuadPrecDTypeObject * new_quaddtype_instance(QuadBackendType backend); +/* Fail a resolver; `loop_descrs` must be NULL-initialized by the caller. */ +static inline NPY_CASTING +quad_resolve_descrs_fail(PyArray_Descr *loop_descrs[], int n) +{ + for (int i = 0; i < n; i++) { + Py_CLEAR(loop_descrs[i]); + } + return (NPY_CASTING)-1; +} + int init_quadprec_dtype(void); diff --git a/src/include/lock.h b/src/include/lock.h index 6c2a970..9c58bf0 100644 --- a/src/include/lock.h +++ b/src/include/lock.h @@ -13,6 +13,6 @@ extern PyMutex sleef_lock; #define UNLOCK_SLEEF PyMutex_Unlock(&sleef_lock) #endif -void init_sleef_locks(void); +int init_sleef_locks(void); #endif // _QUADDTYPE_LOCK_H \ No newline at end of file