numpy  2.0.0
src/umath/reduction.h File Reference

Go to the source code of this file.

Typedefs

typedef int( PyArray_AssignReduceIdentityFunc )(PyArrayObject *result, void *data)
typedef int( PyArray_ReduceLoopFunc )(NpyIter *iter, char **dataptr, npy_intp *strideptr, npy_intp *countptr, NpyIter_IterNextFunc *iternext, int needs_api, npy_intp skip_first_count, void *data)

Functions

NPY_NO_EXPORT PyArrayObjectPyUFunc_ReduceWrapper (PyArrayObject *operand, PyArrayObject *out, PyArrayObject *wheremask, PyArray_Descr *operand_dtype, PyArray_Descr *result_dtype, NPY_CASTING casting, npy_bool *axis_flags, int reorderable, int keepdims, int subok, PyArray_AssignReduceIdentityFunc *assign_identity, PyArray_ReduceLoopFunc *loop, void *data, npy_intp buffersize, const char *funcname)

Typedef Documentation

typedef int( PyArray_AssignReduceIdentityFunc)(PyArrayObject *result, void *data)

Typedefs used by PyArray_ReduceWrapper, new in 1.7.

This is a function for assigning a reduction identity to the result, before doing the reduction computation. The value in 'data' is passed through from PyArray_ReduceWrapper.

This function could, for example, simply be a call like
return PyArray_AssignZero(result, NULL, NULL);
It should return -1 on failure, or 0 on success.
typedef int( PyArray_ReduceLoopFunc)(NpyIter *iter, char **dataptr, npy_intp *strideptr, npy_intp *countptr, NpyIter_IterNextFunc *iternext, int needs_api, npy_intp skip_first_count, void *data)
This is a function for the reduce loop.
The needs_api parameter indicates whether it's ok to release the GIL during the loop, such as when the iternext() function never calls a function which could raise a Python exception.
Ths skip_first_count parameter indicates how many elements need to be skipped based on NpyIter_IsFirstVisit checks. This can only be positive when the 'assign_identity' parameter was NULL when calling PyArray_ReduceWrapper.
The loop gets two data pointers and two strides, and should look roughly like this:

System Message: ERROR/3 (<string>, line 14) Unexpected indentation.

<blockquote>

{

NPY_BEGIN_THREADS_DEF; if (!needs_api) {

System Message: ERROR/3 (<string>, line 17) Unexpected indentation.

<blockquote> NPY_BEGIN_THREADS;</blockquote>

System Message: WARNING/2 (<string>, line 18) Block quote ends without a blank line; unexpected unindent.

} This first-visit loop can be skipped if 'assign_identity' was non-NULL if (skip_first_count > 0) {

System Message: ERROR/3 (<string>, line 21) Unexpected indentation.

<blockquote>

do {

char *data0 = dataptr[0], *data1 = dataptr[1]; npy_intp stride0 = strideptr[0], stride1 = strideptr[1]; npy_intp count = *countptr;

System Message: WARNING/2 (<string>, line 22); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 22); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 22); backlink Inline emphasis start-string without end-string.

// Skip any first-visit elements if (NpyIter_IsFirstVisit(iter, 0)) {

System Message: ERROR/3 (<string>, line 28) Unexpected indentation.

<blockquote>

if (stride0 == 0) {
--count; --skip_first_count; data1 += stride1;
System Message: WARNING/2 (<string>, line 32) Definition list ends without a blank line; unexpected unindent.

} else {

System Message: ERROR/3 (<string>, line 34) Unexpected indentation.

<blockquote> skip_first_count -= count; count = 0;</blockquote>

System Message: WARNING/2 (<string>, line 36) Block quote ends without a blank line; unexpected unindent.

} </blockquote>

System Message: WARNING/2 (<string>, line 37) Block quote ends without a blank line; unexpected unindent.

}

while (count--) {
*(result_t *)data0 = my_reduce_op(*(result_t *)data0,
System Message: WARNING/2 (<string>, line 40); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 40); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 40); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 40); backlink Inline emphasis start-string without end-string.

*(operand_t *)data1);

System Message: WARNING/2 (<string>, line 41); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 41); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 42) Definition list ends without a blank line; unexpected unindent.

data0 += stride0; data1 += stride1;

System Message: WARNING/2 (<string>, line 44) Definition list ends without a blank line; unexpected unindent.

}

// Jump to the faster loop when skipping is done if (skip_first_count == 0) {

System Message: ERROR/3 (<string>, line 48) Unexpected indentation.

<blockquote>

if (iternext(iter)) {
break;
System Message: WARNING/2 (<string>, line 50) Definition list ends without a blank line; unexpected unindent.

} else {

System Message: ERROR/3 (<string>, line 52) Unexpected indentation.

<blockquote> goto finish_loop;</blockquote>

System Message: WARNING/2 (<string>, line 53) Block quote ends without a blank line; unexpected unindent.

} </blockquote>

System Message: WARNING/2 (<string>, line 54) Block quote ends without a blank line; unexpected unindent.

}

System Message: WARNING/2 (<string>, line 55) Definition list ends without a blank line; unexpected unindent.

} while (iternext(iter)); </blockquote>

System Message: WARNING/2 (<string>, line 56) Block quote ends without a blank line; unexpected unindent.

} do {

System Message: ERROR/3 (<string>, line 58) Unexpected indentation.

<blockquote>

char *data0 = dataptr[0], *data1 = dataptr[1]; npy_intp stride0 = strideptr[0], stride1 = strideptr[1]; npy_intp count = *countptr;

System Message: WARNING/2 (<string>, line 58); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 58); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 58); backlink Inline emphasis start-string without end-string.
while (count--) {
*(result_t *)data0 = my_reduce_op(*(result_t *)data0,
System Message: WARNING/2 (<string>, line 63); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 63); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 63); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 63); backlink Inline emphasis start-string without end-string.

*(operand_t *)data1);

System Message: WARNING/2 (<string>, line 64); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 64); backlink Inline emphasis start-string without end-string.
System Message: WARNING/2 (<string>, line 65) Definition list ends without a blank line; unexpected unindent.

data0 += stride0; data1 += stride1;

System Message: WARNING/2 (<string>, line 67) Definition list ends without a blank line; unexpected unindent.

} </blockquote>

System Message: WARNING/2 (<string>, line 68) Block quote ends without a blank line; unexpected unindent.

} while (iternext(iter));

finish_loop:
if (!needs_api) {
NPY_END_THREADS;
System Message: WARNING/2 (<string>, line 72) Definition list ends without a blank line; unexpected unindent.

} return (needs_api && PyErr_Occurred()) ? -1 : 0;

System Message: WARNING/2 (<string>, line 74) Definition list ends without a blank line; unexpected unindent.
} </blockquote>
If needs_api is True, this function should call PyErr_Occurred() to check if an error occurred during processing, and return -1 for error, 0 for success.

Function Documentation

NPY_NO_EXPORT PyArrayObject* PyUFunc_ReduceWrapper ( PyArrayObject operand,
PyArrayObject out,
PyArrayObject wheremask,
PyArray_Descr operand_dtype,
PyArray_Descr result_dtype,
NPY_CASTING  casting,
npy_bool axis_flags,
int  reorderable,
int  keepdims,
int  subok,
PyArray_AssignReduceIdentityFunc assign_identity,
PyArray_ReduceLoopFunc loop,
void *  data,
npy_intp  buffersize,
const char *  funcname 
)
This function executes all the standard NumPy reduction function boilerplate code, just calling assign_identity and the appropriate inner loop function where necessary.
operand : The array to be reduced. out : NULL, or the array into which to place the result. wheremask : NOT YET SUPPORTED, but this parameter is placed here

System Message: ERROR/3 (<string>, line 8) Unexpected indentation.

<blockquote> so that support can be added in the future without breaking API compatibility. Pass in NULL.</blockquote>

System Message: WARNING/2 (<string>, line 10) Block quote ends without a blank line; unexpected unindent.
operand_dtype : The dtype the inner loop expects for the operand. result_dtype : The dtype the inner loop expects for the result. casting : The casting rule to apply to the operands. axis_flags : Flags indicating the reduction axes of 'operand'. reorderable : If True, the reduction being done is reorderable, which

System Message: ERROR/3 (<string>, line 15) Unexpected indentation.

<blockquote> means specifying multiple axes of reduction at once is ok, and the reduction code may calculate the reduction in an arbitrary order. The calculation may be reordered because of cache behavior or multithreading requirements.</blockquote>

System Message: WARNING/2 (<string>, line 19) Block quote ends without a blank line; unexpected unindent.
keepdims : If true, leaves the reduction dimensions in the result
with size one.
subok : If true, the result uses the subclass of operand, otherwise
it is always a base class ndarray.
assign_identity : If NULL, PyArray_InitializeReduceResult is used, otherwise
this function is called to initialize the result to the reduction's unit.
System Message: WARNING/2 (<string>, line 26) Definition list ends without a blank line; unexpected unindent.
loop : The loop which does the reduction. data : Data which is passed to assign_identity and the inner loop. buffersize : Buffer size for the iterator. For the default, pass in 0. funcname : The name of the reduction function, for error messages.
This function executes all the standard NumPy reduction function boilerplate code, just calling assign_identity and the appropriate inner loop function where necessary.
operand : The array to be reduced. out : NULL, or the array into which to place the result. wheremask : NOT YET SUPPORTED, but this parameter is placed here

System Message: ERROR/3 (<string>, line 8) Unexpected indentation.

<blockquote> so that support can be added in the future without breaking API compatibility. Pass in NULL.</blockquote>

System Message: WARNING/2 (<string>, line 10) Block quote ends without a blank line; unexpected unindent.
operand_dtype : The dtype the inner loop expects for the operand. result_dtype : The dtype the inner loop expects for the result. casting : The casting rule to apply to the operands. axis_flags : Flags indicating the reduction axes of 'operand'. reorderable : If True, the reduction being done is reorderable, which

System Message: ERROR/3 (<string>, line 15) Unexpected indentation.

<blockquote> means specifying multiple axes of reduction at once is ok, and the reduction code may calculate the reduction in an arbitrary order. The calculation may be reordered because of cache behavior or multithreading requirements.</blockquote>

System Message: WARNING/2 (<string>, line 19) Block quote ends without a blank line; unexpected unindent.
keepdims : If true, leaves the reduction dimensions in the result
with size one.
subok : If true, the result uses the subclass of operand, otherwise
it is always a base class ndarray.
assign_identity : If NULL, PyArray_InitializeReduceResult is used, otherwise
this function is called to initialize the result to the reduction's unit.
System Message: WARNING/2 (<string>, line 26) Definition list ends without a blank line; unexpected unindent.
loop : The loop which does the reduction. data : Data which is passed to assign_identity and the inner loop. buffersize : Buffer size for the iterator. For the default, pass in 0. funcname : The name of the reduction function, for error messages.
TODO FIXME: if you squint, this is essentially an second independent implementation of generalized ufuncs with signature (i)->(), plus a few extra bells and whistles. (Indeed, as far as I can tell, it was originally split out to support a fancy version of count_nonzero... which is not actually a reduction function at all, it's just a (i)->() function!) So probably these two implementation should be merged into one. (In fact it would be quite nice to support axis= and keepdims etc. for arbitrary generalized ufuncs!)
Iterator parameters
Validate that the parameters for future expansion are NULL
This either conforms 'out' to the ndim of 'operand', or allocates a new array appropriate for this reduction.
Initialize the result to the reduction unit if possible, otherwise copy the initial values and get a view to the rest.
If this reduction is non-reorderable, make sure there are only 0 or 1 axes in axis_flags.
Set up the iterator
Straightforward reduction
Strip out the extra 'one' dimensions in the result