summaryrefslogtreecommitdiff
path: root/numpy/core/src
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/core/src')
-rw-r--r--numpy/core/src/multiarray/arrayobject.c4
-rw-r--r--numpy/core/src/multiarray/convert.c2
-rw-r--r--numpy/core/src/multiarray/ctors.c331
-rw-r--r--numpy/core/src/multiarray/ctors.h21
-rw-r--r--numpy/core/src/multiarray/dtype_transfer.c6
-rw-r--r--numpy/core/src/multiarray/einsum.c.src3
-rw-r--r--numpy/core/src/multiarray/getset.c2
-rw-r--r--numpy/core/src/multiarray/mapping.c10
-rw-r--r--numpy/core/src/multiarray/methods.c35
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c4
-rw-r--r--numpy/core/src/multiarray/shape.c2
-rw-r--r--numpy/core/src/umath/ufunc_object.c8
12 files changed, 122 insertions, 306 deletions
diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c
index 0434e8676..46c4d90c9 100644
--- a/numpy/core/src/multiarray/arrayobject.c
+++ b/numpy/core/src/multiarray/arrayobject.c
@@ -1223,7 +1223,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
(int)dims.len,
dims.ptr,
strides.ptr, NULL, is_f_order, NULL, NULL,
- 0, 1);
+ _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (ret == NULL) {
descr = NULL;
goto fail;
@@ -1260,7 +1260,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
subtype, descr,
dims.len, dims.ptr, strides.ptr, offset + (char *)buffer.ptr,
buffer.flags, NULL, buffer.base,
- 0, 1);
+ _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (ret == NULL) {
descr = NULL;
goto fail;
diff --git a/numpy/core/src/multiarray/convert.c b/numpy/core/src/multiarray/convert.c
index 9e0c9fb60..e8b880a43 100644
--- a/numpy/core/src/multiarray/convert.c
+++ b/numpy/core/src/multiarray/convert.c
@@ -509,7 +509,7 @@ PyArray_View(PyArrayObject *self, PyArray_Descr *type, PyTypeObject *pytype)
PyArray_NDIM(self), PyArray_DIMS(self), PyArray_STRIDES(self),
PyArray_DATA(self),
flags, (PyObject *)self, (PyObject *)self,
- 0, 1);
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (ret == NULL) {
Py_XDECREF(type);
return NULL;
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c
index 79a1905a7..3c5b047c3 100644
--- a/numpy/core/src/multiarray/ctors.c
+++ b/numpy/core/src/multiarray/ctors.c
@@ -628,8 +628,7 @@ NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr_int(
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
- int flags, PyObject *obj, PyObject *base, int zeroed,
- int allow_emptystring)
+ int flags, PyObject *obj, PyObject *base, _NPY_CREATION_FLAGS cflags)
{
PyArrayObject_fields *fa;
npy_intp nbytes;
@@ -644,45 +643,54 @@ PyArray_NewFromDescr_int(
return NULL;
}
- if (descr->subarray) {
- PyObject *ret;
- npy_intp newdims[2*NPY_MAXDIMS];
- npy_intp *newstrides = NULL;
- memcpy(newdims, dims, nd*sizeof(npy_intp));
- if (strides) {
- newstrides = newdims + NPY_MAXDIMS;
- memcpy(newstrides, strides, nd*sizeof(npy_intp));
- }
- nd =_update_descr_and_dimensions(&descr, newdims,
- newstrides, nd);
- ret = PyArray_NewFromDescr_int(
- subtype, descr,
- nd, newdims, newstrides, data,
- flags, obj, base,
- zeroed, allow_emptystring);
- return ret;
- }
-
- /* Check datatype element size */
nbytes = descr->elsize;
- if (PyDataType_ISUNSIZED(descr)) {
- if (!PyDataType_ISFLEXIBLE(descr) &&
- NPY_DT_is_legacy(NPY_DTYPE(descr))) {
- PyErr_SetString(PyExc_TypeError, "Empty data-type");
- Py_DECREF(descr);
- return NULL;
- }
- else if (PyDataType_ISSTRING(descr) && !allow_emptystring &&
- data == NULL) {
- PyArray_DESCR_REPLACE(descr);
- if (descr == NULL) {
+ /*
+ * Unless explicitly asked not to, we do replace dtypes in some cases.
+ * This mainly means that we never create arrays with a subarray dtype
+ * (unless for internal use when requested). And neither do we create
+ * S0/U0 arrays in most cases (unless data == NULL so this is probably
+ * a view where growing the dtype would be presumable wrong).
+ */
+ if (!(cflags & _NPY_ARRAY_ENSURE_DTYPE_IDENTITY)) {
+ if (descr->subarray) {
+ PyObject *ret;
+ npy_intp newdims[2*NPY_MAXDIMS];
+ npy_intp *newstrides = NULL;
+ memcpy(newdims, dims, nd*sizeof(npy_intp));
+ if (strides) {
+ newstrides = newdims + NPY_MAXDIMS;
+ memcpy(newstrides, strides, nd*sizeof(npy_intp));
+ }
+ nd =_update_descr_and_dimensions(&descr, newdims,
+ newstrides, nd);
+ ret = PyArray_NewFromDescr_int(
+ subtype, descr,
+ nd, newdims, newstrides, data,
+ flags, obj, base, cflags);
+ return ret;
+ }
+
+ /* Check datatype element size */
+ if (PyDataType_ISUNSIZED(descr)) {
+ if (!PyDataType_ISFLEXIBLE(descr) &&
+ NPY_DT_is_legacy(NPY_DTYPE(descr))) {
+ PyErr_SetString(PyExc_TypeError, "Empty data-type");
+ Py_DECREF(descr);
return NULL;
}
- if (descr->type_num == NPY_STRING) {
- nbytes = descr->elsize = 1;
- }
- else {
- nbytes = descr->elsize = sizeof(npy_ucs4);
+ else if (PyDataType_ISSTRING(descr)
+ && !(cflags & _NPY_ARRAY_ALLOW_EMPTY_STRING)
+ && data == NULL) {
+ PyArray_DESCR_REPLACE(descr);
+ if (descr == NULL) {
+ return NULL;
+ }
+ if (descr->type_num == NPY_STRING) {
+ nbytes = descr->elsize = 1;
+ }
+ else {
+ nbytes = descr->elsize = sizeof(npy_ucs4);
+ }
}
}
}
@@ -811,8 +819,9 @@ PyArray_NewFromDescr_int(
* with malloc and let the zero-filling loop fill the array buffer
* with valid zero values for the dtype.
*/
- int use_calloc = (PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT) ||
- (zeroed && (fill_zero_info.func == NULL)));
+ int use_calloc = (
+ PyDataType_FLAGCHK(descr, NPY_NEEDS_INIT) ||
+ ((cflags & _NPY_ARRAY_ZEROED) && (fill_zero_info.func == NULL)));
/* Store the handler in case the default is modified */
fa->mem_handler = PyDataMem_GetHandler();
@@ -846,7 +855,8 @@ PyArray_NewFromDescr_int(
/*
* If the array needs special dtype-specific zero-filling logic, do that
*/
- if (NPY_UNLIKELY(zeroed && (fill_zero_info.func != NULL))) {
+ if (NPY_UNLIKELY((cflags & _NPY_ARRAY_ZEROED)
+ && (fill_zero_info.func != NULL))) {
npy_intp size = PyArray_MultiplyList(fa->dimensions, fa->nd);
if (fill_zero_info.func(
NULL, descr, data, size, descr->elsize,
@@ -1001,7 +1011,7 @@ PyArray_NewFromDescrAndBase(
{
return PyArray_NewFromDescr_int(subtype, descr, nd,
dims, strides, data,
- flags, obj, base, 0, 0);
+ flags, obj, base, 0);
}
/*
@@ -1484,160 +1494,6 @@ PyArray_GetArrayParamsFromObject(PyObject *NPY_UNUSED(op),
}
-/*
- * This function is a legacy implementation to retain subarray dtype
- * behaviour in array coercion. The behaviour here makes sense if tuples
- * of matching dimensionality are being coerced. Due to the difficulty
- * that the result is ill-defined for lists of array-likes, this is deprecated.
- *
- * WARNING: Do not use this function, it exists purely to support a deprecated
- * code path.
- */
-static int
-setArrayFromSequence(PyArrayObject *a, PyObject *s,
- int dim, PyArrayObject * dst)
-{
- Py_ssize_t i, slen;
- int res = -1;
-
- /* first recursion, view equal destination */
- if (dst == NULL)
- dst = a;
-
- /*
- * This code is to ensure that the sequence access below will
- * return a lower-dimensional sequence.
- */
-
- /* INCREF on entry DECREF on exit */
- Py_INCREF(s);
-
- PyObject *seq = NULL;
-
- if (PyArray_Check(s)) {
- if (!(PyArray_CheckExact(s))) {
- /*
- * make sure a base-class array is used so that the dimensionality
- * reduction assumption is correct.
- */
- /* This will DECREF(s) if replaced */
- s = PyArray_EnsureArray(s);
- if (s == NULL) {
- goto fail;
- }
- }
-
- /* dst points to correct array subsection */
- if (PyArray_CopyInto(dst, (PyArrayObject *)s) < 0) {
- goto fail;
- }
-
- Py_DECREF(s);
- return 0;
- }
-
- if (dim > PyArray_NDIM(a)) {
- PyErr_Format(PyExc_ValueError,
- "setArrayFromSequence: sequence/array dimensions mismatch.");
- goto fail;
- }
-
- /* Try __array__ before using s as a sequence */
- PyObject *tmp = _array_from_array_like(s, NULL, 0, NULL, 0);
- if (tmp == NULL) {
- goto fail;
- }
- else if (tmp == Py_NotImplemented) {
- Py_DECREF(tmp);
- }
- else {
- int r = PyArray_CopyInto(dst, (PyArrayObject *)tmp);
- Py_DECREF(tmp);
- if (r < 0) {
- goto fail;
- }
- Py_DECREF(s);
- return 0;
- }
-
- seq = PySequence_Fast(s, "Could not convert object to sequence");
- if (seq == NULL) {
- goto fail;
- }
- slen = PySequence_Fast_GET_SIZE(seq);
-
- /*
- * Either the dimensions match, or the sequence has length 1 and can
- * be broadcast to the destination.
- */
- if (slen != PyArray_DIMS(a)[dim] && slen != 1) {
- PyErr_Format(PyExc_ValueError,
- "cannot copy sequence with size %zd to array axis "
- "with dimension %" NPY_INTP_FMT, slen, PyArray_DIMS(a)[dim]);
- goto fail;
- }
-
- /* Broadcast the one element from the sequence to all the outputs */
- if (slen == 1) {
- PyObject *o = PySequence_Fast_GET_ITEM(seq, 0);
- npy_intp alen = PyArray_DIM(a, dim);
-
- for (i = 0; i < alen; i++) {
- if ((PyArray_NDIM(a) - dim) > 1) {
- PyArrayObject * tmp =
- (PyArrayObject *)array_item_asarray(dst, i);
- if (tmp == NULL) {
- goto fail;
- }
-
- res = setArrayFromSequence(a, o, dim+1, tmp);
- Py_DECREF(tmp);
- }
- else {
- char * b = (PyArray_BYTES(dst) + i * PyArray_STRIDES(dst)[0]);
- res = PyArray_SETITEM(dst, b, o);
- }
- if (res < 0) {
- goto fail;
- }
- }
- }
- /* Copy element by element */
- else {
- for (i = 0; i < slen; i++) {
- PyObject * o = PySequence_Fast_GET_ITEM(seq, i);
- if ((PyArray_NDIM(a) - dim) > 1) {
- PyArrayObject * tmp =
- (PyArrayObject *)array_item_asarray(dst, i);
- if (tmp == NULL) {
- goto fail;
- }
-
- res = setArrayFromSequence(a, o, dim+1, tmp);
- Py_DECREF(tmp);
- }
- else {
- char * b = (PyArray_BYTES(dst) + i * PyArray_STRIDES(dst)[0]);
- res = PyArray_SETITEM(dst, b, o);
- }
- if (res < 0) {
- goto fail;
- }
- }
- }
-
- Py_DECREF(seq);
- Py_DECREF(s);
- return 0;
-
- fail:
- Py_XDECREF(seq);
- Py_DECREF(s);
- return res;
-}
-
-
-
/*NUMPY_API
* Does not check for NPY_ARRAY_ENSURECOPY and NPY_ARRAY_NOTSWAPPED in flags
* Steals a reference to newtype --- which can be NULL
@@ -1700,70 +1556,6 @@ PyArray_FromAny_int(PyObject *op, PyArray_Descr *in_descr,
return NULL;
}
- if (NPY_UNLIKELY(in_descr != NULL && PyDataType_HASSUBARRAY(dtype))) {
- /*
- * When a subarray dtype was passed in, its dimensions are appended
- * to the array dimension (causing a dimension mismatch).
- * There is a problem with that, because if we coerce from non-arrays
- * we do this correctly by element (as defined by tuples), but for
- * arrays we first append the dimensions and then assign to the base
- * dtype and then assign which causes the problem.
- *
- * Thus, we check if there is an array included, in that case we
- * give a FutureWarning.
- * When the warning is removed, PyArray_Pack will have to ensure
- * that it does not append the dimensions when creating the subarrays
- * to assign `arr[0] = obj[0]`.
- */
- int includes_array = 0;
- if (cache != NULL) {
- /* This is not ideal, but it is a pretty special case */
- coercion_cache_obj *next = cache;
- while (next != NULL) {
- if (!next->sequence) {
- includes_array = 1;
- break;
- }
- next = next->next;
- }
- }
- if (includes_array) {
- npy_free_coercion_cache(cache);
-
- ret = (PyArrayObject *) PyArray_NewFromDescr(
- &PyArray_Type, dtype, ndim, dims, NULL, NULL,
- flags & NPY_ARRAY_F_CONTIGUOUS, NULL);
- if (ret == NULL) {
- return NULL;
- }
- assert(PyArray_NDIM(ret) != ndim);
-
- /* NumPy 1.20, 2020-10-01 */
- if (DEPRECATE_FUTUREWARNING(
- "creating an array with a subarray dtype will behave "
- "differently when the `np.array()` (or `asarray`, etc.) "
- "call includes an array or array object.\n"
- "If you are converting a single array or a list of arrays,"
- "you can opt-in to the future behaviour using:\n"
- " np.array(arr, dtype=np.dtype(['f', dtype]))['f']\n"
- " np.array([arr1, arr2], dtype=np.dtype(['f', dtype]))['f']\n"
- "\n"
- "By including a new field and indexing it after the "
- "conversion.\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 (setArrayFromSequence(ret, op, 0, NULL) < 0) {
- Py_DECREF(ret);
- return NULL;
- }
- return (PyObject *)ret;
- }
- }
-
if (dtype == NULL) {
dtype = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
}
@@ -2127,13 +1919,26 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
if ((flags & NPY_ARRAY_ENSUREARRAY)) {
subok = 0;
}
+ Py_INCREF(newtype);
ret = (PyArrayObject *)PyArray_NewLikeArray(arr, order,
newtype, subok);
if (ret == NULL) {
+ Py_DECREF(newtype);
return NULL;
}
- if (PyArray_CopyInto(ret, arr) < 0) {
+ int actual_ndim = PyArray_NDIM(ret);
+ PyArray_Descr *actual_dtype = PyArray_DESCR(ret);
+ ((PyArrayObject_fields *)ret)->nd = PyArray_NDIM(arr);
+ ((PyArrayObject_fields *)ret)->descr = newtype;
+
+ int success = PyArray_CopyInto(ret, arr);
+
+ Py_DECREF(newtype);
+ ((PyArrayObject_fields *)ret)->nd = actual_ndim;
+ ((PyArrayObject_fields *)ret)->descr = actual_dtype;
+
+ if (success < 0) {
Py_DECREF(ret);
return NULL;
}
@@ -3052,7 +2857,7 @@ PyArray_Zeros(int nd, npy_intp const *dims, PyArray_Descr *type, int is_f_order)
&PyArray_Type, type,
nd, dims, NULL, NULL,
is_f_order, NULL, NULL,
- 1, 0);
+ _NPY_ARRAY_ZEROED);
if (ret == NULL) {
return NULL;
@@ -3706,7 +3511,7 @@ PyArray_FromFile(FILE *fp, PyArray_Descr *dtype, npy_intp num, char *sep)
&PyArray_Type, dtype,
1, &num, NULL, NULL,
0, NULL, NULL,
- 0, 1);
+ _NPY_ARRAY_ALLOW_EMPTY_STRING);
}
if ((sep == NULL) || (strlen(sep) == 0)) {
ret = array_fromfile_binary(fp, dtype, num, &nread);
diff --git a/numpy/core/src/multiarray/ctors.h b/numpy/core/src/multiarray/ctors.h
index 22020e26a..a876ab2c0 100644
--- a/numpy/core/src/multiarray/ctors.h
+++ b/numpy/core/src/multiarray/ctors.h
@@ -13,12 +13,29 @@ PyArray_NewFromDescrAndBase(
npy_intp const *dims, npy_intp const *strides, void *data,
int flags, PyObject *obj, PyObject *base);
+
+/* Private options for NewFromDescriptor */
+typedef enum {
+ /*
+ * Indicate the the array should be zeroed, we may use calloc to do so
+ * (otherwise much like ).
+ */
+ _NPY_ARRAY_ZEROED = 1 << 0,
+ /* Whether to allow empty strings (implied by ensure dtype identity) */
+ _NPY_ARRAY_ALLOW_EMPTY_STRING = 1 << 1,
+ /*
+ * If we take a view into an existing array and use its dtype, then that
+ * dtype must be preserved (for example for subarray and S0, but also
+ * possibly for future dtypes that store more metadata).
+ */
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY = 1 << 2,
+} _NPY_CREATION_FLAGS;
+
NPY_NO_EXPORT PyObject *
PyArray_NewFromDescr_int(
PyTypeObject *subtype, PyArray_Descr *descr, int nd,
npy_intp const *dims, npy_intp const *strides, void *data,
- int flags, PyObject *obj, PyObject *base, int zeroed,
- int allow_emptystring);
+ int flags, PyObject *obj, PyObject *base, _NPY_CREATION_FLAGS cflags);
NPY_NO_EXPORT PyObject *
PyArray_NewLikeArrayWithShape(
diff --git a/numpy/core/src/multiarray/dtype_transfer.c b/numpy/core/src/multiarray/dtype_transfer.c
index 9e77d456d..f79662040 100644
--- a/numpy/core/src/multiarray/dtype_transfer.c
+++ b/numpy/core/src/multiarray/dtype_transfer.c
@@ -567,7 +567,7 @@ wrap_copy_swap_function(
&PyArray_Type, dtype,
1, &shape, NULL, NULL,
0, NULL, NULL,
- 0, 1);
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (data->arr == NULL) {
PyMem_Free(data);
return NPY_FAIL;
@@ -1316,7 +1316,7 @@ get_legacy_dtype_cast_function(
&PyArray_Type, tmp_dtype,
1, &shape, NULL, NULL,
0, NULL, NULL,
- 0, 1);
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (data->aip == NULL) {
PyMem_Free(data);
return NPY_FAIL;
@@ -1343,7 +1343,7 @@ get_legacy_dtype_cast_function(
&PyArray_Type, tmp_dtype,
1, &shape, NULL, NULL,
0, NULL, NULL,
- 0, 1);
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (data->aop == NULL) {
Py_DECREF(data->aip);
PyMem_Free(data);
diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src
index cd1a58982..9f9d41579 100644
--- a/numpy/core/src/multiarray/einsum.c.src
+++ b/numpy/core/src/multiarray/einsum.c.src
@@ -321,8 +321,7 @@ get_single_op_view(PyArrayObject *op, char *labels,
Py_TYPE(op), PyArray_DESCR(op),
ndim_output, new_dims, new_strides, PyArray_DATA(op),
PyArray_ISWRITEABLE(op) ? NPY_ARRAY_WRITEABLE : 0,
- (PyObject *)op, (PyObject *)op,
- 0, 0);
+ (PyObject *)op, (PyObject *)op, 0);
if (*ret == NULL) {
return -1;
diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c
index d019acbb5..7022eb231 100644
--- a/numpy/core/src/multiarray/getset.c
+++ b/numpy/core/src/multiarray/getset.c
@@ -804,7 +804,7 @@ array_imag_get(PyArrayObject *self, void *NPY_UNUSED(ignored))
PyArray_DIMS(self),
NULL, NULL,
PyArray_ISFORTRAN(self),
- (PyObject *)self, NULL, 1, 0);
+ (PyObject *)self, NULL, _NPY_ARRAY_ZEROED);
if (ret == NULL) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c
index 3dd488220..b7fcf2ee2 100644
--- a/numpy/core/src/multiarray/mapping.c
+++ b/numpy/core/src/multiarray/mapping.c
@@ -889,13 +889,13 @@ get_view_from_index(PyArrayObject *self, PyArrayObject **view,
/* Create the new view and set the base array */
Py_INCREF(PyArray_DESCR(self));
- *view = (PyArrayObject *)PyArray_NewFromDescrAndBase(
+ *view = (PyArrayObject *)PyArray_NewFromDescr_int(
ensure_array ? &PyArray_Type : Py_TYPE(self),
PyArray_DESCR(self),
new_dim, new_shape, new_strides, data_ptr,
PyArray_FLAGS(self),
ensure_array ? NULL : (PyObject *)self,
- (PyObject *)self);
+ (PyObject *)self, _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (*view == NULL) {
return -1;
}
@@ -1361,7 +1361,8 @@ _get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view)
PyArray_BYTES(arr) + offset,
PyArray_FLAGS(arr),
(PyObject *)arr, (PyObject *)arr,
- 0, 1);
+ /* We do not preserve the dtype for a subarray one, only str */
+ _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (*view == NULL) {
return 0;
}
@@ -1415,7 +1416,8 @@ _get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view)
PyArray_DATA(arr),
PyArray_FLAGS(arr),
(PyObject *)arr, (PyObject *)arr,
- 0, 1);
+ /* We do not preserve the dtype for a subarray one, only str */
+ _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (*view == NULL) {
return 0;
diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c
index 3b2e72820..bc3efc295 100644
--- a/numpy/core/src/multiarray/methods.c
+++ b/numpy/core/src/multiarray/methods.c
@@ -437,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;
}
@@ -924,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;
}
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index 98ca15ac4..029e41990 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -494,7 +494,7 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis,
/* Allocate the array for the result. This steals the 'dtype' reference. */
ret = (PyArrayObject *)PyArray_NewFromDescr_int(
subtype, descr, ndim, shape, strides, NULL, 0, NULL,
- NULL, 0, 1);
+ NULL, _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (ret == NULL) {
return NULL;
}
@@ -599,7 +599,7 @@ PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays,
/* Allocate the array for the result. This steals the 'dtype' reference. */
ret = (PyArrayObject *)PyArray_NewFromDescr_int(
subtype, descr, 1, &shape, &stride, NULL, 0, NULL,
- NULL, 0, 1);
+ NULL, _NPY_ARRAY_ALLOW_EMPTY_STRING);
if (ret == NULL) {
return NULL;
}
diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c
index 25af43bbc..15b166423 100644
--- a/numpy/core/src/multiarray/shape.c
+++ b/numpy/core/src/multiarray/shape.c
@@ -285,7 +285,7 @@ PyArray_Newshape(PyArrayObject *self, PyArray_Dims *newdims,
Py_TYPE(self), PyArray_DESCR(self),
ndim, dimensions, strides, PyArray_DATA(self),
flags, (PyObject *)self, (PyObject *)self,
- 0, 1);
+ _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
Py_DECREF(self);
return (PyObject *)ret;
}
diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c
index d4aced05f..39e64decb 100644
--- a/numpy/core/src/umath/ufunc_object.c
+++ b/numpy/core/src/umath/ufunc_object.c
@@ -6607,16 +6607,10 @@ py_resolve_dtypes_generic(PyUFuncObject *ufunc, npy_bool return_context,
Py_INCREF(descr);
dummy_arrays[i] = (PyArrayObject *)PyArray_NewFromDescr_int(
&PyArray_Type, descr, 0, NULL, NULL, NULL,
- 0, NULL, NULL, 0, 1);
+ 0, NULL, NULL, _NPY_ARRAY_ENSURE_DTYPE_IDENTITY);
if (dummy_arrays[i] == NULL) {
goto finish;
}
- if (PyArray_DESCR(dummy_arrays[i]) != descr) {
- PyErr_SetString(PyExc_NotImplementedError,
- "dtype was replaced during array creation, the dtype is "
- "unsupported currently (a subarray dtype?).");
- goto finish;
- }
DTypes[i] = NPY_DTYPE(descr);
Py_INCREF(DTypes[i]);
if (!NPY_DT_is_legacy(DTypes[i])) {