numpy 2.0.0
src/umath/ufunc_object.c File Reference
#include "Python.h"
#include "npy_config.h"
#include "numpy/npy_3kcompat.h"
#include "numpy/noprefix.h"
#include "numpy/ufuncobject.h"
#include "lowlevel_strided_loops.h"
#include "ufunc_object.h"

Data Structures

struct  _simple_cobj

Defines

#define _UMATHMODULE
#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 USE_NEW_ITERATOR_GENFUNC   1
#define HANDLEIT(NAME, str)
#define NO_UFUNCLOOP   0
#define ZERO_EL_REDUCELOOP   0
#define ONE_UFUNCLOOP   1
#define ONE_EL_REDUCELOOP   1
#define NOBUFFER_UFUNCLOOP   2
#define NOBUFFER_REDUCELOOP   2
#define BUFFER_UFUNCLOOP   3
#define BUFFER_REDUCELOOP   3
#define SIGNATURE_NOBUFFER_UFUNCLOOP   4
#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 *self, const char *signature)
static int get_ufunc_arguments (PyUFuncObject *self, PyObject *args, PyObject *kwds, PyArrayObject **out_op, NPY_ORDER *out_order, NPY_CASTING *out_casting, PyObject **out_extobj, PyObject **out_typetup, int *out_subok, int *out_any_object)
static const char * _casting_to_string (NPY_CASTING casting)
static int ufunc_loop_matches (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, int any_object, int use_min_scalar, int *types, int *out_no_castable_output, char *out_err_src_typecode, char *out_err_dst_typecode)
static int set_ufunc_loop_data_types (PyUFuncObject *self, PyArrayObject **op, PyArray_Descr **out_dtype, int *types, npy_intp buffersize, int *out_trivial_loop_ok)
static int find_ufunc_matching_userloop (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, npy_intp buffersize, int any_object, int use_min_scalar, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata, int *out_trivial_loop_ok, int *out_no_castable_output, char *out_err_src_typecode, char *out_err_dst_typecode)
static int find_ufunc_specified_userloop (PyUFuncObject *self, int n_specified, int *specified_types, PyArrayObject **op, NPY_CASTING casting, npy_intp buffersize, int any_object, int use_min_scalar, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata, int *out_trivial_loop_ok)
static int dtype_kind_to_simplified_ordering (char kind)
static int should_use_min_scalar (PyArrayObject **op, int nop)
static int find_best_ufunc_inner_loop (PyUFuncObject *self, PyArrayObject **op, NPY_CASTING input_casting, NPY_CASTING output_casting, npy_intp buffersize, int any_object, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata, int *out_trivial_loop_ok)
static int find_specified_ufunc_inner_loop (PyUFuncObject *self, PyObject *type_tup, PyArrayObject **op, NPY_CASTING casting, npy_intp buffersize, int any_object, PyArray_Descr **out_dtype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata, int *out_trivial_loop_ok)
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 *self, PyArrayObject **op, PyObject *arr_prep, PyObject *arr_prep_args, int i)
static int iterator_loop (PyUFuncObject *self, 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_ufunc_loop (PyUFuncObject *self, int trivial_loop_ok, PyArrayObject **op, PyArray_Descr **dtype, NPY_ORDER order, npy_intp buffersize, PyObject **arr_prep, PyObject *arr_prep_args, PyUFuncGenericFunction innerloop, void *innerloopdata)
static PyObject * make_arr_prep_args (npy_intp nin, PyObject *args, PyObject *kwds)
static int PyUFunc_GeneralizedFunction (PyUFuncObject *self, PyObject *args, PyObject *kwds, PyArrayObject **op)
NPY_NO_EXPORT int PyUFunc_GenericFunction (PyUFuncObject *self, PyObject *args, PyObject *kwds, PyArrayObject **op)
static int get_binary_op_function (PyUFuncObject *self, int *otype, PyUFuncGenericFunction *out_innerloop, void **out_innerloopdata)
static PyObject * PyUFunc_ReductionOp (PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out, int axis, int otype, int operation, char *opname)
static PyObject * PyUFunc_Reduce (PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out, int axis, int otype)
static PyObject * PyUFunc_Accumulate (PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *out, int axis, int otype)
static PyObject * PyUFunc_Reduceat (PyUFuncObject *self, PyArrayObject *arr, PyArrayObject *ind, PyArrayObject *out, int axis, int otype)
static PyObject * PyUFunc_GenericReduction (PyUFuncObject *self, 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 *self, 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 *self)
static PyObject * ufunc_repr (PyUFuncObject *self)
static PyObject * ufunc_outer (PyUFuncObject *self, PyObject *args, PyObject *kwds)
static PyObject * ufunc_reduce (PyUFuncObject *self, PyObject *args, PyObject *kwds)
static PyObject * ufunc_accumulate (PyUFuncObject *self, PyObject *args, PyObject *kwds)
static PyObject * ufunc_reduceat (PyUFuncObject *self, 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 *self)
static PyObject * ufunc_get_nin (PyUFuncObject *self)
static PyObject * ufunc_get_nout (PyUFuncObject *self)
static PyObject * ufunc_get_nargs (PyUFuncObject *self)
static PyObject * ufunc_get_ntypes (PyUFuncObject *self)
static PyObject * ufunc_get_types (PyUFuncObject *self)
static PyObject * ufunc_get_name (PyUFuncObject *self)
static PyObject * ufunc_get_identity (PyUFuncObject *self)
static PyObject * ufunc_get_signature (PyUFuncObject *self)

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 BUFFER_REDUCELOOP   3
#define BUFFER_UFUNCLOOP   3
#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 NO_UFUNCLOOP   0
#define NOBUFFER_REDUCELOOP   2
#define NOBUFFER_UFUNCLOOP   2
#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 ONE_EL_REDUCELOOP   1
#define ONE_UFUNCLOOP   1
#define SIGNATURE_NOBUFFER_UFUNCLOOP   4
#define USE_NEW_ITERATOR_GENFUNC   1
#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.
#define ZERO_EL_REDUCELOOP   0

Function Documentation

static const char* _casting_to_string ( NPY_CASTING  casting) [static]
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.
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.

Referenced by iterator_loop().

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]

References _pya_malloc.

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 self,
const char *  signature 
) [static]
Sets core_num_dim_ix, core_num_dims, core_dim_ixs, core_offsets, and core_signature in PyUFuncObject "self". 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 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 dtype_kind_to_simplified_ordering ( char  kind) [static]
Provides an ordering for the dtype 'kind' character codes, to help determine when to use the min_scalar_type function. This groups 'kind' into boolean, integer, floating point, and everything else.

Boolean kind
Unsigned int kind
Signed int kind
Float kind
Complex kind
Anything else

References NPY_MAXARGS, and should_use_min_scalar().

static int execute_ufunc_loop ( PyUFuncObject self,
int  trivial_loop_ok,
PyArrayObject **  op,
PyArray_Descr **  dtype,
NPY_ORDER  order,
npy_intp  buffersize,
PyObject **  arr_prep,
PyObject *  arr_prep_args,
PyUFuncGenericFunction  innerloop,
void *  innerloopdata 
) [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

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 find_best_ufunc_inner_loop ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
npy_intp  buffersize,
int  any_object,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata,
int *  out_trivial_loop_ok 
) [static]
Does a linear search for the best inner loop of the ufunc. When op[i] is a scalar or a one dimensional array smaller than the buffersize, and needs a dtype conversion, this function may substitute op[i] with a version cast to the correct type. This way, the later trivial loop detection has a higher chance of being triggered.
Note that if an error is returned, the caller must free the non-zero references in out_dtype. This function does not do its own clean-up.

For making a better error message on coercion error
If the ufunc has userloops, search for them.
Error
A loop was found
Determine the UFunc loop. This could in general be much faster, and a better way to implement it might be for the ufunc to provide a function which gives back the result type and inner loop function.
A default fast mechanism could be provided for functions which follow the most typical pattern, when all functions have signatures "xx...x -> x" for some built-in data type x, as follows.

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

<blockquote>

  • Use PyArray_ResultType to get the output type
  • Look up the inner loop in a table based on the output type_num

</blockquote>

The method for finding the loop in the previous code did not appear consistent (as noted by some asymmetry in the generated coercion tables for np.add).
Copy the types into an int array for matching
Error
Found a match
Save the inner loop and its data
If no function was found, throw an error
TODO: We should try again if the casting rule is same_kind
or unsafe, and look for a function more liberally.

References NPY_UF_DBG_PRINT2, PyArray_DescrFromType(), and _PyArray_Descr::type_num.

static int find_specified_ufunc_inner_loop ( PyUFuncObject self,
PyObject *  type_tup,
PyArrayObject **  op,
NPY_CASTING  casting,
npy_intp  buffersize,
int  any_object,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata,
int *  out_trivial_loop_ok 
) [static]
Does a linear search for the inner loop of the ufunc specified by type_tup. When op[i] is a scalar or a one dimensional array smaller than the buffersize, and needs a dtype conversion, this function may substitute op[i] with a version cast to the correct type. This way, the later trivial loop detection has a higher chance of being triggered.
Note that if an error is returned, the caller must free the non-zero references in out_dtype. This function does not do its own clean-up.

For making a better error message on coercion error
Fill in specified_types from the tuple or string
If the ufunc has userloops, search for them.
Error
Found matching loop
Copy the types into an int array for matching
Error
It worked
Save the inner loop and its data
Didn't work
If no function was found, throw an error

static int find_ufunc_matching_userloop ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
npy_intp  buffersize,
int  any_object,
int  use_min_scalar,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata,
int *  out_trivial_loop_ok,
int *  out_no_castable_output,
char *  out_err_src_typecode,
char *  out_err_dst_typecode 
) [static]
Does a search through the arguments and the loops

Use this to try to avoid repeating the same userdef loop search
Error
Found a match
Save the inner loop and its data
Didn't find a match

Referenced by find_ufunc_specified_userloop().

static int find_ufunc_specified_userloop ( PyUFuncObject self,
int  n_specified,
int *  specified_types,
PyArrayObject **  op,
NPY_CASTING  casting,
npy_intp  buffersize,
int  any_object,
int  use_min_scalar,
PyArray_Descr **  out_dtype,
PyUFuncGenericFunction out_innerloop,
void **  out_innerloopdata,
int *  out_trivial_loop_ok 
) [static]
Does a search through the arguments and the loops

Use this to try to avoid repeating the same userdef loop search
It works
Save the inner loop and its data
Didn't match
Error
Didn't find a match

References _casting_to_string(), find_ufunc_matching_userloop(), NPY_MAXARGS, NPY_UF_DBG_PRINT, NPY_UF_DBG_PRINT1, set_ufunc_loop_data_types(), should_use_min_scalar(), and ufunc_loop_matches().

static int get_binary_op_function ( PyUFuncObject self,
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 self,
PyObject *  args,
PyObject *  kwds,
PyArrayObject **  out_op,
NPY_ORDER out_order,
NPY_CASTING out_casting,
PyObject **  out_extobj,
PyObject **  out_typetup,
int *  out_subok,
int *  out_any_object 
) [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
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
Another way to specify 'sig'
Allow this parameter to be None

Referenced by iterator_loop().

static int iterator_loop ( PyUFuncObject self,
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

References _extract_pyvals(), get_ufunc_arguments(), NPY_KEEPORDER, NPY_MAXARGS, NPY_MAXDIMS, NPY_UF_DBG_PRINT, NPY_UF_DBG_PRINT1, NPY_UNSAFE_CASTING, PyArray_NDIM, and PyUFunc_GetPyValues().

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 self,
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

static PyObject* PyUFunc_Accumulate ( PyUFuncObject self,
PyArrayObject arr,
PyArrayObject out,
int  axis,
int  otype 
) [static]
NPY_NO_EXPORT int PyUFunc_checkfperr ( int  errmask,
PyObject *  errobj,
int *  first 
)

  1. check hardware flag --- this is platform dependent code

References NPY_MAXARGS, PyArray_CheckExact, and PyArray_IsAnyScalar.

NPY_NO_EXPORT void PyUFunc_clearfperr ( )
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 
)

generalized ufunc

static int PyUFunc_GeneralizedFunction ( PyUFuncObject self,
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.
Many things in NumPy do unsafe casting (doing int += float, etc). The strictness should probably become a state parameter, similar to the seterr/geterr.
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
Decide the casting rules for inputs and outputs. We want NPY_SAFE_CASTING or stricter, so that the loop selection code doesn't choose an integer loop for float inputs, for example.
Find the best ufunc inner loop, and fill in the dtypes
Find the specified ufunc inner loop, and fill in the dtypes
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.
If both are same subtype of object arrays, then proceed
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 self,
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.

These parameters come from extobj= or from a TLS global
The selected 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.
TODO: For 1.6, the default should probably be NPY_CORDER
Many things in NumPy do unsafe casting (doing int += float, etc). The strictness should probably become a state parameter, similar to the seterr/geterr.
When provided, extobj and typetup contain borrowed references
TODO: support generalized ufunc
Initialize all the operands and dtypes to NULL
Get all the arguments
Get the buffersize, errormask, and error object globals
Decide the casting rules for inputs and outputs. We want NPY_SAFE_CASTING or stricter, so that the loop selection code doesn't choose an integer loop for float inputs, for example.
Find the best ufunc inner loop, and fill in the dtypes
Find the specified ufunc inner loop, and fill in the dtypes
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.
If both are same subtype of object arrays, then proceed
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
Start with the floating-point exception flags cleared
Do the ufunc loop
Check whether any errors occurred during the loop
The caller takes ownership of all the references in op

static PyObject* PyUFunc_GenericReduction ( PyUFuncObject self,
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 if input is zero-dimensional
Check to see that type (and otype) is not FLEXIBLE
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

References _pya_free, _loop1d_info::arg_types, and _loop1d_info::next.

NPY_NO_EXPORT int PyUFunc_getfperr ( void  )
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().

Referenced by iterator_loop().

NPY_NO_EXPORT int PyUFunc_handlefperr ( int  errmask,
PyObject *  errobj,
int  retstatus,
int *  first 
)
static PyObject* PyUFunc_Reduce ( PyUFuncObject self,
PyArrayObject arr,
PyArrayObject out,
int  axis,
int  otype 
) [static]
We have two basic kinds of loops. One is used when arr is not-swapped and aligned and output type is the same as input type. The other uses buffers when one of these is not satisfied. <blockquote> Zero-length and one-length axes-to-be-reduced are handled separately.</blockquote>

References PyArray_GetPriority(), and PyArray_SUBTYPE_PRIORITY.

static PyObject* PyUFunc_Reduceat ( PyUFuncObject self,
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
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

References PyArray_CheckExact.

static PyObject* PyUFunc_ReductionOp ( PyUFuncObject self,
PyArrayObject arr,
PyArrayObject out,
int  axis,
int  otype,
int  operation,
char *  opname 
) [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 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
Set up the op_axes for the outer loop
The per-operand flags for the outer loop
This is because 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 unit has size zero, either return the reduction unit for UFUNC_REDUCE, or return the zero-sized output array for UFUNC_ACCUMULATE.
Only allocate an inner iterator if it's necessary
Also set the dtype for buffering arr
The per-operand flags for the inner loop
Should never get an inner iterator for ACCUMULATE
Get the variables needed for the loop
Execute the loop with two nested iterators
Only UFUNC_REDUCE uses iter_inner
Reset the inner iterator to the outer's data
Copy the first element to start the reduction
Turn the two items into three for the inner 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 just the inner iterator
Only UFUNC_REDUCE uses iter_inner
Reset the inner iterator to prepare the buffers
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_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

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 set_ufunc_loop_data_types ( PyUFuncObject self,
PyArrayObject **  op,
PyArray_Descr **  out_dtype,
int *  types,
npy_intp  buffersize,
int *  out_trivial_loop_ok 
) [static]

Fill the dtypes array
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.

Referenced by find_ufunc_specified_userloop(), and ufunc_loop_matches().

static int should_use_min_scalar ( PyArrayObject **  op,
int  nop 
) [static]

Determine if there are any scalars, and if so, whether the maximum "kind" of the scalars surpasses the maximum "kind" of the arrays
Indicate whether to use the min_scalar_type function

Referenced by dtype_kind_to_simplified_ordering(), and find_ufunc_specified_userloop().

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 self,
PyObject *  args,
PyObject *  kwds 
) [static]
static void ufunc_dealloc ( PyUFuncObject self) [static]
static PyObject* ufunc_generic_call ( PyUFuncObject self,
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

static PyObject* ufunc_get_doc ( PyUFuncObject self) [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__

static PyObject* ufunc_get_identity ( PyUFuncObject self) [static]
static PyObject* ufunc_get_name ( PyUFuncObject self) [static]
static PyObject* ufunc_get_nargs ( PyUFuncObject self) [static]
static PyObject* ufunc_get_nin ( PyUFuncObject self) [static]
static PyObject* ufunc_get_nout ( PyUFuncObject self) [static]
static PyObject* ufunc_get_ntypes ( PyUFuncObject self) [static]
static PyObject* ufunc_get_signature ( PyUFuncObject self) [static]
static PyObject* ufunc_get_types ( PyUFuncObject self) [static]

return a list with types grouped input->output

NPY_NO_EXPORT PyObject* ufunc_geterr ( PyObject *  NPY_UNUSEDdummy,
PyObject *  args 
)

Construct list of defaults

References PyUFunc_One, and PyUFunc_Zero.

static int ufunc_loop_matches ( PyUFuncObject self,
PyArrayObject **  op,
NPY_CASTING  input_casting,
NPY_CASTING  output_casting,
int  any_object,
int  use_min_scalar,
int *  types,
int *  out_no_castable_output,
char *  out_err_src_typecode,
char *  out_err_dst_typecode 
) [static]

First check if all the inputs can be safely cast to the types for this function
If no inputs are objects and there are more than one loop, don't allow conversion to object. The rationale behind this is mostly performance. Except for custom ufuncs built with just one object-parametered inner loop, only the types that are supported are implemented. Trying the object version of logical_or on float arguments doesn't seem right.
If all the inputs are scalars, use the regular promotion rules, not the special value-checking ones.
If all the inputs were ok, then check casting back to the outputs.

References _loop1d_info::arg_types, _loop1d_info::data, _loop1d_info::func, _loop1d_info::next, NPY_UF_DBG_PRINT, NpyCapsule_AsVoidPtr(), PyArray_DESCR, PyTypeNum_ISUSERDEF, and set_ufunc_loop_data_types().

Referenced by find_ufunc_specified_userloop().

static PyObject* ufunc_outer ( PyUFuncObject self,
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 self,
PyObject *  args,
PyObject *  kwds 
) [static]
static PyObject* ufunc_reduceat ( PyUFuncObject self,
PyObject *  args,
PyObject *  kwds 
) [static]
static PyObject* ufunc_repr ( PyUFuncObject self) [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.

References NPY_NO_EXPORT, PyUFunc_Type, ufunc_get_identity(), ufunc_get_name(), and ufunc_get_signature().


Variable Documentation

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

                        UFUNC TYPE OBJECT                               ***
 

Referenced by ufunc_frompyfunc(), and ufunc_update_use_defaults().

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}           
}