ufunc API#
常量#
UFUNC_{THING}_{ERR}
宏#
-
NPY_LOOP_BEGIN_THREADS#
在通用函数代码中使用,仅当 loop->obj 不为真时才释放 Python GIL(即,这不是 OBJECT 数组循环).需要在变量声明区域中使用
NPY_BEGIN_THREADS_DEF.
-
NPY_LOOP_END_THREADS#
如果在通用函数代码中释放了 Python GIL,则重新获取它(因为 loop->obj 不为真).
类型#
-
type PyUFuncGenericFunction#
指向实际实现底层(逐个元素)函数 \(N\) 次的函数的指针,具有以下签名:
-
void loopfunc(char **args, npy_intp const *dimensions, npy_intp const *steps, void *data)#
- 参数:
args – 指向输入和输出数组的实际数据的指针数组.输入参数首先给出,然后是输出参数.
dimensions – 指向此函数循环的维度大小的指针.
steps – 指向字节数的指针,该字节数跳到此维度中每个输入和输出参数的下一个元素.
data – 可以与 ufunc 一起存储的任意数据(额外参数,函数名称等),并在调用时传入.可以为
NULL. .. versionchanged:: 1.23.0 除了NULL值数组之外,还接受NULLdata .
这是专门用于双精度加法返回双精度的 func 示例.
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; } }
-
void loopfunc(char **args, npy_intp const *dimensions, npy_intp const *steps, void *data)#
函数#
-
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)#
从必需变量创建一个新的广播通用函数.每个 ufunc 都围绕逐个元素操作的概念构建.每个 ufunc 对象都包含指向 1-d 循环的指针,这些指针实现了每种支持类型的基本功能.
备注
PyUFunc_FromFuncAndData不会复制 func,data,types,name 和 doc 参数.调用者必须确保只要 ufunc 对象存在,就不会释放这些数组使用的内存.- 参数:
func – 必须指向包含 ntypes
PyUFuncGenericFunction元素的数组.data – 应为
NULL或指向大小为 ntypes 的数组的指针.此数组可能包含任意额外数据,这些数据将传递给 func 数组中的相应循环函数,包括NULL.types – 长度为
(nin + nout) * ntypes的char数组,用于编码与func数组中相应函数接受的numpy.dtype.num(仅内置) . 例如,对于具有三个ntypes,两个nin和一个nout的比较 ufunc,其中第一个函数接受numpy.int32,第二个函数接受numpy.int64,两者都返回numpy.bool_,则types将为(char[]) {5, 5, 0, 7, 7, 0},因为NPY_INT32为 5,NPY_INT64为 7,NPY_BOOL为 0. 如果需要,也可以使用位宽名称(例如NPY_INT32,NPY_COMPLEX128). 类型转换规则 将在运行时用于查找提供的输入/输出可调用的第一个func.ntypes – ufunc 实现了多少个不同的特定于数据类型的功能.
nin – 此操作的输入数量.
nout – 输出的数量
identity – 可以是
PyUFunc_One,PyUFunc_Zero,PyUFunc_MinusOne或PyUFunc_None.它指定当空数组传递给 ufunc 的 reduce 方法时应返回什么.特殊值PyUFunc_IdentityValue只能与PyUFunc_FromFuncAndDataAndSignatureAndIdentity方法一起使用,以允许将任意 python 对象用作 identity.name – ufunc 的名称,以
NULL结尾的字符串.指定名称为"add"或"multiply"会为整数类型的 reductions 启用特殊行为,当未给出 dtype 时.如果输入类型是小于numpy.int_数据类型大小的整数(或布尔)数据类型,它将在内部向上转换为numpy.int_(或numpy.uint)数据类型.doc – 允许传入一个文档字符串,与 ufunc 一起存储.文档字符串不应包含函数的名称或调用签名,因为这将从对象动态确定,并在访问 ufunc 的 __doc__* 属性时可用.
unused – 未使用,为了 C-API 的向后兼容性而存在.
-
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)#
此函数与上面的 PyUFunc_FromFuncAndData 非常相似,但有一个额外的 signature 参数,用于定义 generalized universal functions .与 ufunc 围绕逐个元素的操作构建类似,gufunc 围绕逐个子数组的操作构建, signature 定义要操作的子数组.
- 参数:
signature – 新 gufunc 的 signature.将其设置为 NULL 等同于调用 PyUFunc_FromFuncAndData.会创建字符串的副本,因此可以释放传入的缓冲区.
-
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)#
此函数与上面的
PyUFunc_FromFuncAndDataAndSignature非常相似,但有一个额外的 identity_value 参数,用于在将identity作为PyUFunc_IdentityValue传递时,为 ufunc 定义一个任意 identity.- 参数:
identity_value – 新 gufunc 的 identity.除非将
identity参数传递为PyUFunc_IdentityValue,否则必须将其作为NULL传递.将其设置为 NULL 等同于调用 PyUFunc_FromFuncAndDataAndSignature.
-
int PyUFunc_RegisterLoopForType(PyUFuncObject *ufunc, int usertype, PyUFuncGenericFunction function, int *arg_types, void *data)#
此函数允许用户向已创建的 ufunc 注册一个 1-D 循环,以便在 ufunc 被调用时,任何输入参数都是用户定义的数据类型时使用.这是使 ufunc 与内置数据类型一起工作所必需的.数据类型必须已在 numpy 系统中注册.循环作为函数传入.此循环可以接受任意数据,这些数据应作为 data 传入.循环需要的数据类型作为 arg_types 传入,arg_types 必须是指向至少与 ufunc->nargs 一样大的内存的指针.
-
int PyUFunc_RegisterLoopForDescr(PyUFuncObject *ufunc, PyArray_Descr *userdtype, PyUFuncGenericFunction function, PyArray_Descr **arg_dtypes, void *data)#
此函数的行为类似于上面的 PyUFunc_RegisterLoopForType,但它允许用户使用 PyArray_Descr 对象而不是 dtype 类型数字值来注册 1-D 循环.这允许为结构化数组数据数据类型和自定义数据类型而不是标量数据类型注册 1-D 循环.
-
int PyUFunc_ReplaceLoopBySignature(PyUFuncObject *ufunc, PyUFuncGenericFunction newfunc, int *signature, PyUFuncGenericFunction *oldfunc)#
用新的 1-D 循环 newfunc 替换已创建的 ufunc 中与给定 signature 匹配的 1-D 循环.在 oldfunc 中返回旧的 1-D 循环函数.成功时返回 0,失败时返回 -1.此函数仅适用于内置类型(对于用户定义的类型,请使用
PyUFunc_RegisterLoopForType).signature 是一个数据类型数字数组,指示 1-D 循环假定的输入,后跟输出.
-
void PyUFunc_clearfperr()#
清除 IEEE 错误标志.
通用函数#
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_F_F_As_D_D(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)#
ufunc 的类型特定核心 1-d 函数,其中每次计算都是通过调用一个接受一个输入参数并返回一个输出的函数来获得的. 此函数在
func中传递. 字母对应于支持数据类型的 dtypechar (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数据类型的 ndarray,但调用一个接受 double 并返回 double 的 C 函数.
-
void PyUFunc_ff_f_As_dd_d(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_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)#
ufunc 的类型特定核心 1-d 函数,其中每次计算都是通过调用一个接受两个输入参数并返回一个输出的函数来获得的. 要调用的底层函数作为 func 传入. 字母对应于通用函数支持的特定数据类型的 dtypechar. 参数
func必须支持相应的签名._As_XX_X变体假定一种数据类型的 ndarray,但在循环的每次迭代中转换这些值,以使用采用不同数据类型的底层函数.
-
void PyUFunc_OO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#
NPY_OBJECT数据类型的单输入,单输出和双输入,单输出核心 1-d 函数. 这些函数处理引用计数问题,并在出错时提前返回. 要调用的实际函数是 func,它必须接受带有签名(PyObject) (PyObject)用于PyUFunc_O_O或(PyObject)(PyObject , PyObject )用于PyUFunc_OO_O的调用.
-
void PyUFunc_O_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#
这个通用 1-d 核心函数假定 func 是一个字符串,表示输入对象的方法. 对于循环的每次迭代,从数组中提取 Python 对象,并调用其 func 方法,将结果返回到输出数组.
-
void PyUFunc_OO_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#
这个通用 1-d 核心函数假定 func 是一个字符串,表示输入对象的方法,该方法接受一个参数. args 中的第一个参数是要调用其函数的函数,args 中的第二个参数是传递给函数的参数. 函数的输出存储在 args 的第三个条目中.
-
void PyUFunc_On_Om(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)#
这是 umath.frompyfunc(function, nin, nout) 创建的动态 ufunc 使用的 1-d 核心函数. 在这种情况下,func 是指向
PyUFunc_PyFuncData结构的指针,该结构具有以下定义-
type PyUFunc_PyFuncData#
typedef struct { int nin; int nout; PyObject *callable; } PyUFunc_PyFuncData;
在循环的每次迭代中,从其对象数组中提取 nin 个输入对象,并将它们放入参数元组中,使用输入参数调用 Python 可调用对象,并将 nout 个输出放入其对象数组中.
-
type PyUFunc_PyFuncData#
导入 API#
-
PY_UFUNC_UNIQUE_SYMBOL#
-
NO_IMPORT_UFUNC#
-
int PyUFunc_ImportUFuncAPI(void)#
确保 UFunc C-API 已导入且可用. 成功时返回
0,如果无法导入 NumPy,则返回-1并设置一个错误. 虽然最好在模块初始化时调用一次,但如果多次调用此函数,它的开销非常小.在 2.0 版本加入: 此函数主要检查
PyUFunc_API == NULL,因此如果需要,可以手动向后移植它.
-
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_SYMBOL和NO_IMPORT_UFUNC的状态.