diff options
Diffstat (limited to 'numpy')
-rw-r--r-- | numpy/core/include/numpy/experimental_dtype_api.h | 6 | ||||
-rw-r--r-- | numpy/core/src/multiarray/array_method.h | 8 | ||||
-rw-r--r-- | numpy/core/src/umath/legacy_array_method.c | 11 | ||||
-rw-r--r-- | numpy/core/src/umath/reduction.c | 8 |
4 files changed, 20 insertions, 13 deletions
diff --git a/numpy/core/include/numpy/experimental_dtype_api.h b/numpy/core/include/numpy/experimental_dtype_api.h index a1418e929..86ad15f37 100644 --- a/numpy/core/include/numpy/experimental_dtype_api.h +++ b/numpy/core/include/numpy/experimental_dtype_api.h @@ -332,11 +332,13 @@ typedef int (PyArrayMethod_StridedLoop)(PyArrayMethod_Context *context, * * @param context The arraymethod context, mainly to access the descriptors. * @param reduction_is_empty Whether the reduction is empty. When it is, the - * default value for the identity might differ, for example: + * value returned may differ. In this case it is a "default" value that + * may differ from the "identity" value normally used. For example: * - `0.0` is the default for `sum([])`. But `-0.0` is the correct * identity otherwise as it preserves the sign for `sum([-0.0])`. * - We use no identity for object, but return the default of `0` and `1` - for the empty `sum([], dtype=object)` and `prod([], dtype=object)`. + * for the empty `sum([], dtype=object)` and `prod([], dtype=object)`. + * This allows `np.sum(np.array(["a", "b"], dtype=object))` to work. * - `-inf` or `INT_MIN` for `max` is an identity, but at least `INT_MIN` * not a good *default* when there are no items. * @param initial Pointer to initial data to be filled (if possible) diff --git a/numpy/core/src/multiarray/array_method.h b/numpy/core/src/multiarray/array_method.h index 694c342d3..732f711bc 100644 --- a/numpy/core/src/multiarray/array_method.h +++ b/numpy/core/src/multiarray/array_method.h @@ -109,11 +109,13 @@ typedef int (get_loop_function)( * * @param context The arraymethod context, mainly to access the descriptors. * @param reduction_is_empty Whether the reduction is empty. When it is, the - * default value for the identity might differ, for example: + * value returned may differ. In this case it is a "default" value that + * may differ from the "identity" value normally used. For example: * - `0.0` is the default for `sum([])`. But `-0.0` is the correct * identity otherwise as it preserves the sign for `sum([-0.0])`. * - We use no identity for object, but return the default of `0` and `1` - for the empty `sum([], dtype=object)` and `prod([], dtype=object)`. + * for the empty `sum([], dtype=object)` and `prod([], dtype=object)`. + * This allows `np.sum(np.array(["a", "b"], dtype=object))` to work. * - `-inf` or `INT_MIN` for `max` is an identity, but at least `INT_MIN` * not a good *default* when there are no items. * @param initial Pointer to initial data to be filled (if possible) @@ -226,7 +228,7 @@ typedef struct PyArrayMethodObject_tag { PyArray_DTypeMeta **wrapped_dtypes; translate_given_descrs_func *translate_given_descrs; translate_loop_descrs_func *translate_loop_descrs; - /* Chunk used by the legacy fallback arraymethod mainly */ + /* Chunk reserved for use by the legacy fallback arraymethod */ char initial[sizeof(npy_clongdouble)]; /* initial value storage */ } PyArrayMethodObject; diff --git a/numpy/core/src/umath/legacy_array_method.c b/numpy/core/src/umath/legacy_array_method.c index c0ac18b03..ab8b4b52b 100644 --- a/numpy/core/src/umath/legacy_array_method.c +++ b/numpy/core/src/umath/legacy_array_method.c @@ -239,7 +239,8 @@ get_wrapped_legacy_ufunc_loop(PyArrayMethod_Context *context, /* * We can shave off a bit of time by just caching the initial and this is - * trivial for all numeric types. (Wrapped ufuncs never use byte-swapping.) + * trivial for all internal numeric types. (Wrapped ufuncs never use + * byte-swapping.) */ static int copy_cached_initial( @@ -255,10 +256,10 @@ copy_cached_initial( * The default `get_reduction_initial` attempts to look up the identity * from the calling ufunc. This might fail, so we only call it when necessary. * - * For our numbers, we can easily cache it, so do so after the first call - * by overriding the function with `copy_cache_initial`. This path is not - * publically available. That could be added, and for a custom initial getter - * it will usually be static/compile time data anyway. + * For internal number dtypes, we can easily cache it, so do so after the + * first call by overriding the function with `copy_cache_initial`. + * This path is not publically available. That could be added, and for a + * custom initial getter it should be static/compile time data anyway. */ static int get_initial_from_ufunc( diff --git a/numpy/core/src/umath/reduction.c b/numpy/core/src/umath/reduction.c index 23127024b..9416e9a29 100644 --- a/numpy/core/src/umath/reduction.c +++ b/numpy/core/src/umath/reduction.c @@ -292,9 +292,11 @@ PyUFunc_ReduceWrapper(PyArrayMethod_Context *context, result = NpyIter_GetOperandArray(iter)[0]; /* - * Get the initial value (if it may exists). If the iteration is empty - * then we assume the reduction is (in the other case, we do not need - * the initial value anyway). + * Get the initial value (if it exists). If the iteration is empty + * then we assume the reduction is also empty. The reason is that when + * the outer iteration is empty we just won't use the initial value + * in any case. (`np.sum(np.zeros((0, 3)), axis=0)` is a length 3 + * reduction but has an empty result.) */ if ((initial == NULL && context->method->get_reduction_initial == NULL) || initial == Py_None) { |