C-API 注册一个针对内置 ufunc 的 ufunc 循环
C-API register a ufunc loop against builtin ufunc
我正在寻找构建一个 numpy 扩展模块,它声明一个新的结构化数据类型并提供必要的内部 ufunc 循环以允许在其上执行 built-in math operations。
按照 creating your own ufunc 上的指南,我已经能够:
- 创建一个新的
PyUFuncGenericFunction
来模拟一个内置的 ufunc:
PyUFuncGenericFunction *add_uncertain = PyUFunc_FromFuncAndData(
NULL,
NULL,
NULL,
0,
2,
1,
PyUFunc_None,
"add_uncertain",
"adds arrays of uncertain values",
0);
- 声明数据类型,如:
PyObject *uncertain_double_dtype_dict = Py_BuildValue(
"[(s, s), (s, s)]",
"nominal", "f8", "uncertainty", "f8");
- 为特定的数据类型编写一个实现:
static PyObject *
add_uncertain_double(char **args, npy_intp *dimensions, npy_intp *steps, void *data)
{
char *in_arr_a = args[0];
char *in_arr_b = args[1];
char *out_arr = args[2];
npy_intp in_a_step = steps[0];
npy_intp in_b_step = steps[1];
npy_intp out_step = steps[2];
for (npy_intp i = 0; i < dimensions[0]; i++)
{
double *in_a = (double *)in_arr_a;
double *in_b = (double *)in_arr_b;
double *out = (double *)out_arr;
out[0] = in_a[0] + in_b[0];
out[1] = hypot(in_a[1], in_b[1]);
in_arr_a += in_a_step;
out_arr += out_step;
}
};
- 针对 mock ufunc 注册此函数:
PyUFunc_RegisterLoopForDescr(
add_uncertain,
uncertain_double_dtype,
&add_uncertain_double,
add_uncertain_double_dtypes,
NULL);
当作为模块导出时,这会按预期工作,但需要用户通过导出的 ufunc 包调用该函数(即 my_package.add_uncertain
);我宁愿通过 numpy.add
.
获得此实现
numpy C-API 文档的 registering a ufunc loop section 中使用的语言似乎表明我应该能够针对内置 ufunc 注册 ufunc 循环。为此,我相信我应该将内置 PyUFuncGenericFunction
传递给 PyUFunc_RegisterLoopForDescr
.
如果我知道我是否在正确的轨道上,我将非常感激,如果是的话,我应该在哪里寻找内置 PyUFuncGenericFunction
the numpy rational type test 中包含的解决方案是使用 PyImport_Import
导入 numpy
,然后使用 PyObject_GetAttrString
获取 add
ufunc,此时可以注册新的内部循环:
numpy_str = PyUnicode_FromString("numpy");
if (!numpy_str)
return NULL;
numpy = PyImport_Import(numpy_str);
Py_DECREF(numpy_str);
if (!numpy)
return NULL;
PyUFuncObject *add_ufunc = PyObject_GetAttrString(numpy, "add");
if (!add_ufunc)
return NULL;
PyUFunc_RegisterLoopForDescr(
add_ufunc,
uncertain_double_dtype,
&add_uncertain_double,
add_uncertain_double_dtypes,
NULL);
我正在寻找构建一个 numpy 扩展模块,它声明一个新的结构化数据类型并提供必要的内部 ufunc 循环以允许在其上执行 built-in math operations。
按照 creating your own ufunc 上的指南,我已经能够:
- 创建一个新的
PyUFuncGenericFunction
来模拟一个内置的 ufunc:PyUFuncGenericFunction *add_uncertain = PyUFunc_FromFuncAndData( NULL, NULL, NULL, 0, 2, 1, PyUFunc_None, "add_uncertain", "adds arrays of uncertain values", 0);
- 声明数据类型,如:
PyObject *uncertain_double_dtype_dict = Py_BuildValue( "[(s, s), (s, s)]", "nominal", "f8", "uncertainty", "f8");
- 为特定的数据类型编写一个实现:
static PyObject * add_uncertain_double(char **args, npy_intp *dimensions, npy_intp *steps, void *data) { char *in_arr_a = args[0]; char *in_arr_b = args[1]; char *out_arr = args[2]; npy_intp in_a_step = steps[0]; npy_intp in_b_step = steps[1]; npy_intp out_step = steps[2]; for (npy_intp i = 0; i < dimensions[0]; i++) { double *in_a = (double *)in_arr_a; double *in_b = (double *)in_arr_b; double *out = (double *)out_arr; out[0] = in_a[0] + in_b[0]; out[1] = hypot(in_a[1], in_b[1]); in_arr_a += in_a_step; out_arr += out_step; } };
- 针对 mock ufunc 注册此函数:
PyUFunc_RegisterLoopForDescr( add_uncertain, uncertain_double_dtype, &add_uncertain_double, add_uncertain_double_dtypes, NULL);
当作为模块导出时,这会按预期工作,但需要用户通过导出的 ufunc 包调用该函数(即 my_package.add_uncertain
);我宁愿通过 numpy.add
.
numpy C-API 文档的 registering a ufunc loop section 中使用的语言似乎表明我应该能够针对内置 ufunc 注册 ufunc 循环。为此,我相信我应该将内置 PyUFuncGenericFunction
传递给 PyUFunc_RegisterLoopForDescr
.
如果我知道我是否在正确的轨道上,我将非常感激,如果是的话,我应该在哪里寻找内置 PyUFuncGenericFunction
the numpy rational type test 中包含的解决方案是使用 PyImport_Import
导入 numpy
,然后使用 PyObject_GetAttrString
获取 add
ufunc,此时可以注册新的内部循环:
numpy_str = PyUnicode_FromString("numpy");
if (!numpy_str)
return NULL;
numpy = PyImport_Import(numpy_str);
Py_DECREF(numpy_str);
if (!numpy)
return NULL;
PyUFuncObject *add_ufunc = PyObject_GetAttrString(numpy, "add");
if (!add_ufunc)
return NULL;
PyUFunc_RegisterLoopForDescr(
add_ufunc,
uncertain_double_dtype,
&add_uncertain_double,
add_uncertain_double_dtypes,
NULL);