summaryrefslogtreecommitdiff
path: root/numpy/core/src/multiarray/methods.c
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/src/multiarray/methods.c')
-rw-r--r--numpy/core/src/multiarray/methods.c197
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[] = {