numpy  2.0.0
src/umath/ufunc_object.c File Reference
#include "Python.h"
#include "npy_config.h"
#include "npy_pycompat.h"
#include "numpy/arrayobject.h"
#include "numpy/ufuncobject.h"
#include "numpy/arrayscalars.h"
#include "lowlevel_strided_loops.h"
#include "ufunc_type_resolution.h"
#include "reduction.h"
#include "ufunc_object.h"

Data Structures

struct  _simple_cobj

Defines

#define _UMATHMODULE
#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define NPY_UF_DBG_TRACING   0
#define NPY_UF_DBG_PRINT(s)
#define NPY_UF_DBG_PRINT1(s, p1)
#define NPY_UF_DBG_PRINT2(s, p1, p2)
#define NPY_UF_DBG_PRINT3(s, p1, p2, p3)
#define USE_USE_DEFAULTS   1
#define HANDLEIT(NAME, str)
#define _GETATTR_(str, rstr)
#define _SETCPTR(cobj, val)   ((_simple_cobj *)(cobj))->c_obj = (val)

Functions

static int _does_loop_use_arrays (void *data)
static int _error_handler (int method, PyObject *errobj, char *errtype, int retstatus, int *first)
NPY_NO_EXPORT int PyUFunc_getfperr (void)
NPY_NO_EXPORT int PyUFunc_handlefperr (int errmask, PyObject *errobj, int retstatus, int *first)
NPY_NO_EXPORT int PyUFunc_checkfperr (int errmask, PyObject *errobj, int *first)
NPY_NO_EXPORT void PyUFunc_clearfperr ()
static void _find_array_prepare (PyObject *args, PyObject *kwds, PyObject **output_prep, int nin, int nout)
static int _extract_pyvals (PyObject *ref, char *name, int *bufsize, int *errmask, PyObject **errobj)
NPY_NO_EXPORT int PyUFunc_GetPyValues (char *name, int *bufsize, int *errmask, PyObject **errobj)
static int _has_reflected_op (PyObject *op, char *name)
static int _next_non_white_space (const char *str, int offset)
static int _is_alpha_underscore (char ch)
static int _is_alnum_underscore (char ch)
static int _get_end_of_name (const char *str, int offset)
static int _is_same_name (const char *s1, const char *s2)
static int _parse_signature (PyUFuncObject *ufunc, const char *signature)
static int get_ufunc_arguments (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds, PyArrayObject **out_op, NPY_ORDER *out_order, NPY_CASTING *out_casting, PyObject **out_extobj, PyObject **out_typetup, int *out_subok, PyArrayObject **out_wheremask)
static int check_for_trivial_loop (PyUFuncObject *ufunc, PyArrayObject **op, PyArray_Descr **dtype, npy_intp buffersize)
static void trivial_two_operand_loop (PyArrayObject **op, PyUFuncGenericFunction innerloop, void *innerloopdata)
static void trivial_three_operand_loop (PyArrayObject **op, PyUFuncGenericFunction innerloop, void *innerloopdata)
static int prepare_ufunc_output (PyUFuncObject *ufunc, PyArrayObject **op, PyObject *arr_prep, PyObject *arr_prep_args, int i)
static int iterator_loop (PyUFuncObject *ufunc, PyArrayObject **op, PyArray_Descr **dtype, NPY_ORDER order, npy_intp buffersize, PyObject **arr_prep, PyObject *arr_prep_args, PyUFuncGenericFunction innerloop, void *innerloopdata)
static int execute_legacy_ufunc_loop (PyUFuncObject *ufunc, int trivial_loop_ok, PyArrayObject **op, PyArray_Descr **dtypes, NPY_ORDER order, npy_intp buffersize, PyObject **arr_prep, PyObject *arr_prep_args)
static int execute_fancy_ufunc_loop (PyUFuncObject *ufunc, PyArrayObject *wheremask, PyArrayObject **op, PyArray_Descr **dtypes, NPY_ORDER order, npy_intp buffersize, PyObject **arr_prep, PyObject *arr_prep_args)
static PyObject * make_arr_prep_args (npy_intp nin, PyObject *args, PyObject *kwds)
static int PyUFunc_GeneralizedFunction (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds, PyArrayObject **op)
NPY_NO_EXPORT int PyUFunc_GenericFunction (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds, PyArrayObject **op)
static int get_binary_op_function (PyUFuncObject *ufunc, int *otype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
static int reduce_type_resolver (PyUFuncObject *ufunc, PyArrayObject *arr, PyArray_Descr *odtype, PyArray_Descr **out_dtype)
static int assign_reduce_identity_zero (PyArrayObject *result, void *data)
static int assign_reduce_identity_one (PyArrayObject *result, void *data)
static int reduce_loop (NpyIter *iter, char **dataptrs, npy_intp *strides, npy_intp *countptr, NpyIter_IterNextFunc *iternext, int needs_api, npy_intp skip_first_count, void *data)
static PyArrayObjectPyUFunc_Reduce (PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out, int naxes, int *axes, PyArray_Descr *odtype, int keepdims)
static PyObject * PyUFunc_Accumulate (PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out, int axis, int otype)
static PyObject * PyUFunc_Reduceat (PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *ind, PyArrayObject *out, int axis, int otype)
static PyObject * PyUFunc_GenericReduction (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds, int operation)
static void _find_array_wrap (PyObject *args, PyObject *kwds, PyObject **output_wrap, int nin, int nout)
static PyObject * ufunc_generic_call (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
NPY_NO_EXPORT PyObject * ufunc_geterr (PyObject *NPY_UNUSED(dummy), PyObject *args)
static int ufunc_update_use_defaults (void)
NPY_NO_EXPORT PyObject * ufunc_seterr (PyObject *NPY_UNUSED(dummy), PyObject *args)
NPY_NO_EXPORT int PyUFunc_ReplaceLoopBySignature (PyUFuncObject *func, PyUFuncGenericFunction newfunc, int *signature, PyUFuncGenericFunction *oldfunc)
NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndData (PyUFuncGenericFunction *func, void **data, char *types, int ntypes, int nin, int nout, int identity, char *name, char *doc, int check_return)
NPY_NO_EXPORT PyObject * PyUFunc_FromFuncAndDataAndSignature (PyUFuncGenericFunction *func, void **data, char *types, int ntypes, int nin, int nout, int identity, char *name, char *doc, int check_return, const char *signature)
NPY_NO_EXPORT int PyUFunc_SetUsesArraysAsData (void **data, size_t i)
static int cmp_arg_types (int *arg1, int *arg2, int n)
static NPY_INLINE void _free_loop1d_list (PyUFunc_Loop1d *data)
static void _loop1d_list_free (void *ptr)
NPY_NO_EXPORT int PyUFunc_RegisterLoopForType (PyUFuncObject *ufunc, int usertype, PyUFuncGenericFunction function, int *arg_types, void *data)
static void ufunc_dealloc (PyUFuncObject *ufunc)
static PyObject * ufunc_repr (PyUFuncObject *ufunc)
static PyObject * ufunc_outer (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
static PyObject * ufunc_reduce (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
static PyObject * ufunc_accumulate (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
static PyObject * ufunc_reduceat (PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
static PyObject * _makeargs (int num, char *ltr, int null_if_none)
static char _typecharfromnum (int num)
static PyObject * ufunc_get_doc (PyUFuncObject *ufunc)
static PyObject * ufunc_get_nin (PyUFuncObject *ufunc)
static PyObject * ufunc_get_nout (PyUFuncObject *ufunc)
static PyObject * ufunc_get_nargs (PyUFuncObject *ufunc)
static PyObject * ufunc_get_ntypes (PyUFuncObject *ufunc)
static PyObject * ufunc_get_types (PyUFuncObject *ufunc)
static PyObject * ufunc_get_name (PyUFuncObject *ufunc)
static PyObject * ufunc_get_identity (PyUFuncObject *ufunc)
static PyObject * ufunc_get_signature (PyUFuncObject *ufunc)

Variables

static int PyUFunc_NUM_NODEFAULTS = 0
static PyObject * PyUFunc_PYVALS_NAME = NULL
static struct PyMethodDef ufunc_methods []
static PyGetSetDef ufunc_getset []
NPY_NO_EXPORT PyTypeObject PyUFunc_Type

Define Documentation

#define _GETATTR_ (   str,
  rstr 
)
Value:
do {if (strcmp(name, #str) == 0)     \
        return PyObject_HasAttrString(op, "__" #rstr "__");} while (0);
#define _SETCPTR (   cobj,
  val 
)    ((_simple_cobj *)(cobj))->c_obj = (val)
#define _UMATHMODULE
#define HANDLEIT (   NAME,
  str 
)
Value:
{if (retstatus & UFUNC_FPE_##NAME) {        \
            handle = errmask & UFUNC_MASK_##NAME;                       \
            if (handle &&                                               \
                _error_handler(handle >> UFUNC_SHIFT_##NAME,            \
                               errobj, str, retstatus, first) < 0)      \
                return -1;                                              \
        }}
#define NPY_NO_DEPRECATED_API   NPY_API_VERSION
#define NPY_UF_DBG_PRINT (   s)
#define NPY_UF_DBG_PRINT1 (   s,
  p1 
)
#define NPY_UF_DBG_PRINT2 (   s,
  p1,
  p2 
)
#define NPY_UF_DBG_PRINT3 (   s,
  p1,
  p2,
  p3 
)
#define NPY_UF_DBG_TRACING   0
**** PRINTF DEBUG TRACING *********
#define USE_USE_DEFAULTS   1
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.

Function Documentation

static int _does_loop_use_arrays ( void *  data) [static]
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.
System Message: ERROR/3 (<string>, line 1) Document or section may not begin with a transition.

System Message: ERROR/3 (<string>, line 1) Document may not end with a transition.
Return 1 if the given data pointer for the loop specifies that it needs the arrays as the data pointer.

NOTE: This is easier to specify with the type_resolver
in the ufunc object.
TODO: Remove this, since this is already basically broken
with the addition of the masked inner loops and not worth fixing since the new loop selection functions have access to the full dtypes and can dynamically allocate arbitrary auxiliary data.
static int _error_handler ( int  method,
PyObject *  errobj,
char *  errtype,
int  retstatus,
int *  first 
) [static]
fpstatus is the ufunc_formatted hardware status errmask is the handling mask specified by the user. errobj is a Python object with (string, callable object or None) or NULL
2. for each of the flags determine whether to ignore, warn, raise error, or call Python function. If ignore, do nothing If warn, print a warning and continue If raise return an error If call, call a user-defined function with string
static int _extract_pyvals ( PyObject *  ref,
char *  name,
int *  bufsize,
int *  errmask,
PyObject **  errobj 
) [static]
Extracts some values from the global pyvals tuple. ref - should hold the global tuple name - is the name of the ufunc (ufuncobj->name) bufsize - receives the buffer size to use errmask - receives the bitmask for error handling errobj - receives the python object to call with the error,

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

<blockquote> if an error handling method is 'call'</blockquote>

References PyUString_InternFromString, and UFUNC_PYVALS_NAME.

static void _find_array_prepare ( PyObject *  args,
PyObject *  kwds,
PyObject **  output_prep,
int  nin,
int  nout 
) [static]
This function analyzes the input arguments and determines an appropriate __array_prepare__ function to call for the outputs.
If an output argument is provided, then it is prepped with its own __array_prepare__ not with the one determined by the input arguments.
if the provided output argument is already an ndarray, the prepping function is None (which means no prepping will be done --- not even PyArray_Return).
A NULL is placed in output_prep for outputs that should just have PyArray_Return called.
If a 'subok' parameter is passed and isn't True, don't wrap
If we have some preps defined, find the one of highest priority
Here prep is the prepping function determined from the input arrays (could be NULL).
For all the output arrays decide what to do.
1) Use the prep function determined from the input arrays This is the default if the output array is not passed in.
2) Use the __array_prepare__ method of the output object. This is special cased for exact ndarray so that no PyArray_Return is done in that case.
Output argument one may also be in a keyword argument
Output argument one may also be in a keyword argument
None signals to not call any wrapping
static void _find_array_wrap ( PyObject *  args,
PyObject *  kwds,
PyObject **  output_wrap,
int  nin,
int  nout 
) [static]
This function analyzes the input arguments and determines an appropriate __array_wrap__ function to call for the outputs.
If an output argument is provided, then it is wrapped with its own __array_wrap__ not with the one determined by the input arguments.
if the provided output argument is already an array, the wrapping function is None (which means no wrapping will be done --- not even PyArray_Return).
A NULL is placed in output_wrap for outputs that should just have PyArray_Return called.
If a 'subok' parameter is passed and isn't True, don't wrap
If we have some wraps defined, find the one of highest priority
Here wrap is the wrapping function determined from the input arrays (could be NULL).
For all the output arrays decide what to do.
1) Use the wrap function determined from the input arrays This is the default if the output array is not passed in.
2) Use the __array_wrap__ method of the output object passed in. -- this is special cased for exact ndarray so that no PyArray_Return is done in that case.
Output argument one may also be in a keyword argument
Output argument one may also be in a keyword argument
None signals to not call any wrapping
static NPY_INLINE void _free_loop1d_list ( PyUFunc_Loop1d data) [static]
This frees the linked-list structure when the CObject is destroyed (removed from the internal dictionary)
static int _get_end_of_name ( const char *  str,
int  offset 
) [static]
Return the ending position of a variable name
static int _has_reflected_op ( PyObject *  op,
char *  name 
) [static]
static int _is_alnum_underscore ( char  ch) [static]

Referenced by PyUFunc_GetPyValues().

static int _is_alpha_underscore ( char  ch) [static]
static int _is_same_name ( const char *  s1,
const char *  s2 
) [static]
Returns 1 if the dimension names pointed by s1 and s2 are the same, otherwise returns 0.
static void _loop1d_list_free ( void *  ptr) [static]
static PyObject* _makeargs ( int  num,
char *  ltr,
int  null_if_none 
) [static]
System Message: SEVERE/4 (<string>, line 1)
Title overline & underline mismatch.

                           UFUNC GETSET                                 ***
 
construct the string y1,y2,...,yn
static int _next_non_white_space ( const char *  str,
int  offset 
) [static]
Return the position of next non-white-space char in the string
static int _parse_signature ( PyUFuncObject ufunc,
const char *  signature 
) [static]
Sets core_num_dim_ix, core_num_dims, core_dim_ixs, core_offsets, and core_signature in PyUFuncObject "ufunc". Returns 0 unless an error occured.

<

number of dimension of the current argument

<

index into core_num_dims&core_offsets

<

index into core_dim_ixs
Allocate sufficient memory to store pointers to all dimension names

<

shrink this later
loop over input/output arguments
expect "->"
parse core dimensions of one argument, e.g. "()", "(i)", or "(i,j)"
loop over core dimensions
The list of input arguments (or output arguments) was only read partially
check for trivial core-signature, e.g. "(),()->()"
static char _typecharfromnum ( int  num) [static]
static int assign_reduce_identity_one ( PyArrayObject result,
void *  data 
) [static]
static int assign_reduce_identity_zero ( PyArrayObject result,
void *  data 
) [static]
static int check_for_trivial_loop ( PyUFuncObject ufunc,
PyArrayObject **  op,
PyArray_Descr **  dtype,
npy_intp  buffersize 
) [static]
This checks whether a trivial loop is ok, making copies of scalar and one dimensional operands if that will help.
Returns 1 if a trivial loop is ok, 0 if it is not, and -1 if there is an error.
If the dtype doesn't match, or the array isn't aligned, indicate that the trivial loop can't be done.
If op[j] is a scalar or small one dimensional array input, make a copy to keep the opportunity for a trivial loop.
static int cmp_arg_types ( int *  arg1,
int *  arg2,
int  n 
) [static]
return 1 if arg1 > arg2, 0 if arg1 == arg2, and -1 if arg1 < arg2
static int execute_fancy_ufunc_loop ( PyUFuncObject ufunc,
PyArrayObject wheremask,
PyArrayObject **  op,
PyArray_Descr **  dtypes,
NPY_ORDER  order,
npy_intp  buffersize,
PyObject **  arr_prep,
PyObject *  arr_prep_args 
) [static]
nin - number of inputs nout - number of outputs wheremask - if not NULL, the 'where=' parameter to the ufunc. op - the operands (nin + nout of them) order - the loop execution order/output memory order buffersize - how big of a buffer to use arr_prep - the __array_prepare__ functions for the outputs innerloop - the inner loop function innerloopdata - data to pass to the inner loop
Set up the flags
Allocate the iterator. Because the types of the inputs were already checked, we use the casting rule 'unsafe' which is faster to calculate.
Copy any allocated outputs
Call the __array_prepare__ functions where necessary
Only do the loop if the iteration size is non-zero
Validate that the prepare_ufunc_output didn't mess with pointers
Get the inner loop, with the possibility of specialization based on the fixed strides.
Get the variables needed for the loop
Execute the loop
static int execute_legacy_ufunc_loop ( PyUFuncObject ufunc,
int  trivial_loop_ok,
PyArrayObject **  op,
PyArray_Descr **  dtypes,
NPY_ORDER  order,
npy_intp  buffersize,
PyObject **  arr_prep,
PyObject *  arr_prep_args 
) [static]
trivial_loop_ok - 1 if no alignment, data conversion, etc required nin - number of inputs nout - number of outputs op - the operands (nin + nout of them) order - the loop execution order/output memory order buffersize - how big of a buffer to use arr_prep - the __array_prepare__ functions for the outputs innerloop - the inner loop function innerloopdata - data to pass to the inner loop
If the loop wants the arrays, provide them.
First check for the trivial cases that don't need an iterator
Call the __prepare_array__ if necessary
Call the __prepare_array__ if necessary
Have to choose the input with more dimensions to clone, as one of them could be a scalar.
Call the __prepare_array__ if necessary
Call the __prepare_array__ if necessary
If no trivial loop matched, an iterator is required to resolve broadcasting, etc
static int get_binary_op_function ( PyUFuncObject ufunc,
int *  otype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata 
) [static]
Given the output type, finds the specified binary op. The ufunc must have nin==2 and nout==1. The function may modify otype if the given type isn't found.
Returns 0 on success, -1 on failure.
If the type is custom and there are userloops, search for it here
Search for a function with compatible inputs
If the signature is "xx->x", we found the loop
Otherwise, we found the natural type of the reduction, replace otype and search again
Search for the exact function
Since the signature is "xx->x", we found the loop
static int get_ufunc_arguments ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds,
PyArrayObject **  out_op,
NPY_ORDER out_order,
NPY_CASTING out_casting,
PyObject **  out_extobj,
PyObject **  out_typetup,
int *  out_subok,
PyArrayObject **  out_wheremask 
) [static]
*** GENERIC UFUNC USING ITERATOR ****
Parses the positional and keyword arguments for a generic ufunc call.
Note that if an error is returned, the caller must free the non-zero references in out_op. This function does not do its own clean-up.
Check number of arguments
Get input arguments
TODO: There should be a comment here explaining what
context does.
Indicate not implemented if there are flexible objects (structured type or string) but no object types.
Not sure - adding this increased to 246 errors, 150 failures.
Get positional output arguments
Translate None to NULL
If it's an array, can use it
Get keyword output and other arguments. Raise an error if anything else is present in the keyword dictionary.
Provides a policy for allowed casting
Another way to specify 'sig'
Allow this parameter to be None
Overrides the global parameters buffer size, error mask, and error object
First output may be specified as a keyword parameter
Allows the default output layout to be overridden
Allows a specific function inner loop to be selected
Provides a boolean array 'where=' mask if out_wheremask is supplied.
static int iterator_loop ( PyUFuncObject ufunc,
PyArrayObject **  op,
PyArray_Descr **  dtype,
NPY_ORDER  order,
npy_intp  buffersize,
PyObject **  arr_prep,
PyObject *  arr_prep_args,
PyUFuncGenericFunction  innerloop,
void *  innerloopdata 
) [static]
Set up the flags
Allocate the iterator. Because the types of the inputs were already checked, we use the casting rule 'unsafe' which is faster to calculate.
Copy any allocated outputs
Call the __array_prepare__ functions where necessary
Only do the loop if the iteration size is non-zero
Reset the iterator with the base pointers from the wrapped outputs
Get the variables needed for the loop
Execute the loop
static PyObject* make_arr_prep_args ( npy_intp  nin,
PyObject *  args,
PyObject *  kwds 
) [static]
Copy the tuple, but set the nin-th item to the keyword arg
static int prepare_ufunc_output ( PyUFuncObject ufunc,
PyArrayObject **  op,
PyObject *  arr_prep,
PyObject *  arr_prep_args,
int  i 
) [static]
Calls the given __array_prepare__ function on the operand *op, substituting it in place if a new array is returned and matches the old one.

System Message: WARNING/2 (<string>, line 1); backlink Inline emphasis start-string without end-string.
This requires that the dimensions, strides and data type remain exactly the same, which may be more strict than before.
If the same object was returned, nothing to do
If the result doesn't match, throw an error
Replace the op value

References NPY_BEGIN_THREADS.

static PyObject* PyUFunc_Accumulate ( PyUFuncObject ufunc,
PyArrayObject arr,
PyArrayObject out,
int  axis,
int  otype 
) [static]
The selected inner loop
These parameters come from extobj= or from a TLS global
Take a reference to out for later returning
Set up the output data type, using the input's exact data type if the type number didn't change to preserve metadata
Set up the op_axes for the outer loop
The per-operand flags for the outer loop
We can't buffer, so must do UPDATEIFCOPY
The way accumulate is set up, we can't do buffering, so make a copy instead when necessary.
Add some more flags
In case COPY or UPDATEIFCOPY occurred
Get the output
If the reduction axis has size zero, either return the reduction unit for UFUNC_REDUCE, or return the zero-sized output array for UFUNC_ACCUMULATE.
Get the variables needed for the loop
Execute the loop with just the outer iterator
Copy the first element to start the reduction
Turn the two items into three for the inner loop
Execute the loop with no iterators
Turn the two items into three for the inner loop
Copy the first element to start the reduction
NPY_NO_EXPORT int PyUFunc_checkfperr ( int  errmask,
PyObject *  errobj,
int *  first 
)
  1. check hardware flag --- this is platform dependent code
Checking the status flag clears it
NPY_NO_EXPORT PyObject* PyUFunc_FromFuncAndData ( PyUFuncGenericFunction func,
void **  data,
char *  types,
int  ntypes,
int  nin,
int  nout,
int  identity,
char *  name,
char *  doc,
int  check_return 
)
NPY_NO_EXPORT PyObject* PyUFunc_FromFuncAndDataAndSignature ( PyUFuncGenericFunction func,
void **  data,
char *  types,
int  ntypes,
int  nin,
int  nout,
int  identity,
char *  name,
char *  doc,
int  check_return,
const char *  signature 
)
static int PyUFunc_GeneralizedFunction ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds,
PyArrayObject **  op 
) [static]
Use remapped axes for generalized ufunc
These parameters come from extobj= or from a TLS global
The selected inner loop
The dimensions which get passed to the inner loop
The strides which get passed to the inner loop
The __array_prepare__ function to call for each output
This is either args, or args with the out= parameter from kwds added appropriately.
Use the default assignment casting rule
When provided, extobj and typetup contain borrowed references
Initialize all the operands and dtypes to NULL
Get all the arguments
Figure out the number of dimensions needed by the iterator
Fill in op_axes for all the operands
Note that n may be negative if broadcasting extends into the core dimensions.
Broadcast all the unspecified dimensions normally
Use the signature information for the rest
Get the buffersize, errormask, and error object globals
For the generalized ufunc, we get the loop right away too
FAIL with NotImplemented if the other object has the __r<op>__ method and has a higher priority than the current op (signalling it can handle ndarray's).
Get the appropriate __array_prepare__ function to call for each output
Set up arr_prep_args if a prep function was needed
If the loop wants the arrays, provide them
Set up the iterator per-op flags. For generalized ufuncs, we can't do buffering, so must COPY or UPDATEIFCOPY.
Create the iterator
Fill in any allocated outputs
Set up the inner strides array. Because we're not doing buffering, the strides are fixed throughout the looping.
The strides after the first nop match core_dim_ixs
Set up the inner dimensions array
Move the core dimensions to start at the second element
Remove all the core dimensions from the iterator
The first nop strides are for the inner loop (but only can copy them after removing the core axes
Start with the floating-point exception flags cleared
Do the ufunc loop
Get the variables needed for the loop
Check whether any errors occurred during the loop
The caller takes ownership of all the references in op
NPY_NO_EXPORT int PyUFunc_GenericFunction ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds,
PyArrayObject **  op 
)
This generic function is called with the ufunc object, the arguments to it,

and an array of (pointers to) PyArrayObjects which are NULL.

'op' is an array of at least NPY_MAXARGS PyArrayObject *.

System Message: WARNING/2 (<string>, line 4); backlink Inline emphasis start-string without end-string.
These parameters come from extobj= or from a TLS global
The mask provided in the 'where=' parameter
The __array_prepare__ function to call for each output
This is either args, or args with the out= parameter from kwds added appropriately.
Use the default assignment casting rule
When provided, extobj and typetup contain borrowed references
Initialize all the operands and dtypes to NULL
Get all the arguments
Use the masked loop if a wheremask was specified.
Get the buffersize, errormask, and error object globals
Only do the trivial loop check for the unmasked version.
This checks whether a trivial loop is ok, making copies of scalar and one dimensional operands if that will help.
FAIL with NotImplemented if the other object has the __r<op>__ method and has __array_priority__ as an attribute (signalling it can handle ndarray's) and is not already an ndarray or a subtype of the same type.
Get the appropriate __array_prepare__ function to call for each output
Set up arr_prep_args if a prep function was needed
Start with the floating-point exception flags cleared
Do the ufunc loop
TODO: When this is supported, it should be preferred over the legacy_inner_loop_selector
Check whether any errors occurred during the loop
The caller takes ownership of all the references in op
static PyObject* PyUFunc_GenericReduction ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds,
int  operation 
) [static]
This code handles reduce, reduceat, and accumulate (accumulate and reduce are special cases of the more general reduceat but they are handled separately for speed)
Ensure input is an array
Check to see that type (and otype) is not FLEXIBLE
Convert the 'axis' parameter into a list of axes
Convert 'None' into all the axes
Try to interpret axis as an integer
TODO: PyNumber_Index would be good to use here
Special case letting axis={0 or -1} slip through for scalars
Check to see if input is zero-dimensional.
A reduction with no axes is still valid but trivial. As a special case for backwards compatibility in 'sum', 'prod', et al, also allow a reduction where axis=0, even though this is technically incorrect.
If there's an output parameter, copy the value
Otherwise return the array unscathed
If out is specified it determines otype unless otype already specified.
For integer types --- make sure at least a long is used for add and multiply reduction to avoid overflow
If an output parameter was provided, don't wrap it
NPY_NO_EXPORT int PyUFunc_GetPyValues ( char *  name,
int *  bufsize,
int *  errmask,
PyObject **  errobj 
)
On return, if errobj is populated with a non-NULL value, the caller
owns a new reference to errobj.

References _is_alnum_underscore().

NPY_NO_EXPORT int PyUFunc_handlefperr ( int  errmask,
PyObject *  errobj,
int  retstatus,
int *  first 
)

References NPY_MAXARGS.

static PyArrayObject* PyUFunc_Reduce ( PyUFuncObject ufunc,
PyArrayObject arr,
PyArrayObject out,
int  naxes,
int *  axes,
PyArray_Descr odtype,
int  keepdims 
) [static]
The implementation of the reduction operators with the new iterator turned into a bit of a long function here, but I think the design of this part needs to be changed to be more like einsum, so it may not be worth refactoring it too much. Consider this timing:

>>> a = arange(10000)
>>> timeit sum(a)
10000 loops, best of 3: 17 us per loop
>>> timeit einsum("i->",a)
100000 loops, best of 3: 13.5 us per loop
The axes must already be bounds-checked by the calling function, this function does not validate them.
These parameters come from a TLS global
Create an array of flags for reduction
The identity for a dynamic dtype like object arrays can't be used in general
The identity for a dynamic dtype like object arrays can't be used in general
Get the reduction dtype

References NpyIter_Deallocate().

static PyObject* PyUFunc_Reduceat ( PyUFuncObject ufunc,
PyArrayObject arr,
PyArrayObject ind,
PyArrayObject out,
int  axis,
int  otype 
) [static]
Reduceat performs a reduce over an axis using the indices as a guide
op.reduceat(array,indices) computes op.reduce(array[indices[i]:indices[i+1]] for i=0..end with an implicit indices[i+1]=len(array) assumed when i=end-1
if indices[i+1] <= indices[i]+1 then the result is array[indices[i]] for that value
op.accumulate(array) is the same as op.reduceat(array,indices)[::2] where indices is range(len(array)-1) with a zero placed in every other sample indices = zeros(len(array)*2-1) indices[1::2] = range(1,len(array))
output shape is based on the size of indices
The reduceat indices - ind must be validated outside this call
The selected inner loop
These parameters come from extobj= or from a TLS global
Check for out-of-bounds values in indices array
Take a reference to out for later returning
Set up the output data type, using the input's exact data type if the type number didn't change to preserve metadata
Set up the op_axes for the outer loop
Use the i-th iteration dimension to match up ind
Likewise with accumulate, must do UPDATEIFCOPY
The way reduceat is set up, we can't do buffering, so make a copy instead when necessary.
The per-operand flags for the outer loop
Remove the inner loop axis from the outer iterator
In case COPY or UPDATEIFCOPY occurred
Allocate the output for when there's no outer iterator
If the output has zero elements, return now.
Get the variables needed for the loop
Execute the loop with just the outer iterator
Copy the first element to start the reduction
Inner loop like REDUCE
Execute the loop with no iterators
Copy the first element to start the reduction
Inner loop like REDUCE
NPY_NO_EXPORT int PyUFunc_RegisterLoopForType ( PyUFuncObject ufunc,
int  usertype,
PyUFuncGenericFunction  function,
int *  arg_types,
void *  data 
)
Get entry for this user-defined type
If it's not there, then make one and return.
There is already at least 1 loop. Place this one in lexicographic order. If the next one signature is exactly like this one, then just replace. Otherwise insert.
just replace it with new function
insert it before the current one by hacking the internals of cobject to replace the function pointer --- can't use CObject API because destructor is set.
place this at front
NPY_NO_EXPORT int PyUFunc_ReplaceLoopBySignature ( PyUFuncObject func,
PyUFuncGenericFunction  newfunc,
int *  signature,
PyUFuncGenericFunction oldfunc 
)
Find the location of the matching signature

References _typecharfromnum(), PyUString_FromStringAndSize, and _tagPyUFuncObject::types.

NPY_NO_EXPORT int PyUFunc_SetUsesArraysAsData ( void **  data,
size_t  i 
)
Specify that the loop specified by the given index should use the array of input and arrays as the data pointer to the loop.
static int reduce_loop ( NpyIter iter,
char **  dataptrs,
npy_intp strides,
npy_intp countptr,
NpyIter_IterNextFunc iternext,
int  needs_api,
npy_intp  skip_first_count,
void *  data 
) [static]
The normal selected inner loop
Get the inner loop
Skip any first-visit elements
Turn the two items into three for the inner loop
Jump to the faster loop when skipping is done
Turn the two items into three for the inner loop
static int reduce_type_resolver ( PyUFuncObject ufunc,
PyArrayObject arr,
PyArray_Descr odtype,
PyArray_Descr **  out_dtype 
) [static]
If odtype is specified, make a type tuple for the type resolution.
Use the type resolution function to find our loop
The first two type should be equivalent. Because of how reduce has historically behaved in NumPy, the return type could be different, and it is the return type on which the reduction occurs.
static void trivial_three_operand_loop ( PyArrayObject **  op,
PyUFuncGenericFunction  innerloop,
void *  innerloopdata 
) [static]
static void trivial_two_operand_loop ( PyArrayObject **  op,
PyUFuncGenericFunction  innerloop,
void *  innerloopdata 
) [static]
static PyObject* ufunc_accumulate ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds 
) [static]
static void ufunc_dealloc ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_generic_call ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds 
) [static]
Initialize all array objects to NULL to make cleanup easier if something goes wrong.
To allow the other argument to be given a chance
Free the input references
Use __array_wrap__ on all outputs if present on one of the input arguments. If present for multiple inputs: use __array_wrap__ of input object with largest __array_priority__ (default = 0.0)
Exception: we should not wrap outputs for items already passed in as output-arguments. These items should either be left unwrapped or wrapped by calling their own __array_wrap__ routine.
For each output argument, wrap will be either NULL --- call PyArray_Return() -- default if no output arguments given None --- array-object passed in don't call PyArray_Return method --- the __array_wrap__ method to call.
wrap outputs
default behavior

Referenced by PyUFunc_FromFuncAndDataAndSignature().

static PyObject* ufunc_get_doc ( PyUFuncObject ufunc) [static]
Put docstring first or FindMethod finds it... could so some introspection on name and nin + nout to automate the first part of it the doc string shouldn't need the calling convention construct name(x1, x2, ...,[ out1, out2, ...]) __doc__

Referenced by PyUFunc_FromFuncAndDataAndSignature().

static PyObject* ufunc_get_identity ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_name ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_nargs ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_nin ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_nout ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_ntypes ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_signature ( PyUFuncObject ufunc) [static]
static PyObject* ufunc_get_types ( PyUFuncObject ufunc) [static]
return a list with types grouped input->output

Referenced by PyUFunc_FromFuncAndDataAndSignature().

NPY_NO_EXPORT PyObject* ufunc_geterr ( PyObject *  NPY_UNUSEDdummy,
PyObject *  args 
)
Construct list of defaults
static PyObject* ufunc_outer ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds 
) [static]
System Message: SEVERE/4 (<string>, line 1)
Title overline & underline mismatch.

                          UFUNC METHODS                                 ***
 
op.outer(a,b) is equivalent to op(a[:,NewAxis,NewAxis,etc.],b) where a has b.ndim NewAxis terms appended.
The result has dimensions a.ndim + b.ndim
Construct new shape tuple
static PyObject* ufunc_reduce ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds 
) [static]
static PyObject* ufunc_reduceat ( PyUFuncObject ufunc,
PyObject *  args,
PyObject *  kwds 
) [static]
static PyObject* ufunc_repr ( PyUFuncObject ufunc) [static]
NPY_NO_EXPORT PyObject* ufunc_seterr ( PyObject *  NPY_UNUSEDdummy,
PyObject *  args 
)
static int ufunc_update_use_defaults ( void  ) [static]
This is a strategy to buy a little speed up and avoid the dictionary look-up in the default case. It should work in the presence of threads. If it is deemed too complicated or it doesn't actually work it could be taken out.

Variable Documentation

int PyUFunc_NUM_NODEFAULTS = 0 [static]
PyObject* PyUFunc_PYVALS_NAME = NULL [static]
System Message: SEVERE/4 (<string>, line 1)
Title overline & underline mismatch.

                        UFUNC TYPE OBJECT                               ***
 

Referenced by PyUFunc_FromFuncAndDataAndSignature(), and ufunc_frompyfunc().

PyGetSetDef ufunc_getset[] [static]
Initial value:
 {
    {"__doc__",
        (getter)ufunc_get_doc,
        NULL, NULL, NULL},
    {"nin",
        (getter)ufunc_get_nin,
        NULL, NULL, NULL},
    {"nout",
        (getter)ufunc_get_nout,
        NULL, NULL, NULL},
    {"nargs",
        (getter)ufunc_get_nargs,
        NULL, NULL, NULL},
    {"ntypes",
        (getter)ufunc_get_ntypes,
        NULL, NULL, NULL},
    {"types",
        (getter)ufunc_get_types,
        NULL, NULL, NULL},
    {"__name__",
        (getter)ufunc_get_name,
        NULL, NULL, NULL},
    {"identity",
        (getter)ufunc_get_identity,
        NULL, NULL, NULL},
    {"signature",
        (getter)ufunc_get_signature,
        NULL, NULL, NULL},
    {NULL, NULL, NULL, NULL, NULL},  
}
Docstring is now set from python static char *Ufunctype__doc__ = NULL;

System Message: WARNING/2 (<string>, line 1); backlink Inline emphasis start-string without end-string.
struct PyMethodDef ufunc_methods[] [static]
Initial value:
 {
    {"reduce",
        (PyCFunction)ufunc_reduce,
        METH_VARARGS | METH_KEYWORDS, NULL },
    {"accumulate",
        (PyCFunction)ufunc_accumulate,
        METH_VARARGS | METH_KEYWORDS, NULL },
    {"reduceat",
        (PyCFunction)ufunc_reduceat,
        METH_VARARGS | METH_KEYWORDS, NULL },
    {"outer",
        (PyCFunction)ufunc_outer,
        METH_VARARGS | METH_KEYWORDS, NULL},
    {NULL, NULL, 0, NULL}           
}