summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2018-02-08 22:32:05 -0800
committerEric Wieser <wieser.eric@gmail.com>2018-02-08 22:41:09 -0800
commitff2e1bc0976210076d309f1cee4323352017d1fd (patch)
tree7adc0832cf10adce7df15fe49a4ca143318a6374
parent4cfac4067a27835de6b0ae204df0e8c91998c1f2 (diff)
downloadnumpy-ff2e1bc0976210076d309f1cee4323352017d1fd.tar.gz
MAINT: Push no-op type promotion check further down
This does mean we do a redundant refcount change, but that's a small price to pay
-rw-r--r--numpy/core/src/multiarray/convert_datatype.c86
1 files changed, 33 insertions, 53 deletions
diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c
index 6ff381862..00cb07335 100644
--- a/numpy/core/src/multiarray/convert_datatype.c
+++ b/numpy/core/src/multiarray/convert_datatype.c
@@ -1002,6 +1002,17 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
{
int type_num1, type_num2, ret_type_num;
+ /*
+ * Fast path for identical dtypes.
+ *
+ * Non-native-byte-order types are converted to native ones below, so we
+ * can't quit early.
+ */
+ if (type1 == type2 && PyArray_ISNBO(type1->byteorder)) {
+ Py_INCREF(type1);
+ return type1;
+ }
+
type_num1 = type1->type_num;
type_num2 = type2->type_num;
@@ -1296,6 +1307,8 @@ PyArray_PromoteTypes(PyArray_Descr *type1, PyArray_Descr *type2)
/*
* Produces the smallest size and lowest kind type to which all
* input types can be cast.
+ *
+ * Equivalent to functools.reduce(PyArray_PromoteTypes, types)
*/
NPY_NO_EXPORT PyArray_Descr *
PyArray_PromoteTypeSequence(PyArray_Descr **types, npy_intp ntypes)
@@ -1309,16 +1322,11 @@ PyArray_PromoteTypeSequence(PyArray_Descr **types, npy_intp ntypes)
ret = types[0];
Py_INCREF(ret);
for (i = 1; i < ntypes; ++i) {
- PyArray_Descr *type = types[i];
-
- /* Only call promote if the types aren't the same dtype */
- if (type != ret || !PyArray_ISNBO(type->byteorder)) {
- PyArray_Descr *tmp = PyArray_PromoteTypes(type, ret);
- Py_DECREF(ret);
- ret = tmp;
- if (ret == NULL) {
- return NULL;
- }
+ PyArray_Descr *tmp = PyArray_PromoteTypes(types[i], ret);
+ Py_DECREF(ret);
+ ret = tmp;
+ if (ret == NULL) {
+ return NULL;
}
}
return ret;
@@ -1698,7 +1706,7 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
{
npy_intp i;
int use_min_scalar = 0;
- PyArray_Descr *ret = NULL, *tmpret;
+ PyArray_Descr *ret = NULL;
int ret_is_small_unsigned = 0;
/* If there's just one type, pass it through */
@@ -1794,30 +1802,15 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
ret_is_small_unsigned = tmp_is_small_unsigned;
}
else {
-#if 0
- printf("promoting type ");
- PyObject_Print(tmp, stdout, 0);
- printf(" (%d) ", tmp_is_small_unsigned);
- PyObject_Print(ret, stdout, 0);
- printf(" (%d) ", ret_is_small_unsigned);
- printf("\n");
-#endif
- /* If they point to the same type, don't call promote */
- if (tmp == ret && PyArray_ISNBO(tmp->byteorder)) {
- Py_DECREF(tmp);
- }
- else {
- tmpret = promote_types(tmp, ret, tmp_is_small_unsigned,
- ret_is_small_unsigned);
- if (tmpret == NULL) {
- Py_DECREF(tmp);
- Py_DECREF(ret);
- return NULL;
- }
- Py_DECREF(tmp);
- Py_DECREF(ret);
- ret = tmpret;
+ PyArray_Descr *tmpret = promote_types(
+ tmp, ret, tmp_is_small_unsigned, ret_is_small_unsigned);
+ Py_DECREF(tmp);
+ Py_DECREF(ret);
+ ret = tmpret;
+ if (ret == NULL) {
+ return NULL;
}
+
ret_is_small_unsigned = tmp_is_small_unsigned &&
ret_is_small_unsigned;
}
@@ -1831,25 +1824,12 @@ PyArray_ResultType(npy_intp narrs, PyArrayObject **arr,
Py_INCREF(ret);
}
else {
- /* Only call promote if the types aren't the same dtype */
- if (tmp != ret || !PyArray_ISNBO(tmp->byteorder)) {
- if (ret_is_small_unsigned) {
- tmpret = promote_types(tmp, ret, 0,
- ret_is_small_unsigned);
- if (tmpret == NULL) {
- Py_DECREF(tmp);
- Py_DECREF(ret);
- return NULL;
- }
- }
- else {
- tmpret = PyArray_PromoteTypes(tmp, ret);
- }
- Py_DECREF(ret);
- ret = tmpret;
- if (ret == NULL) {
- return NULL;
- }
+ PyArray_Descr *tmpret = promote_types(
+ tmp, ret, 0, ret_is_small_unsigned);
+ Py_DECREF(ret);
+ ret = tmpret;
+ if (ret == NULL) {
+ return NULL;
}
}
}