8000 ENH: umath: Switch PyUFunc_Reduce to call PyArray_ReduceWrapper to si… · numpy/numpy@9b4ff64 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9b4ff64

Browse files
committed
ENH: umath: Switch PyUFunc_Reduce to call PyArray_ReduceWrapper to simplify code
1 parent 3ad0cd8 commit 9b4ff64

File tree

10 files changed

+480
-621
lines changed

10 files changed

+480
-621
lines changed

numpy/core/code_generators/generate_umath.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ def english_upper(s):
238238
'add' :
239239
Ufunc(2, 1, Zero,
240240
docstrings.get('numpy.core.umath.add'),
241-
'PyUFunc_AdditionTypeResolution',
241+
'PyUFunc_AdditionTypeResolver',
242242
TD(notimes_or_obj),
243243
[TypeDescription('M', FullTypeDescr, 'Mm', 'M'),
244244
TypeDescription('m', FullTypeDescr, 'mm', 'm'),
@@ -249,7 +249,7 @@ def english_upper(s):
249249
'subtract' :
250250
Ufunc(2, 1, None, # Zero is only a unit to the right, not the left
251251
docstrings.get('numpy.core.umath.subtract'),
252-
'PyUFunc_SubtractionTypeResolution',
252+
'PyUFunc_SubtractionTypeResolver',
253253
TD(notimes_or_obj),
254254
[TypeDescription('M', FullTypeDescr, 'Mm', 'M'),
255255
TypeDescription('m', FullTypeDescr, 'mm', 'm'),
@@ -260,7 +260,7 @@ def english_upper(s):
260260
'multiply' :
261261
Ufunc(2, 1, One,
262262
docstrings.get('numpy.core.umath.multiply'),
263-
'PyUFunc_MultiplicationTypeResolution',
263+
'PyUFunc_MultiplicationTypeResolver',
264264
TD(notimes_or_obj),
265265
[TypeDescription('m', FullTypeDescr, 'mq', 'm'),
266266
TypeDescription('m', FullTypeDescr, 'qm', 'm'),
@@ -272,7 +272,7 @@ def english_upper(s):
272272
'divide' :
273273
Ufunc(2, 1, None, # One is only a unit to the right, not the left
274274
docstrings.get('numpy.core.umath.divide'),
275-
'PyUFunc_DivisionTypeResolution',
275+
'PyUFunc_DivisionTypeResolver',
276276
TD(intfltcmplx),
277277
[TypeDescription('m', FullTypeDescr, 'mq', 'm'),
278278
TypeDescription('m', FullTypeDescr, 'md', 'm'),
@@ -283,7 +283,7 @@ def english_upper(s):
283283
'floor_divide' :
284284
Ufunc(2, 1, None, # One is only a unit to the right, not the left
285285
docstrings.get('numpy.core.umath.floor_divide'),
286-
'PyUFunc_DivisionTypeResolution',
286+
'PyUFunc_DivisionTypeResolver',
287287
TD(intfltcmplx),
288288
[TypeDescription('m', FullTypeDescr, 'mq', 'm'),
289289
TypeDescription('m', FullTypeDescr, 'md', 'm'),
@@ -293,7 +293,7 @@ def english_upper(s):
293293
'true_divide' :
294294
Ufunc(2, 1, None, # One is only a unit to the right, not the left
295295
docstrings.get('numpy.core.umath.true_divide'),
296-
'PyUFunc_DivisionTypeResolution',
296+
'PyUFunc_DivisionTypeResolver',
297297
TD('bBhH', out='d'),
298298
TD('iIlLqQ', out='d'),
299299
TD(flts+cmplx),
@@ -336,7 +336,7 @@ def english_upper(s):
336336
'_ones_like' :
337337
Ufunc(1, 1, None,
338338
docstrings.get('numpy.core.umath._ones_like'),
339-
'PyUFunc_OnesLikeTypeResolution',
339+
'PyUFunc_OnesLikeTypeResolver',
340340
TD(noobj),
341341
TD(O, f='Py_get_one'),
342342
),
@@ -351,7 +351,7 @@ def english_upper(s):
351351
'absolute' :
352352
Ufunc(1, 1, None,
353353
docstrings.get('numpy.core.umath.absolute'),
354-
'PyUFunc_AbsoluteTypeResolution',
354+
'PyUFunc_AbsoluteTypeResolver',
355355
TD(bints+flts+timedeltaonly),
356356
TD(cmplx, out=('f', 'd', 'g')),
357357
TD(O, f='PyNumber_Absolute'),
@@ -365,21 +365,21 @@ def english_upper(s):
365365
'negative' :
366366
Ufunc(1, 1, None,
367367
docstrings.get('numpy.core.umath.negative'),
368-
'PyUFunc_SimpleUnaryOperationTypeResolution',
368+
'PyUFunc_SimpleUnaryOperationTypeResolver',
369369
TD(bints+flts+timedeltaonly),
370370
TD(cmplx, f='neg'),
371371
TD(O, f='PyNumber_Negative'),
372372
),
373373
'sign' :
374374
Ufunc(1, 1, None,
375375
docstrings.get('numpy.core.umath.sign'),
376-
'PyUFunc_SimpleUnaryOperationTypeResolution',
376+
'PyUFunc_SimpleUnaryOperationTypeResolver',
377377
TD(nobool_or_datetime),
378378
),
379379
'greater' :
380380
Ufunc(2, 1, None,
381381
docstrings.get('numpy.core.umath.greater'),
382-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
382+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
383383
TD(all, out='?'),
384384
),
385385
'greater_equal' :
@@ -391,31 +391,31 @@ def english_upper(s):
391391
'less' :
392392
Ufunc(2, 1, None,
393393
docstrings.get('numpy.core.umath.less'),
394-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
394+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
395395
TD(all, out='?'),
396396
),
397397
'less_equal' :
398398
Ufunc(2, 1, None,
399399
docstrings.get('numpy.core.umath.less_equal'),
400-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
400+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
401401
TD(all, out='?'),
402402
),
403403
'equal' :
404404
Ufunc(2, 1, None,
405405
docstrings.get('numpy.core.umath.equal'),
406-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
406+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
407407
TD(all, out='?'),
408408
),
409409
'not_equal' :
410410
Ufunc(2, 1, None,
411411
docstrings.get('numpy.core.umath.not_equal'),
412-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
412+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
413413
TD(all, out='?'),
414414
),
415415
'logical_and' :
416416
Ufunc(2, 1, One,
417417
docstrings.get('numpy.core.umath.logical_and'),
418-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
418+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
419419
TD(nodatetime_or_obj, out='?'),
420420
TD(O, f='npy_ObjectLogicalAnd'),
421421
),
@@ -429,42 +429,42 @@ def english_upper(s):
429429
'logical_or' :
430430
Ufunc(2, 1, Zero,
431431
docstrings.get('numpy.core.umath.logical_or'),
432-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
432+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
433433
TD(nodatetime_or_obj, out='?'),
434434
TD(O, f='npy_ObjectLogicalOr'),
435435
),
436436
'logical_xor' :
437437
Ufunc(2, 1, None,
438438
docstrings.get('numpy.core.umath.logical_xor'),
439-
'PyUFunc_SimpleBinaryComparisonTypeResolution',
439+
'PyUFunc_SimpleBinaryComparisonTypeResolver',
440440
TD(nodatetime_or_obj, out='?'),
441441
TD(P, f='logical_xor'),
442442
),
443443
'maximum' :
444444
Ufunc(2, 1, ReorderableNone,
445445
docstrings.get('numpy.core.umath.maximum'),
446-
'PyUFunc_SimpleBinaryOperationTypeResolution',
446+
'PyUFunc_SimpleBinaryOperationTypeResolver',
447447
TD(noobj),
448448
TD(O, f='npy_ObjectMax')
449449
),
450450
'minimum' :
451451
Ufunc(2, 1, ReorderableNone,
452452
docstrings.get('numpy.core.umath.minimum'),
453-
'PyUFunc_SimpleBinaryOperationTypeResolution',
453+
'PyUFunc_SimpleBinaryOperationTypeResolver',
454454
TD(noobj),
455455
TD(O, f='npy_ObjectMin')
456456
),
457457
'fmax' :
458458
Ufunc(2, 1, ReorderableNone,
459459
docstrings.get('numpy.core.umath.fmax'),
460-
'PyUFunc_SimpleBinaryOperationTypeResolution',
460+
'PyUFunc_SimpleBinaryOperationTypeResolver',
461461
TD(noobj),
462462
TD(O, f='npy_ObjectMax')
463463
),
464464
'fmin' :
465465
Ufunc(2, 1, ReorderableNone,
466466
docstrings.get('numpy.core.umath.fmin'),
467-
'PyUFunc_SimpleBinaryOperationTypeResolution',
467+
'PyUFunc_SimpleBinaryOperationTypeResolver',
468468
TD(noobj),
469469
TD(O, f='npy_ObjectMin')
470470
),
@@ -928,7 +928,7 @@ def make_ufuncs(funcdict):
928928
name, docstring))
929929
if uf.typereso != None:
930930
mlist.append(
931-
r"((PyUFuncObject *)f)->type_resolution_function = &%s;" %
931+
r"((PyUFuncObject *)f)->type_resolver = &%s;" %
932932
uf.typereso)
933933
mlist.append(r"""PyDict_SetItemString(dictionary, "%s", f);""" % name)
934934
mlist.append(r"""Py_DECREF(f);""")

numpy/core/code_generators/numpy_api.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@
385385
'PyUFunc_ee_e_As_ff_f': 37,
386386
'PyUFunc_ee_e_As_dd_d': 38,
387387
# End 1.6 API
388-
'PyUFunc_DefaultTypeResolution': 39,
388+
'PyUFunc_DefaultTypeResolver': 39,
389389
'PyUFunc_ValidateCasting': 40,
390390
}
391391

numpy/core/include/numpy/ndarraytypes.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1787,7 +1787,7 @@ typedef struct {
17871787
************************************************************/
17881788

17891789
/*
1790-
* This is a function for assigning a reduction unit to the result,
1790+
* This is a function for assigning a reduction identity to the result,
17911791
* before doing the reduction computation. If 'preservena' is True,
17921792
* any masked NA values in 'result' should not be overwritten. The
17931793
* value in 'data' is passed through from PyArray_ReduceWrapper.
@@ -1797,30 +1797,30 @@ typedef struct {
17971797
*
17981798
* It should return -1 on failure, or 0 on success.
17991799
*/
1800-
typedef int (PyArray_AssignReduceUnitFunc)(PyArrayObject *result,
1800+
typedef int (PyArray_AssignReduceIdentityFunc)(PyArrayObject *result,
18011801
int preservena, void *data);
18021802

18031803
/*
1804-
* This is a function for the inner reduce loop. Both the unmasked and
1804+
* This is a function for the reduce loop. Both the unmasked and
18051805
* masked variants have the same prototype, but should behave differently.
18061806
*
18071807
* The needs_api parameter indicates whether it's ok to release the GIL during
1808-
* the inner loop, such as when the iternext() function never calls
1808+
* the loop, such as when the iternext() function never calls
18091809
* a function which could raise a Python exception.
18101810
*
18111811
* Ths skip_first_count parameter indicates how many elements need to be
18121812
* skipped based on NpyIter_IsFirstVisit checks. This can only be positive
1813-
* when the 'assign_unit' parameter was NULL when calling
1813+
* when the 'assign_identity' parameter was NULL when calling
18141814
* PyArray_ReduceWrapper.
18151815
*
1816-
* The unmasked inner loop gets two data pointers and two strides, and should
1816+
* The unmasked loop gets two data pointers and two strides, and should
18171817
* look roughly like this:
18181818
* {
18191819
* NPY_BEGIN_THREADS_DEF;
18201820
* if (!needs_api) {
18211821
* NPY_BEGIN_THREADS;
18221822
* }
1823-
* // This first-visit loop can be skipped if 'assign_unit' was non-NULL
1823+
* // This first-visit loop can be skipped if 'assign_identity' was non-NULL
18241824
* if (skip_first_count > 0) {
18251825
* do {
18261826
* char *data0 = dataptr[0], *data1 = dataptr[1];
@@ -1878,8 +1878,8 @@ typedef int (PyArray_AssignReduceUnitFunc)(PyArrayObject *result,
18781878
* return (needs_api && PyErr_Occurred()) ? -1 : 0;
18791879
* }
18801880
*
1881-
* The masked inner loop gets three data pointers and three strides, and
1882-
* looks identical except for the iteration inner loops which should be
1881+
* The masked loop gets three data pointers and three strides, and
1882+
* looks identical except for the iteration loops which should be
18831883
* like this:
18841884
* do {
18851885
* char *data0 = dataptr[0], *data1 = dataptr[1], *data2 = dataptr[2];
@@ -1907,7 +1907,7 @@ typedef int (PyArray_AssignReduceUnitFunc)(PyArrayObject *result,
19071907
* to check if an error occurred during processing, and return -1 for
19081908
* error, 0 for success.
19091909
*/
1910-
typedef int (PyArray_ReduceInnerLoopFunc)(NpyIter *iter,
1910+
typedef int (PyArray_ReduceLoopFunc)(NpyIter *iter,
19111911
char **dataptr,
19121912
npy_intp *strideptr,
19131913
npy_intp *countptr,

numpy/core/include/numpy/ufuncobject.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ typedef void (PyUFunc_MaskedStridedInnerLoopFunc)(
3838
npy_intp count,
3939
NpyAuxData *innerloopdata);
4040

41-
/* Forward declaration for the type resolution function */
41+
/* Forward declaration for the type resolver and loop selector typedefs */
4242
struct _tagPyUFuncObject;
4343

4444
/*
@@ -99,25 +99,31 @@ typedef int (PyUFunc_TypeResolutionFunc)(
9999
* loop for the given type.
100100
* out_innerloopdata: Should be populated with the void* data to
101101
* be passed into the out_innerloop function.
102+
* out_needs_api: If the inner loop needs to use the Python API,
103+
* should set the to 1, otherwise should leave
104+
* this untouched.
102105
*/
103106
typedef int (PyUFunc_LegacyInnerLoopSelectionFunc)(
104107
struct _tagPyUFuncObject *ufunc,
105108
PyArray_Descr **dtypes,
106109
PyUFuncGenericFunction *out_innerloop,
107-
void **out_innerloopdata);
110+
void **out_innerloopdata,
111+
int *out_needs_api);
108112
typedef int (PyUFunc_InnerLoopSelectionFunc)(
109113
struct _tagPyUFuncObject *ufunc,
110114
PyArray_Descr **dtypes,
111115
npy_intp *fixed_strides,
112116
PyUFunc_StridedInnerLoopFunc **out_innerloop,
113-
NpyAuxData **out_innerloopdata);
117+
NpyAuxData **out_innerloopdata,
118+
int *out_needs_api);
114119
typedef int (PyUFunc_MaskedInnerLoopSelectionFunc)(
115120
struct _tagPyUFuncObject *ufunc,
116121
PyArray_Descr **dtypes,
117122
npy_intp *fixed_strides,
118123
npy_intp fixed_mask_stride,
119124
PyUFunc_MaskedStridedInnerLoopFunc **out_innerloop,
120-
NpyAuxData **out_innerloopdata);
125+
NpyAuxData **out_innerloopdata,
126+
int *out_needs_api);
121127

122128
typedef struct _tagPyUFuncObject {
123129
PyObject_HEAD
@@ -185,7 +191,7 @@ typedef struct _tagPyUFuncObject {
185191
* A function which resolves the types and fills an array
186192
* with the dtypes for the inputs and outputs.
187193
*/
188-
PyUFunc_TypeResolutionFunc *type_resolution_function;
194+
PyUFunc_TypeResolutionFunc *type_resolver;
189195
/*
190196
* A function which returns an inner loop written for
191197
* NumPy 1.6 and earlier ufuncs. This is for backwards

numpy/core/src/multiarray/item_selection.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1893,15 +1893,15 @@ count_boolean_trues(int ndim, char *data, npy_intp *ashape, npy_intp *astrides)
18931893
}
18941894

18951895
static int
1896-
assign_reduce_unit_zero(PyArrayObject *result, int preservena, void *data)
1896+
assign_reduce_identity_zero(PyArrayObject *result, int preservena, void *data)
18971897
{
18981898
return PyArray_AssignZero(result, NULL, preservena, NULL);
18991899
}
19001900

19011901
static int
1902-
reduce_count_nonzero_inner_loop(NpyIter *iter,
1902+
reduce_count_nonzero_loop(NpyIter *iter,
19031903
char **dataptr,
1904-
npy_intp *strideptr,
1904+
npy_intp *strides,
19051905
npy_intp *countptr,
19061906
NpyIter_IterNextFunc *iternext,
19071907
int needs_api,
@@ -1919,7 +1919,7 @@ reduce_count_nonzero_inner_loop(NpyIter *iter,
19191919

19201920
do {
19211921
char *data0 = dataptr[0], *data1 = dataptr[1];
1922-
npy_intp stride0 = strideptr[0], stride1 = strideptr[1];
1922+
npy_intp stride0 = strides[0], stride1 = strides[1];
19231923
npy_intp count = *countptr;
19241924

19251925
while (count--) {
@@ -1939,9 +1939,9 @@ reduce_count_nonzero_inner_loop(NpyIter *iter,
19391939
}
19401940

19411941
static int
1942-
reduce_count_nonzero_masked_inner_loop(NpyIter *iter,
1942+
reduce_count_nonzero_masked_loop(NpyIter *iter,
19431943
char **dataptr,
1944-
npy_intp *strideptr,
1944+
npy_intp *strides,
19451945
npy_intp *countptr,
19461946
NpyIter_IterNextFunc *iternext,
19471947
int needs_api,
@@ -1959,8 +1959,8 @@ reduce_count_nonzero_masked_inner_loop(NpyIter *iter,
19591959

19601960
do {
19611961
char *data0 = dataptr[0], *data1 = dataptr[1], *data2 = dataptr[2];
1962-
npy_intp stride0 = strideptr[0], stride1 = strideptr[1],
1963-
stride2 = strideptr[2];
1962+
npy_intp stride0 = strides[0], stride1 = strides[1],
1963+
stride2 = strides[2];
19641964
npy_intp count = *countptr;
19651965

19661966
while (count--) {
@@ -2011,10 +2011,11 @@ PyArray_ReduceCountNonzero(PyArrayObject *arr, PyArrayObject *out,
20112011

20122012
result = PyArray_ReduceWrapper(arr, out,
20132013
PyArray_DESCR(arr), dtype,
2014+
NPY_SAME_KIND_CASTING,
20142015
axis_flags, 1, skipna, keepdims,
2015-
&assign_reduce_unit_zero,
2016-
&reduce_count_nonzero_inner_loop,
2017-
&reduce_count_nonzero_masked_inner_loop,
2016+
&assign_reduce_identity_zero,
2017+
&reduce_count_nonzero_loop,
2018+
&reduce_count_nonzero_masked_loop,
20182019
nonzero, 0, "count_nonzero");
20192020
Py_DECREF(dtype);
20202021
if (out == NULL && result != NULL) {

0 commit comments

Comments
 (0)
0