UFunc API

原文:https://docs.scipy.org/doc/numpy/reference/c-api.ufunc.html

译者:飞龙 UsyiyiCN

校对:(虚位以待)

Constants

UFUNC_ERR_ {HANDLER}

{HANDLER}可以是IGNOREWARNRAISECALL

UFUNC_ {THING} _ {ERR}

{THING} can be MASK, SHIFT, or FPE, and {ERR} can be DIVIDEBYZERO, OVERFLOW, UNDERFLOW, and INVALID.

PyUFunc_ {VALUE}

{VALUE}可以是一个(1),(0)或

Macros

NPY_LOOP_BEGIN_THREADS

在通用函数代码中只用于释放Python GIL,如果loop-> obj不为true(这不是OBJECT数组循环)。需要在变量声明区中使用NPY_BEGIN_THREADS_DEF

NPY_LOOP_END_THREADS

用于通用函数代码,以重新获取Python GIL,如果它被释放(因为loop-> obj不是true)。

UFUNC_CHECK_ERROR(loop)

一个宏用于内部检查错误和goto失败,如果发现。此宏需要当前代码块中的失败标签。循环变量​​必须至少具有成员(obj,errormask和errorobj)。如果loop - > obj非零,则调用PyErr_Occurred()(意味着必须保持GIL)。If loop ->obj is zero, then if loop ->errormask is nonzero, PyUFunc_checkfperr is called with arguments loop ->errormask and loop ->errobj. 如果IEEE浮点寄存器的这个检查的结果为真,则代码重定向到必须定义的故障标签。

UFUNC_CHECK_STATUS(ret)

已弃用:请改用npy_math.h使用npy_clear_floatstatus。

扩展为与平台相关的代码的宏。ret变量​​可以是任何整数。根据浮点处理器的相应错误标志的状态,UFUNC_FPE_{ERR}位设置在ret中。

Functions

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

从所需变量创建新的广播通用函数。每个ufunc围绕元素到元素操作的概念构建。每个ufunc对象包含指向1-d循环的指针,实现每种支持类型的基本功能。

注意

不复制func数据类型名称docPyUFunc_FromFuncAndData调用者必须确保这些数组使用的内存不会被释放,只要ufunc对象是活的。

参数:
  • func - 必须包含PyUFuncGenericFunction项目的长度ntypes的数组。这些项是指向实际实现底层(逐个元素)函数N次的函数的指针。
  • data - 应为NULL或指向大小为ntypes的数组的指针。该数组可以包含要传递到func数组中相应的1-d循环函数的任意附加数据。
  • 类型 - 必须为长度(nin + nout)* ntypes,并且包含数据类型内置),在func数组中的相应函数可以处理。
  • ntypes - ufunc已实现了多少个不同的数据类型“签名”。
  • nin - 此操作的输入数。
  • nout - 输出数
  • name - ufunc的名称。指定“add”或“multiply”的名称会启用不指定dtype时整数类型缩减的特殊行为。如果输入类型是小于int_数据类型大小的整数(或布尔)数据类型,则它将在int_(或uint)数据类型。
  • doc - 允许传入要与ufunc一起存储的文档字符串。文档字符串不应包含函数或调用签名的名称,因为它将根据对象动态确定,并且在访问ufunc的__ doc __属性时可用。
  • 未使用 - 未使用,并且用于C-API的向后兼容性。
PyObject * PyUFunc_FromFuncAndDataAndSignature(PyUFuncGenericFunction * func,
void ** data,char * types,int ntypes,int nin,int nout,int identity,
char * name,char * doc,int unused,char * signature)

这个函数与上面的PyUFunc_FromFuncAndData非常相似,但是有一个额外的签名参数,用于定义通用的通用函数。类似于ufuncs是如何围绕元素操作构建的,gufuncs是子数组 - 子数组操作,签名定义了要操作的子数组。

参数:
  • signature - 新gufunc的签名。将其设置为NULL等效于调用PyUFunc_FromFuncAndData。将创建字符串的副本,因此可以释放传入的缓冲区。
int PyUFunc_RegisterLoopF​​orType(PyUFuncObject * ufunc,
int usertype,PyUFuncGenericFunction function,int * arg_types,void * data)

该函数允许用户使用已创建的ufunc注册1-d循环,以便在使用任何输入参数作为用户定义的数据类型调用ufunc时使用。这是需要的,以使ufuncs与内置的数据类型工作。数据类型必须已预先注册到numpy系统。循环作为函数传递。此循环可以获取应作为数据传递的任意数据。循环需要的数据类型作为arg_types传递,它必须是指向内存的指针,至少与ufunc-> nargs一样大。

int PyUFunc_RegisterLoopF​​orDescr(PyUFuncObject * ufunc,
PyArray_Descr * userdtype,PyUFuncGenericFunction function,
PyArray_Descr ** arg_dtypes,void * data)

此函数的行为类似于上面的PyUFunc_RegisterLoopF​​orType,除了它允许用户使用PyArray_Descr对象而不是dtype类型num值注册1-d循环。这允许为结构化数组数据类型和自定义数据类型而不是标量数据类型注册1-d循环。

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

将已经创建的ufunc中给定签名的1-d循环替换为新的1-d循环newfunc。返回oldfunc中的旧1-d循环函数。成功返回0,失败返回-1。此函数仅适用于内置类型(对于用户定义的类型使用PyUFunc_RegisterLoopForType)。签名是数据类型数字的数组,指示由1-d循环采用的输出所遵循的输入。

int PyUFunc_GenericFunction(PyUFuncObject * self,
PyObject * args,PyObject * kwds,PyArrayObject ** mps)

一个通用的ufunc调用。ufunc作为self传递,ufunc的参数为argskwdsmps参数是PyArrayObject指针的数组,其值被丢弃,并且在返回成功时接收转换的输入参数以及ufunc输出。用户负责管理此数组,并接收mps中每个数组的新引用。mps中的数组的总数由self - > nin + self - > nout给出。

成功返回0,错误返回-1。

int PyUFunc_checkfperr(int errmask, PyObject* errobj)

一个简单的接口,用于IEEE错误标志检查支持。errmask参数是UFUNC_MASK_{ERR}位掩码的掩码,指示要检查哪些错误(以及如何检查它们)。errobj必须是一个包含两个元素的Python元组:一个包含将在任何错误通信中使用的名称的字符串和一个可调用的Python对象(回调函数)或Py_None只有在将UFUNC_ERR_CALL设置为所需的错误检查方法时,才能使用可调用对象。此例程管理GIL,即使释放GIL后也可安全调用。如果IEEE兼容性硬件中的错误被确定,则返回-1,否则返回0。

void PyUFunc_clearfperr()

清除IEEE错误标志。

void PyUFunc_GetPyValues(char * name,int * bufsize,
int * errmask,PyObject ** errobj)

从线程本地存储区域获取用于ufunc处理的Python值,除非已设置默认值,在这种情况下绕过名称查找。该名称作为字符串放置在* errobj的第一个元素中。第二个元素是调用错误回调的查找函数。要使用的查找缓冲区大小的值传递到bufsize,并且错误掩码的值放在errmask中。

Generic functions

每个ufunc的核心是一个类型特定函数的集合,它定义了每种支持类型的基本功能。这些函数必须评估底层函数N\geq1 times。可以传递额外数据,其可以在计算期间使用。此功能允许一些一般功能用作这些基本循环功能。一般函数具有将变量指向正确位置并设置函数调用所需的所有代码。一般函数假定实际调用的函数作为额外数据传入,并用正确的值调用它。所有这些函数都适合直接放置在存储在PyUFuncObject结构的functions成员中的函数的数组中。

void PyUFunc_f_f_As_d_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_d_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_f_f(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_g_g(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_F_F_As_D_D(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_F_F(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_D_D(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_G_G(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_e_e(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_e_e_As_f_f(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_e_e_As_d_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)

为ufuncs类型特定的核心1-d函数,其中每个计算通过调用一个接受一个输入参数并返回一个输出的函数来获得。此函数在func中传递。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). 参数func必须支持相同的签名。_As_X_X变体假定一个数据类型的ndarray,但是转换这些值以使用采用不同数据类型的基础函数。因此,PyUFunc_f_f_As_d_d使用数据类型NPY_FLOAT的ndarrays,但调用一个接受double并返回double的C函数。

void PyUFunc_ff_f_As_dd_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_ff_f(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_dd_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_gg_g(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_FF_F_As_DD_D(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_DD_D(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_FF_F(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_GG_G(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_ee_e(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_ee_e_As_ff_f(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)
void PyUFunc_ee_e_As_dd_d(char ** args,npy_intp * dimensions,
npy_intp * steps,void * func)

为ufuncs键入特定的核心1-d函数,其中每个计算通过调用具有两个输入参数并返回一个输出的函数来获得。要调用的底层函数以func形式传递。字母对应于通用函数支持的特定数据类型的dtypechar。参数func必须支持相应的签名。_As_XX_X变体假定一种数据类型的narrays,但在循环的每次迭代中转换值,以使用采用不同数据类型的基础函数。

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

数据类型为NPY_OBJECT的单输入,单输出和双输入,单输出核心1-d功能。这些函数处理引用计数问题,并及早返回错误。要调用的实际函数是func,它必须接受签名(PyObject *) (PyObject *) t1对于PyUFunc_O_O(PyObject *)(PyObject *, PyObject *) / t10>用于PyUFunc_OO_O

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

这个通用1-d核函数假定func是表示输入对象的方法的字符串。对于循环的每次迭代,从数组中提取Python对象,并调用其func方法将结果返回到输出数组。

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

这个通用1-d核函数假设func是一个字符串,表示一个参数的输入对象的方法。args中的第一个参数是函数被调用的方法,args中的第二个参数是传递给函数的参数。函数的输出存储在args的第三个条目中。

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

这是由umath.frompyfunc(function,nin,nout)创建的动态ufuncs使用的1-d核心函数。在这种情况下,func是指向PyUFunc_PyFuncData结构的指针,它具有定义

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

在循环的每次迭代中,nin输入对象都从它们的对象数组中提取,并放入参数元组中,使用输入参数调用Python 可调用 nout输出放置到它们的对象数组中。

Importing the API

PY_UFUNC_UNIQUE_SYMBOL
NO_IMPORT_UFUNC
void import_ufunc(void)

这些是用于从扩展模块访问ufunc C-API的常数和函数,正如可以访问数组C-API一样。必须始终调用import_ufunc()函数(在扩展模块的初始化子程序中)。如果您的扩展模块在一个文件中,那就是所有必需的。如果您的扩展模块使用多个文件,其他两个常数是有用的。在这种情况下,将PY_UFUNC_UNIQUE_SYMBOL定义为代码的唯一属性,然后在不包含模块初始化函数但仍需要访问UFUNC API的源文件中定义PY_UFUNC_UNIQUE_SYMBOL到以前使用的相同名称,并且还定义NO_IMPORT_UFUNC

C-API实际上是一个数组的函数指针。此数组由import_ufunc创建(并由全局变量指向)。根据Py_UFUNC_UNIQUE_SYMBOLNO_IMPORT_UFUNC的状态,全局变量被静态定义或允许被其他文件看到。