summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Goldbaum <nathan.goldbaum@gmail.com>2023-03-17 13:11:19 -0600
committerNathan Goldbaum <nathan.goldbaum@gmail.com>2023-03-17 13:11:19 -0600
commit5ae51e23587faa3bd58ed889fed9871f618d3ca1 (patch)
tree483136974f8196e23b7afc4e567d60e45e3f46ee
parent18e7fbd4301459a08432053ac992b02ece13273e (diff)
downloadnumpy-5ae51e23587faa3bd58ed889fed9871f618d3ca1.tar.gz
MAINT: avoid calling PyArray_AdaptDescriptorToArray in some cases
-rw-r--r--numpy/core/src/multiarray/multiarraymodule.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c
index f0b3a0e13..37c7f14bd 100644
--- a/numpy/core/src/multiarray/multiarraymodule.c
+++ b/numpy/core/src/multiarray/multiarraymodule.c
@@ -1653,10 +1653,32 @@ _array_fromobject_generic(
/* fast exit if simple call */
if (PyArray_CheckExact(op) || (subok && PyArray_Check(op))) {
oparr = (PyArrayObject *)op;
- PyArray_Descr* dtype = PyArray_AdaptDescriptorToArray(
- oparr, dt_info.dtype, dt_info.descr);
- if (dtype == NULL) {
- return NULL;
+ PyArray_Descr* dtype = NULL;
+ /*
+ * Skip AdaptDescriptorToArray if the supplied dtype class does not
+ * match the dtype of the input array or if we have to determine the
+ * descriptor because only the DType was given. This means we avoid
+ * inspecting array values twice for example if someone does:
+ *
+ * >>> arr = np.array(["asdf", "fdsa"], dtype=object)
+ * >>> np.array(arr, dtype="U")
+ */
+ if ((NPY_DTYPE(PyArray_DESCR(oparr)) == dt_info.dtype) ||
+ ((dt_info.descr == NULL) && (dt_info.dtype != NULL))) {
+ dtype = PyArray_AdaptDescriptorToArray(
+ oparr, dt_info.dtype, dt_info.descr);
+ if (dtype == NULL) {
+ return NULL;
+ }
+ }
+ else {
+ if ((dt_info.descr == NULL) && (dt_info.dtype == NULL)) {
+ dtype = PyArray_DESCR(oparr);
+ }
+ else {
+ dtype = dt_info.descr;
+ }
+ Py_INCREF(dtype);
}
if ((dt_info.descr == NULL) && (dt_info.dtype == NULL)) {
if (copy != NPY_COPY_ALWAYS && STRIDING_OK(oparr, order)) {