* 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 */
| 283 | * "cannot" is set to true if it cannot be done even with swapped arguments |
| 284 | */ |
| 285 | static int |
| 286 | can_elide_temp(PyObject *olhs, PyObject *orhs, int *cannot) |
| 287 | { |
| 288 | /* |
| 289 | * to be a candidate the array needs to have reference count 1, be an exact |
| 290 | * array of a basic type, own its data and size larger than threshold |
| 291 | */ |
| 292 | PyArrayObject *alhs = (PyArrayObject *)olhs; |
| 293 | if (Py_REFCNT(olhs) != 1 || !PyArray_CheckExact(olhs) || |
| 294 | !PyArray_ISNUMBER(alhs) || |
| 295 | !PyArray_CHKFLAGS(alhs, NPY_ARRAY_OWNDATA) || |
| 296 | !PyArray_ISWRITEABLE(alhs) || |
| 297 | PyArray_CHKFLAGS(alhs, NPY_ARRAY_WRITEBACKIFCOPY) || |
| 298 | PyArray_NBYTES(alhs) < NPY_MIN_ELIDE_BYTES) { |
| 299 | return 0; |
| 300 | } |
| 301 | if (PyArray_CheckExact(orhs) || |
| 302 | PyArray_CheckAnyScalar(orhs)) { |
| 303 | PyArrayObject * arhs; |
| 304 | |
| 305 | /* create array from right hand side */ |
| 306 | Py_INCREF(orhs); |
| 307 | arhs = (PyArrayObject *)PyArray_EnsureArray(orhs); |
| 308 | if (arhs == NULL) { |
| 309 | return 0; |
| 310 | } |
| 311 | |
| 312 | /* |
| 313 | * if rhs is not a scalar dimensions must match |
| 314 | * TODO: one could allow broadcasting on equal types |
| 315 | */ |
| 316 | if (!(PyArray_NDIM(arhs) == 0 || |
| 317 | (PyArray_NDIM(arhs) == PyArray_NDIM(alhs) && |
| 318 | PyArray_CompareLists(PyArray_DIMS(alhs), PyArray_DIMS(arhs), |
| 319 | PyArray_NDIM(arhs))))) { |
| 320 | Py_DECREF(arhs); |
| 321 | return 0; |
| 322 | } |
| 323 | |
| 324 | /* must be safe to cast (checks values for scalar in rhs) */ |
| 325 | if (PyArray_CanCastArrayTo(arhs, PyArray_DESCR(alhs), |
| 326 | NPY_SAFE_CASTING)) { |
| 327 | Py_DECREF(arhs); |
| 328 | return check_callers(cannot); |
| 329 | } |
| 330 | Py_DECREF(arhs); |
| 331 | } |
| 332 | |
| 333 | return 0; |
| 334 | } |
| 335 | |
| 336 | /* |
| 337 | * try eliding a binary op, if commutative is true also try swapped arguments |
no test coverage detected