diff options
Diffstat (limited to 'numpy/core/src/multiarray/methods.c')
-rw-r--r-- | numpy/core/src/multiarray/methods.c | 197 |
1 files changed, 106 insertions, 91 deletions
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 6ec3798eb..bc3efc295 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -21,12 +21,14 @@ #include "ctors.h" #include "calculation.h" #include "convert_datatype.h" +#include "descriptor.h" #include "item_selection.h" #include "conversion_utils.h" #include "shape.h" #include "strfuncs.h" #include "array_assign.h" #include "npy_dlpack.h" +#include "multiarraymodule.h" #include "methods.h" #include "alloc.h" @@ -435,7 +437,7 @@ PyArray_GetField(PyArrayObject *self, PyArray_Descr *typed, int offset) PyArray_BYTES(self) + offset, PyArray_FLAGS(self) & ~NPY_ARRAY_F_CONTIGUOUS, (PyObject *)self, (PyObject *)self, - 0, 1); + _NPY_ARRAY_ALLOW_EMPTY_STRING); return ret; } @@ -851,29 +853,35 @@ static PyObject * array_astype(PyArrayObject *self, PyObject *const *args, Py_ssize_t len_args, PyObject *kwnames) { - PyArray_Descr *dtype = NULL; /* * TODO: UNSAFE default for compatibility, I think * switching to SAME_KIND by default would be good. */ + npy_dtype_info dt_info; NPY_CASTING casting = NPY_UNSAFE_CASTING; NPY_ORDER order = NPY_KEEPORDER; _PyArray_CopyMode forcecopy = 1; int subok = 1; + NPY_PREPARE_ARGPARSER; if (npy_parse_arguments("astype", args, len_args, kwnames, - "dtype", &PyArray_DescrConverter, &dtype, + "dtype", &PyArray_DTypeOrDescrConverterRequired, &dt_info, "|order", &PyArray_OrderConverter, &order, "|casting", &PyArray_CastingConverter, &casting, "|subok", &PyArray_PythonPyIntFromInt, &subok, "|copy", &PyArray_CopyConverter, &forcecopy, NULL, NULL, NULL) < 0) { - Py_XDECREF(dtype); + Py_XDECREF(dt_info.descr); + Py_XDECREF(dt_info.dtype); return NULL; } /* If it is not a concrete dtype instance find the best one for the array */ - Py_SETREF(dtype, PyArray_AdaptDescriptorToArray(self, (PyObject *)dtype)); + PyArray_Descr *dtype; + + dtype = PyArray_AdaptDescriptorToArray(self, dt_info.dtype, dt_info.descr); + Py_XDECREF(dt_info.descr); + Py_DECREF(dt_info.dtype); if (dtype == NULL) { return NULL; } @@ -916,29 +924,28 @@ array_astype(PyArrayObject *self, PyArrayObject *ret; - /* This steals the reference to dtype, so no DECREF of dtype */ + /* This steals the reference to dtype */ + Py_INCREF(dtype); ret = (PyArrayObject *)PyArray_NewLikeArray( self, order, dtype, subok); if (ret == NULL) { + Py_DECREF(dtype); return NULL; } - /* NumPy 1.20, 2020-10-01 */ - if ((PyArray_NDIM(self) != PyArray_NDIM(ret)) && - DEPRECATE_FUTUREWARNING( - "casting an array to a subarray dtype " - "will not use broadcasting in the future, but cast each " - "element to the new dtype and then append the dtype's shape " - "to the new array. You can opt-in to the new behaviour, by " - "additional field to the cast: " - "`arr.astype(np.dtype([('f', dtype)]))['f']`.\n" - "This may lead to a different result or to current failures " - "succeeding. " - "(FutureWarning since NumPy 1.20)") < 0) { - Py_DECREF(ret); - return NULL; - } - if (PyArray_CopyInto(ret, self) < 0) { + /* Decrease the number of dimensions removing subarray ones again */ + int out_ndim = PyArray_NDIM(ret); + PyArray_Descr *out_descr = PyArray_DESCR(ret); + ((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(self); + ((PyArrayObject_fields *)ret)->descr = dtype; + + int success = PyArray_CopyInto(ret, self); + + Py_DECREF(dtype); + ((PyArrayObject_fields *)ret)->nd = out_ndim; + ((PyArrayObject_fields *)ret)->descr = out_descr; + + if (success < 0) { Py_DECREF(ret); return NULL; } @@ -1095,7 +1102,7 @@ any_array_ufunc_overrides(PyObject *args, PyObject *kwds) int nin, nout; PyObject *out_kwd_obj; PyObject *fast; - PyObject **in_objs, **out_objs; + PyObject **in_objs, **out_objs, *where_obj; /* check inputs */ nin = PyTuple_Size(args); @@ -1126,6 +1133,17 @@ any_array_ufunc_overrides(PyObject *args, PyObject *kwds) } } Py_DECREF(out_kwd_obj); + /* check where if it exists */ + where_obj = PyDict_GetItemWithError(kwds, npy_ma_str_where); + if (where_obj == NULL) { + if (PyErr_Occurred()) { + return -1; + } + } else { + if (PyUFunc_HasOverride(where_obj)){ + return 1; + } + } return 0; } @@ -1657,7 +1675,7 @@ array_deepcopy(PyArrayObject *self, PyObject *args) { PyArrayObject *copied_array; PyObject *visit; - NpyIter *iter; + NpyIter *iter = NULL; NpyIter_IterNextFunc *iternext; char *data; char **dataptr; @@ -1673,64 +1691,73 @@ array_deepcopy(PyArrayObject *self, PyObject *args) if (copied_array == NULL) { return NULL; } - if (PyDataType_REFCHK(PyArray_DESCR(self))) { - copy = PyImport_ImportModule("copy"); - if (copy == NULL) { - Py_DECREF(copied_array); - return NULL; - } - deepcopy = PyObject_GetAttrString(copy, "deepcopy"); - Py_DECREF(copy); - if (deepcopy == NULL) { - Py_DECREF(copied_array); - return NULL; - } - iter = NpyIter_New(copied_array, - NPY_ITER_READWRITE | - NPY_ITER_EXTERNAL_LOOP | - NPY_ITER_REFS_OK | - NPY_ITER_ZEROSIZE_OK, - NPY_KEEPORDER, NPY_NO_CASTING, - NULL); - if (iter == NULL) { - Py_DECREF(deepcopy); - Py_DECREF(copied_array); - return NULL; - } - if (NpyIter_GetIterSize(iter) != 0) { - iternext = NpyIter_GetIterNext(iter, NULL); - if (iternext == NULL) { - NpyIter_Deallocate(iter); - Py_DECREF(deepcopy); - Py_DECREF(copied_array); - return NULL; - } - dataptr = NpyIter_GetDataPtrArray(iter); - strideptr = NpyIter_GetInnerStrideArray(iter); - innersizeptr = NpyIter_GetInnerLoopSizePtr(iter); - - do { - data = *dataptr; - stride = *strideptr; - count = *innersizeptr; - while (count--) { - deepcopy_res = _deepcopy_call(data, data, PyArray_DESCR(copied_array), - deepcopy, visit); - if (deepcopy_res == -1) { - return NULL; - } + if (!PyDataType_REFCHK(PyArray_DESCR(self))) { + return (PyObject *)copied_array; + } - data += stride; + /* If the array contains objects, need to deepcopy them as well */ + copy = PyImport_ImportModule("copy"); + if (copy == NULL) { + Py_DECREF(copied_array); + return NULL; + } + deepcopy = PyObject_GetAttrString(copy, "deepcopy"); + Py_DECREF(copy); + if (deepcopy == NULL) { + goto error; + } + iter = NpyIter_New(copied_array, + NPY_ITER_READWRITE | + NPY_ITER_EXTERNAL_LOOP | + NPY_ITER_REFS_OK | + NPY_ITER_ZEROSIZE_OK, + NPY_KEEPORDER, NPY_NO_CASTING, + NULL); + if (iter == NULL) { + goto error; + } + if (NpyIter_GetIterSize(iter) != 0) { + iternext = NpyIter_GetIterNext(iter, NULL); + if (iternext == NULL) { + goto error; + } + + dataptr = NpyIter_GetDataPtrArray(iter); + strideptr = NpyIter_GetInnerStrideArray(iter); + innersizeptr = NpyIter_GetInnerLoopSizePtr(iter); + + do { + data = *dataptr; + stride = *strideptr; + count = *innersizeptr; + while (count--) { + deepcopy_res = _deepcopy_call(data, data, PyArray_DESCR(copied_array), + deepcopy, visit); + if (deepcopy_res == -1) { + goto error; } - } while (iternext(iter)); - } - NpyIter_Deallocate(iter); - Py_DECREF(deepcopy); + + data += stride; + } + } while (iternext(iter)); + } + + Py_DECREF(deepcopy); + if (!NpyIter_Deallocate(iter)) { + Py_DECREF(copied_array); + return NULL; } - return (PyObject*) copied_array; + return (PyObject *)copied_array; + + error: + Py_DECREF(deepcopy); + Py_DECREF(copied_array); + NpyIter_Deallocate(iter); + return NULL; } + /* Convert Array to flat list (using getitem) */ static PyObject * _getlist_pkl(PyArrayObject *self) @@ -2776,9 +2803,7 @@ array_complex(PyArrayObject *self, PyObject *NPY_UNUSED(args)) PyArray_Descr *dtype; PyObject *c; - if (PyArray_SIZE(self) != 1) { - PyErr_SetString(PyExc_TypeError, - "only length-1 arrays can be converted to Python scalars"); + if (check_is_convertible_to_scalar(self) < 0) { return NULL; } @@ -2823,25 +2848,15 @@ array_complex(PyArrayObject *self, PyObject *NPY_UNUSED(args)) static PyObject * array_class_getitem(PyObject *cls, PyObject *args) { - PyObject *generic_alias; - -#ifdef Py_GENERICALIASOBJECT_H - Py_ssize_t args_len; + const Py_ssize_t args_len = PyTuple_Check(args) ? PyTuple_Size(args) : 1; - args_len = PyTuple_Check(args) ? PyTuple_Size(args) : 1; if ((args_len > 2) || (args_len == 0)) { return PyErr_Format(PyExc_TypeError, "Too %s arguments for %s", args_len > 2 ? "many" : "few", ((PyTypeObject *)cls)->tp_name); } - generic_alias = Py_GenericAlias(cls, args); -#else - PyErr_SetString(PyExc_TypeError, - "Type subscription requires python >= 3.9"); - generic_alias = NULL; -#endif - return generic_alias; + return Py_GenericAlias(cls, args); } NPY_NO_EXPORT PyMethodDef array_methods[] = { |