UFunc API
Константы
-
UFUNC_ERR_{HANDLER} -
{HANDLER}может быть IGNORE, WARN, RAISE или CALL
-
UFUNC_{THING}_{ERR} -
{THING}может быть MASK, SHIFT или FPE, а{ERR}может быть DIVIDEBYZERO, OVERFLOW, UNDERFLOW и INVALID.
-
PyUFunc_{VALUE} -
-
PyUFunc_One
-
PyUFunc_Zero
-
PyUFunc_MinusOne
-
PyUFunc_ReorderableNone
-
PyUFunc_None
-
PyUFunc_IdentityValue
-
Макросы
-
NPY_LOOP_BEGIN_THREADS -
Используется в коде универсальной функции для освобождения блокировки Python GIL только в том случае, если loop->obj не равно true (т.е. это не цикл обработки массива OBJECT). Требуется использование
NPY_BEGIN_THREADS_DEFв области объявления переменных.
-
NPY_LOOP_END_THREADS -
Используется в коде универсальной функции для повторного получения блокировки Python GIL, если она была освобождена (потому что loop->obj не равно true).
Функции
-
PyObject* PyUFunc_FromFuncAndData(PyUFuncGenericFunction* func, void** data, char* types, int ntypes, int nin, int nout, int identity, char* name, char* doc, int unused) -
Создает новую универсальную функцию широковещательной передачи из необходимых переменных. Каждая универсальная функция строится вокруг понятия операции на элементе-по-элементу. Каждый объект универсальной функции содержит указатели на циклы 1-d, реализующие основную функциональность для каждого поддерживаемого типа.
Примечание
Аргументы func, data, types, name и doc не копируются методом
PyUFunc_FromFuncAndData. Вызывающая сторона должна гарантировать, что память, используемая этими массивами, не освобождается до тех пор, пока объект универсальной функции жив.- Параметры
-
-
func –
Должен быть массивом длины ntypes, содержащим
PyUFuncGenericFunctionэлементы. Эти элементы являются указателями на функции, которые фактически реализуют базовую (элемент-по-элементу) функциюраз со следующим сигнатура:
-
void loopfunc( -
char** args, npy_intp* dimensions, npy_intp* steps, void* data) -
args
Массив указателей на фактические данные для входных и выходных массивов. Сначала указываются входные аргументы, за ними — выходные аргументы.
dimensions
Указатель на размер измерения, по которому эта функция циклически обрабатывает данные.
steps
Указатель на количество байтов для перехода к следующему элементу в этом измерении для каждого из входных и выходных аргументов.
data
Произвольные данные (дополнительные аргументы, имена функций и т. д.), которые могут храниться с универсальной функцией и будут передаваться при её вызове.
Это пример функции, специализированной для сложения чисел с плавающей точкой двойной точности, возвращающей числа с плавающей точкой двойной точности.
static void double_add(char **args, npy_intp *dimensions, npy_intp *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; } }
-
-
data – Должен быть
NULLили указателем на массив размера ntypes. Этот массив может содержать произвольные дополнительные данные, которые будут переданы соответствующей функции цикла в массиве func. -
types –
Массив длины
(nin + nout) * ntypesизcharзначений, кодирующихnumpy.dtype.num(только встроенные), которые принимает соответствующая функция в массивеfunc. Например, для универсальной функции сравнения с тремяntypes, двумяninи однойnout, где первая функция принимает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 – Сколько различных функций для разных типов данных реализовала универсальная функция.
- nin – Количество входных данных для данной операции.
- nout – Количество выходных данных
-
identity – Либо
PyUFunc_One,PyUFunc_Zero,PyUFunc_MinusOneилиPyUFunc_None. Это задает, что должно быть возвращено, когда пустой массив передаётся методу reduce универсальной функции. Специальное значениеPyUFunc_IdentityValueможет использоваться только с методомPyUFunc_FromFuncAndDataAndSignatureAndIdentity, чтобы разрешить использование произвольного объекта Python в качестве тождества. -
name – Имя универсальной функции в виде строки, завершенной символом
NULL. Указание имени «add» или «multiply» позволяет использовать специальное поведение для целочисленных сокращений, когда тип данных не указан. Если входной тип — целочисленный (или булев) тип данных меньшего размера, чем размер типа данныхnumpy.int_, он будет внутренне преобразован к типу данныхnumpy.int_(илиnumpy.uint). - doc – Разрешает передачу документационной строки, которая будет храниться вместе с универсальной функцией. Документационная строка не должна содержать имя функции или вызывающий синтаксис, так как он будет динамически определен из объекта и будет доступен при обращении к атрибуту __doc__ универсальной функции.
- unused – Не используется и присутствует для обеспечения обратной совместимости API C.
-
-
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 выше, но имеет дополнительный аргумент signature для определения обобщенных универсальных функций. Аналогично тому, как универсальные функции построены вокруг операции на элементе по элементу, обобщенные универсальные функции построены вокруг операций на подмассивах, при этом сигнатура определяет подмассивы, над которыми необходимо выполнить операцию.
- Параметры
-
- 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. Установка ее в NULL эквивалентна вызову PyUFunc_FromFuncAndDataAndSignature.- Параметры
-
-
identity_value – Тождество для новой обобщенной универсальной функции. Должен передаваться как
NULL, если только аргументidentityне равенPyUFunc_IdentityValue. Установка его в NULL эквивалентна вызову PyUFunc_FromFuncAndDataAndSignature.
-
identity_value – Тождество для новой обобщенной универсальной функции. Должен передаваться как
-
int PyUFunc_RegisterLoopForType(PyUFuncObject* ufunc, int usertype, PyUFuncGenericFunction function, int* arg_types, void* data) -
Эта функция позволяет пользователю зарегистрировать цикл 1-d с уже созданной универсальной функцией, который будет использоваться всякий раз, когда универсальная функция вызывается с любым из ее входных аргументов в качестве пользовательского типа данных. Это необходимо для работы универсальных функций со встроенными типами данных. Тип данных должен быть предварительно зарегистрирован в системе NumPy. Цикл передается как function. Этот цикл может принимать произвольные данные, которые должны быть переданы как data. Типы данных, которые требуются циклу, передаются в виде arg_types, которые должны быть указателем на память размером не меньше ufunc->nargs.
-
int PyUFunc_RegisterLoopForDescr(PyUFuncObject* ufunc, PyArray_Descr* userdtype, PyUFuncGenericFunction function, PyArray_Descr** arg_dtypes, void* data) -
Эта функция ведет себя аналогично PyUFunc_RegisterLoopForType выше, за исключением того, что позволяет пользователю регистрировать цикл 1-d с использованием объектов PyArray_Descr вместо значений num типа данных. Это позволяет регистрировать цикл 1-d для типов данных структурированных массивов и пользовательских типов данных вместо скалярных типов данных.
-
int PyUFunc_ReplaceLoopBySignature(PyUFuncObject* ufunc, PyUFuncGenericFunction newfunc, int* signature, PyUFuncGenericFunction* oldfunc) -
Заменяет цикл 1-d, соответствующий заданной signature в уже созданной ufunc, новым циклом 1-d newfunc. Возвращает старую функцию цикла 1-d в oldfunc. Возвращает 0 при успехе и -1 при неудаче. Эта функция работает только со встроенными типами (используйте
PyUFunc_RegisterLoopForTypeдля пользовательских типов). Сигнатура — массив номеров типов данных, указывающих входные данные, за которыми следуют выходные данные, предполагаемые циклом 1-d.
-
int PyUFunc_GenericFunction(PyUFuncObject* self, PyObject* args, PyObject* kwds, PyArrayObject** mps) -
Обобщенный вызов ufunc. Ufunc передаётся как self, аргументы ufunc как args и kwds. Аргумент mps — массив указателей на
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) -
Получение значений Python, используемых для обработки ufunc, из локального хранилища потока, если значения по умолчанию не заданы, в этом случае поиск по имени пропускается. Имя размещается в виде строки в первом элементе *errobj. Второй элемент — найденная функция, вызываемая при возникновении ошибки (обработчик ошибок). Значение найденного размера буфера, который необходимо использовать, передаётся в bufsize, а значение маски ошибок — в errmask.
Общие функции
В основе каждого ufunc лежит набор функций для конкретных типов данных, определяющих базовые функциональные возможности для каждого из поддерживаемых типов. Эти функции должны вычислять базовую функцию раз. Дополнительные данные могут передаваться и использоваться во время вычисления. Эта функция позволяет использовать некоторые общие функции в качестве этих базовых циклических функций. Общая функция содержит весь необходимый код для указания переменных на нужное место и подготовки вызова функции. Общая функция предполагает, что фактическая функция, которую нужно вызвать, передаётся в качестве дополнительных данных, и вызывает её с правильными значениями. Все эти функции подходят для прямого размещения в массиве функций, хранящемся в члене functions структуры PyUFuncObject.
-
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) -
Функции ядра для ufunc, специфичные для типов данных, где каждое вычисление получается вызовом функции, принимающей один входной аргумент и возвращающей один выходной. Эта функция передаётся в
func. Буквы соответствуют dtypechar для поддерживаемых типов данных (e— полуточная,f— float,d— double,g— long double,F— cfloat,D— cdouble,G— clongdouble). Аргумент func должен поддерживать тот же синтаксис. Варианты _As_X_X предполагают ndarray одного типа данных, но преобразуют значения для использования базовой функции, принимающей другой тип данных. Таким образом,PyUFunc_f_f_As_d_dиспользует ndarray типа данныхNPY_FLOAT, но обращается к C-функции, принимающей double и возвращающей double.
-
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) -
Функции ядра для ufunc, специфичные для типов данных, где каждое вычисление получается вызовом функции, принимающей два входных аргумента и возвращающей один выходной. Базовая вызываемая функция передаётся как func. Буквы соответствуют dtypechar для конкретного типа данных, поддерживаемого универсальной функцией. Аргумент
funcдолжен поддерживать соответствующий синтаксис. Варианты_As_XX_Xпредполагают ndarray одного типа данных, но преобразуют значения на каждой итерации цикла для использования базовой функции, принимающей другой тип данных.
-
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. Эти функции обрабатывают проблемы с учётом ссылок и возвращаются досрочно при возникновении ошибки. Фактическая функция, которую нужно вызвать, — func, и она должна принимать вызовы со структурой(PyObject*) (PyObject*)дляPyUFunc_O_Oили(PyObject*)(PyObject *, PyObject *)дляPyUFunc_OO_O.
-
void PyUFunc_O_O_method(char** args, npy_intp* dimensions, npy_intp* steps, void* func) -
Эта общая функция ядра одномерная предполагает, что func — строка, представляющая метод входного объекта. На каждой итерации цикла из массива извлекается объект Python, и вызывается его метод func, возвращающий результат в массив вывода.
-
void PyUFunc_OO_O_method(char** args, npy_intp* dimensions, npy_intp* steps, void* func) -
Эта общая функция ядра одномерная предполагает, что func — строка, представляющая метод входного объекта, принимающий один аргумент. Первый аргумент в args — метод, чья функция вызывается, второй аргумент в args — аргумент, передаваемый в функцию. Результат функции сохраняется в третьем элементе args.
-
void PyUFunc_On_Om(char** args, npy_intp* dimensions, npy_intp* steps, void* func) -
Это функция ядра одномерная, используемая динамическими ufunc, созданными с помощью umath.frompyfunc(function, nin, nout). В этом случае func — указатель на структуру
PyUFunc_PyFuncDataс определением-
PyUFunc_PyFuncData -
typedef struct { int nin; int nout; PyObject *callable; } PyUFunc_PyFuncData;
На каждой итерации цикла из массивов объектов извлекаются nin входных объектов и помещаются в кортеж аргументов, Python-функция вызывается с входными аргументами, и nout выходных значений помещаются в массивы выходных объектов.
-
Импорт API
-
PY_UFUNC_UNIQUE_SYMBOL
-
NO_IMPORT_UFUNC
-
void import_ufunc(void) -
Это константы и функции для доступа к C-API ufunc из расширений модулей точно так же, как доступно к API массивов. Функция
import_ufunc() всегда должна вызываться (в процедуре инициализации расширения модуля). Если ваше расширение модуля находится в одном файле, то этого достаточно. Другие две константы полезны, если ваше расширение модуля использует несколько файлов. В этом случае определитеPY_UFUNC_UNIQUE_SYMBOLна уникальное значение для вашего кода, а затем в файлах исходного кода, которые не содержат функцию инициализации модуля, но всё ещё нуждаются в доступе к API UFUNC, определитеPY_UFUNC_UNIQUE_SYMBOLс тем же именем, что и ранее, а также определитеNO_IMPORT_UFUNC.C-API фактически является массивом указателей на функции. Этот массив создаётся (и на него указывает глобальная переменная) функцией import_ufunc. Глобальная переменная либо статически определена, либо доступна другим файлам в зависимости от состояния
PY_UFUNC_UNIQUE_SYMBOLиNO_IMPORT_UFUNC.
© 2005–2020 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.18/reference/c-api/ufunc.html