ufunc API — NumPy v2.2 Manual (original) (raw)

Constants#

UFUNC_{THING}_{ERR}

UFUNC_FPE_DIVIDEBYZERO#

UFUNC_FPE_OVERFLOW#

UFUNC_FPE_UNDERFLOW#

UFUNC_FPE_INVALID#

PyUFunc_{VALUE}

PyUFunc_One#

PyUFunc_Zero#

PyUFunc_MinusOne#

PyUFunc_ReorderableNone#

PyUFunc_None#

PyUFunc_IdentityValue#

Macros#

NPY_LOOP_BEGIN_THREADS#

Used in universal function code to only release the Python GIL if loop->obj is not true (i.e. this is not an OBJECT array loop). Requires use of NPY_BEGIN_THREADS_DEF in variable declaration area.

NPY_LOOP_END_THREADS#

Used in universal function code to re-acquire the Python GIL if it was released (because loop->obj was not true).

Types#

type PyUFuncGenericFunction#

Pointers to functions that actually implement the underlying (element-by-element) function \(N\) times with the following signature:

void loopfunc(char **args, npy_intp const *dimensions, npy_intp const *steps, void *data)#

Parameters:

This is an example of a func specialized for addition of doubles returning doubles.

static void double_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *extra) { npy_intp i; npy_intp is1 = steps[0], is2 = steps[1]; npy_intp os = steps[2], n = dimensions[0]; char *i1 = args[0], *i2 = args[1], *op = args[2]; for (i = 0; i < n; i++) { *((double *)op) = *((double *)i1) + *((double *)i2); i1 += is1; i2 += is2; op += os; } }

Functions#

PyObject *PyUFunc_FromFuncAndData(PyUFuncGenericFunction *func, void *const *data, const char *types, int ntypes, int nin, int nout, int identity, const char *name, const char *doc, int unused)#

Create a new broadcasting universal function from required variables. Each ufunc builds around the notion of an element-by-element operation. Each ufunc object contains pointers to 1-d loops implementing the basic functionality for each supported type.

Note

The func, data, types, name, and doc arguments are not copied by PyUFunc_FromFuncAndData. The caller must ensure that the memory used by these arrays is not freed as long as the ufunc object is alive.

Parameters:

PyObject *PyUFunc_FromFuncAndDataAndSignature(PyUFuncGenericFunction *func, void *const *data, const char *types, int ntypes, int nin, int nout, int identity, const char *name, const char *doc, int unused, const char *signature)#

This function is very similar to PyUFunc_FromFuncAndData above, but has an extra signature argument, to define ageneralized universal functions. Similarly to how ufuncs are built around an element-by-element operation, gufuncs are around subarray-by-subarray operations, thesignature defining the subarrays to operate on.

Parameters:

PyObject *PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, void **data, char *types, int ntypes, int nin, int nout, int identity, char *name, char *doc, int unused, char *signature, PyObject *identity_value)#

This function is very similar to PyUFunc_FromFuncAndDataAndSignature above, but has an extra identity_value argument, to define an arbitrary identity for the ufunc when identity is passed as PyUFunc_IdentityValue.

Parameters:

int PyUFunc_RegisterLoopForType(PyUFuncObject *ufunc, int usertype, PyUFuncGenericFunction function, int *arg_types, void *data)#

This function allows the user to register a 1-d loop with an already- created ufunc to be used whenever the ufunc is called with any of its input arguments as the user-defined data-type. This is needed in order to make ufuncs work with built-in data-types. The data-type must have been previously registered with the numpy system. The loop is passed in as_function_. This loop can take arbitrary data which should be passed in as data. The data-types the loop requires are passed in as arg_types which must be a pointer to memory at least as large as ufunc->nargs.

int PyUFunc_RegisterLoopForDescr(PyUFuncObject *ufunc, PyArray_Descr *userdtype, PyUFuncGenericFunction function, PyArray_Descr **arg_dtypes, void *data)#

This function behaves like PyUFunc_RegisterLoopForType above, except that it allows the user to register a 1-d loop using PyArray_Descr objects instead of dtype type num values. This allows a 1-d loop to be registered for structured array data-dtypes and custom data-types instead of scalar data-types.

int PyUFunc_ReplaceLoopBySignature(PyUFuncObject *ufunc, PyUFuncGenericFunction newfunc, int *signature, PyUFuncGenericFunction *oldfunc)#

Replace a 1-d loop matching the given signature in the already-created ufunc with the new 1-d loop newfunc. Return the old 1-d loop function in oldfunc. Return 0 on success and -1 on failure. This function works only with built-in types (usePyUFunc_RegisterLoopForType for user-defined types). A signature is an array of data-type numbers indicating the inputs followed by the outputs assumed by the 1-d loop.

void PyUFunc_clearfperr()#

Clear the IEEE error flags.

Generic functions#

At the core of every ufunc is a collection of type-specific functions that defines the basic functionality for each of the supported types. These functions must evaluate the underlying function \(N\geq1\)times. Extra-data may be passed in that may be used during the calculation. This feature allows some general functions to be used as these basic looping functions. The general function has all the code needed to point variables to the right place and set up a function call. The general function assumes that the actual function to call is passed in as the extra data and calls it with the correct values. All of these functions are suitable for placing directly in the array of functions stored in the functions member of the PyUFuncObject structure.

void PyUFunc_f_f_As_d_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_d_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_f_f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_g_g(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_F_F_As_D_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_F_F(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_D_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_G_G(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_e_e(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_e_e_As_f_f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_e_e_As_d_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

Type specific, core 1-d functions for ufuncs where each calculation is obtained by calling a function taking one input argument and returning one output. This function is passed infunc. The letters correspond to dtypechar’s of the supported data types ( e - half, f - float, d - double,g - long double, F - cfloat, D - cdouble,G - clongdouble). The argument func must support the same signature. The _As_X_X variants assume ndarray’s of one data type but cast the values to use an underlying function that takes a different data type. Thus, PyUFunc_f_f_As_d_d uses ndarrays of data type NPY_FLOAT but calls out to a C-function that takes double and returns double.

void PyUFunc_ff_f_As_dd_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_ff_f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_dd_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_gg_g(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_FF_F_As_DD_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_DD_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_FF_F(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_GG_G(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_ee_e(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_ee_e_As_ff_f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_ee_e_As_dd_d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

Type specific, core 1-d functions for ufuncs where each calculation is obtained by calling a function taking two input arguments and returning one output. The underlying function to call is passed in as func. The letters correspond to dtypechar’s of the specific data type supported by the general-purpose function. The argument func must support the corresponding signature. The _As_XX_X variants assume ndarrays of one data type but cast the values at each iteration of the loop to use the underlying function that takes a different data type.

void PyUFunc_O_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

void PyUFunc_OO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

One-input, one-output, and two-input, one-output core 1-d functions for the NPY_OBJECT data type. These functions handle reference count issues and return early on error. The actual function to call is_func_ and it must accept calls with the signature (PyObject*) (PyObject*) for PyUFunc_O_O or (PyObject*)(PyObject *, PyObject *) for PyUFunc_OO_O.

void PyUFunc_O_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

This general purpose 1-d core function assumes that func is a string representing a method of the input object. For each iteration of the loop, the Python object is extracted from the array and its func method is called returning the result to the output array.

void PyUFunc_OO_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

This general purpose 1-d core function assumes that func is a string representing a method of the input object that takes one argument. The first argument in args is the method whose function is called, the second argument in args is the argument passed to the function. The output of the function is stored in the third entry of args.

void PyUFunc_On_Om(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#

This is the 1-d core function used by the dynamic ufuncs created by umath.frompyfunc(function, nin, nout). In this case func is a pointer to a PyUFunc_PyFuncData structure which has definition

type PyUFunc_PyFuncData#

typedef struct { int nin; int nout; PyObject *callable; } PyUFunc_PyFuncData;

At each iteration of the loop, the nin input objects are extracted from their object arrays and placed into an argument tuple, the Python_callable_ is called with the input arguments, and the nout outputs are placed into their object arrays.

Importing the API#

PY_UFUNC_UNIQUE_SYMBOL#

NO_IMPORT_UFUNC#

int PyUFunc_ImportUFuncAPI(void)#

Ensures that the UFunc C-API is imported and usable. It returns 0on success and -1 with an error set if NumPy couldn’t be imported. While preferable to call it once at module initialization, this function is very light-weight if called multiple times.

New in version 2.0: This function mainly checks for PyUFunc_API == NULL so it can be manually backported if desired.

import_ufunc(void)#

These are the constants and functions for accessing the ufunc C-API from extension modules in precisely the same way as the array C-API can be accessed. The import_ufunc () function must always be called (in the initialization subroutine of the extension module). If your extension module is in one file then that is all that is required. The other two constants are useful if your extension module makes use of multiple files. In that case, define PY_UFUNC_UNIQUE_SYMBOL to something unique to your code and then in source files that do not contain the module initialization function but still need access to the UFUNC API, define PY_UFUNC_UNIQUE_SYMBOL to the same name used previously and also define NO_IMPORT_UFUNC.

The C-API is actually an array of function pointers. This array is created (and pointed to by a global variable) by import_ufunc. The global variable is either statically defined or allowed to be seen by other files depending on the state ofPY_UFUNC_UNIQUE_SYMBOL and NO_IMPORT_UFUNC.