/* * check if in "alhs @op@ orhs" that alhs is a temporary (refcnt == 1) so we * can do in-place operations instead of creating a new temporary * "cannot" is set to true if it cannot be done even with swapped arguments */ static int can_elide_temp(PyArrayObject * alhs, PyObject * orhs, int * cannot) { /* * to be a candidate the array needs to have reference count 1, be an exact * array of a basic type, own its data and size larger than threshold */ if (Py_REFCNT(alhs) != 1 || !PyArray_CheckExact(alhs) || !PyArray_ISNUMBER(alhs) || !PyArray_CHKFLAGS(alhs, NPY_ARRAY_OWNDATA) || !PyArray_ISWRITEABLE(alhs) || PyArray_CHKFLAGS(alhs, NPY_ARRAY_UPDATEIFCOPY) || PyArray_CHKFLAGS(alhs, NPY_ARRAY_WRITEBACKIFCOPY) || PyArray_NBYTES(alhs) < NPY_MIN_ELIDE_BYTES) { return 0; } if (PyArray_CheckExact(orhs) || PyArray_CheckAnyScalar(orhs)) { PyArrayObject * arhs; /* create array from right hand side */ Py_INCREF(orhs); arhs = (PyArrayObject *)PyArray_EnsureArray(orhs); if (arhs == NULL) { return 0; } /* * if rhs is not a scalar dimensions must match * TODO: one could allow broadcasting on equal types */ if (!(PyArray_NDIM(arhs) == 0 || (PyArray_NDIM(arhs) == PyArray_NDIM(alhs) && PyArray_CompareLists(PyArray_DIMS(alhs), PyArray_DIMS(arhs), PyArray_NDIM(arhs))))) { Py_DECREF(arhs); return 0; } /* must be safe to cast (checks values for scalar in rhs) */ if (PyArray_CanCastArrayTo(arhs, PyArray_DESCR(alhs), NPY_SAFE_CASTING)) { Py_DECREF(arhs); return check_callers(cannot); } Py_DECREF(arhs); } return 0; }
/* try elide unary temporary */ NPY_NO_EXPORT int can_elide_temp_unary(PyArrayObject * m1) { int cannot; if (Py_REFCNT(m1) != 1 || !PyArray_CheckExact(m1) || PyArray_DESCR(m1)->type_num == NPY_VOID || !(PyArray_FLAGS(m1) & NPY_ARRAY_OWNDATA) || PyArray_NBYTES(m1) < NPY_MIN_ELIDE_BYTES) { return 0; } if (check_callers(&cannot)) { #if NPY_ELIDE_DEBUG != 0 puts("elided temporary in unary op"); #endif return 1; } else { return 0; } }
/* try elide unary temporary */ NPY_NO_EXPORT int can_elide_temp_unary(PyArrayObject * m1) { int cannot; if (Py_REFCNT(m1) != 1 || !PyArray_CheckExact(m1) || !PyArray_ISNUMBER(m1) || !PyArray_CHKFLAGS(m1, NPY_ARRAY_OWNDATA) || !PyArray_ISWRITEABLE(m1) || PyArray_CHKFLAGS(m1, NPY_ARRAY_UPDATEIFCOPY) || PyArray_NBYTES(m1) < NPY_MIN_ELIDE_BYTES) { return 0; } if (check_callers(&cannot)) { #if NPY_ELIDE_DEBUG != 0 puts("elided temporary in unary op"); #endif return 1; } else { return 0; } }