Spec-Zone.ru › NumPy 1.20

UFunc API

Константы

UFUNC_ERR_{HANDLER}
UFUNC_ERR_IGNORE
UFUNC_ERR_WARN
UFUNC_ERR_RAISE
UFUNC_ERR_CALL
UFUNC_{THING}_{ERR}
UFUNC_MASK_DIVIDEBYZERO
UFUNC_MASK_OVERFLOW
UFUNC_MASK_UNDERFLOW
UFUNC_MASK_INVALID
UFUNC_SHIFT_DIVIDEBYZERO
UFUNC_SHIFT_OVERFLOW
UFUNC_SHIFT_UNDERFLOW
UFUNC_SHIFT_INVALID
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

Макросы

NPY_LOOP_BEGIN_THREADS

Используется в коде универсальных функций для освобождения блокировки Python GIL только в том случае, если loop->obj не истинно (т.е. это не цикл для массива OBJECT). Требует использования NPY_BEGIN_THREADS_DEF в области объявления переменной.

NPY_LOOP_END_THREADS

Используется в коде универсальных функций для повторного получения блокировки Python GIL, если она была освобождена (потому что loop->obj не было истинно).

Типы

PyUFuncGenericFunction

указатели на функции, которые фактически реализуют базовую (элемент за элементом) функцию N раз со следующей подписью:

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

args

Массив указателей на фактические данные для входных и выходных массивов. Входные аргументы указываются сначала, за которыми следуют выходные аргументы.

dimensions

Указатель на размер измерения, по которому эта функция выполняет цикл.

steps

Указатель на количество байтов, которые нужно пропустить, чтобы перейти к следующему элементу в этом измерении для каждого из входных и выходных аргументов.

data

Произвольные данные (дополнительные аргументы, имена функций и т.д.), которые могут храниться с ufunc и будут переданы при вызове.

Это пример функции, специализирующейся на сложении чисел с плавающей точкой двойной точности, возвращающей числа с плавающей точкой двойной точности.

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;
     }
}

Функции

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 содержит указатели на циклы 1D, реализующие базовую функциональность для каждого поддерживаемого типа.

Примечание

Аргументы func, data, types, name и doc не копируются функцией PyUFunc_FromFuncAndData. Вызывающая сторона должна гарантировать, что память, используемая этими массивами, не будет освобождена, пока объект ufunc жив.

Параметры
  • func – Должен быть массивом длиной ntypes, содержащим элементы типа PyUFuncGenericFunction.
  • data – Должен быть NULL или указателем на массив размером ntypes . Этот массив может содержать произвольные дополнительные данные, которые будут передаваться соответствующей функции цикла в массиве func.
  • types –

    Массив длиной (nin + nout) * ntypes из char кодирует numpy.dtype.num (только встроенные), которые соответствующая функция в массиве func принимает. Например, для сравнительной ufunc с тремя 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 – Сколько различных функций для разных типов данных реализовала ufunc.
  • nin – Количество входных данных для этой операции.
  • nout – Количество выходов
  • identity – Либо PyUFunc_One, PyUFunc_Zero, PyUFunc_MinusOne или PyUFunc_None. Это задает, что должно возвращаться, когда в метод reduce ufunc передается пустой массив. Специальное значение PyUFunc_IdentityValue может использоваться только с методом PyUFunc_FromFuncAndDataAndSignatureAndIdentity для того, чтобы разрешить использование произвольного объекта Python в качестве тождества.
  • name – Имя ufunc в виде строки, завершающейся NULL. Указание имени «add» или «multiply» позволяет получить специальное поведение для целочисленных сокращений, когда не указан тип данных. Если входной тип является целым числом (или булевым) типом данных, меньшим размера типа данных numpy.int_, он будет в процессе работы преобразован к типу данных numpy.int_ (или numpy.uint).
  • doc – Позволяет передать строку документации, которая будет храниться с ufunc. Строка документации не должна содержать имя функции или вызывающую подпись, так как они будут динамически определены из объекта и доступны при обращении к атрибуту __doc__ ufunc.
  • unused – Не используется и присутствует для обратной совместимости 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 выше, но имеет дополнительный аргумент signature для определения обобщенных универсальных функций. Аналогично тому, как ufunc построены вокруг операции элемент за элементом, gufunc построены вокруг операций подмассив за подмассивом, а подпись определяет подмассивы для обработки.

Параметры
  • signature – Подпись для новой gufunc. Установка ее в 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 для определения произвольного тождества для ufunc, когда identity передается как PyUFunc_IdentityValue.

Параметры
  • identity_value – Тождество для новой gufunc. Должно быть передано как NULL за исключением случая, когда аргумент identity равен PyUFunc_IdentityValue. Установка его в NULL эквивалентна вызову PyUFunc_FromFuncAndDataAndSignature.
int PyUFunc_RegisterLoopForType(PyUFuncObject* ufunc, int usertype, PyUFuncGenericFunction function, int* arg_types, void* data)

Эта функция позволяет пользователю зарегистрировать цикл 1D с уже созданной ufunc, который будет использоваться всякий раз, когда ufunc вызывается с любым из его входных аргументов как с типом данных, определенным пользователем. Это необходимо для работы ufunc со встроенными типами данных. Тип данных должен быть предварительно зарегистрирован в системе NumPy. Цикл передается как function. Этот цикл может принимать произвольные данные, которые должны передаваться как data. Типы данных, которые требуются циклу, передаются как arg_types, которые должны быть указателем на память, по крайней мере, размером с ufunc->nargs.

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

Эта функция ведет себя подобно PyUFunc_RegisterLoopForType выше, за исключением того, что она позволяет пользователю регистрировать цикл 1-D, используя объекты PyArray_Descr вместо значений типа dtype. Это позволяет зарегистрировать цикл 1-D для данных структурированных массивов и пользовательских типов данных вместо скалярных типов данных.

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

Заменяет цикл 1-D, соответствующий заданной подписи в уже созданном ufunc, новым циклом 1-D newfunc. Возвращает старый цикл 1-D в oldfunc. Возвращает 0 при успехе и -1 при ошибке. Эта функция работает только с встроенными типами (используйте PyUFunc_RegisterLoopForType для пользовательских типов). Подпись — это массив чисел типов данных, указывающих входные данные, за которыми следуют выходные данные, предполагаемые циклом 1-D.

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

Устарело начиная с версии NumPy: 1.19

Если NumPy не обнаружит проблемы с этой функцией, она будет быстро удалена без замены.

Вместо этой функции следует использовать PyObject_Call(ufunc, args, kwds). Вышеуказанная функция отличается от этой, поскольку она игнорирует поддержку не массивов или подклассов массивов в качестве входных данных. Чтобы обеспечить идентичное поведение, может потребоваться преобразовать все входные данные с помощью PyArray_FromAny(obj, NULL, 0, 0, NPY_ARRAY_ENSUREARRAY, NULL).

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 лежит набор функций, специфичных для типа, которые определяют основную функциональность для каждого из поддерживаемых типов. Эти функции должны вычислять базовую функцию N\geq1 раз. Дополнительные данные могут быть переданы и использованы во время расчета. Эта функция позволяет использовать некоторые общие функции в качестве этих основных циклических функций. Общая функция содержит весь код, необходимый для указания переменных в нужное место и настройки вызова функции. Общая функция предполагает, что фактическая функция для вызова передается в качестве дополнительных данных и вызывает ее с правильными значениями. Все эти функции подходят для непосредственного размещения в массиве функций, хранящихся в члене функции структуры PyUFuncObject.

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)

Функции ядра 1-D, специфичные для типа, для ufuncs, где каждое вычисление получается путем вызова функции, принимающей один входной аргумент и возвращающей один выходной. Эта функция передается в 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 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)

Функции ядра 1-D, специфичные для типа, для ufuncs, где каждое вычисление получается путем вызова функции, принимающей два входных аргумента и возвращающей один выходной. Базовая функция для вызова передается в качестве func. Буквы соответствуют dtypechar типов данных, поддерживаемых универсальной функцией. Аргумент func должен поддерживать соответствующую подпись. Варианты _As_XX_X предполагают ndarray одного типа данных, но преобразуют значения на каждой итерации цикла для использования базовой функции, принимающей другой тип данных.

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)

Функции ядра 1-D, принимающие один вход и один выход, и два входа и один выход для типа данных NPY_OBJECT. Эти функции обрабатывают проблемы с подсчетом ссылок и возвращаются рано при ошибке. Фактическая функция для вызова — 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)

Это функция ядра 1-D, используемая динамическими 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 из модулей расширения точно так же, как можно получить доступ к C-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–2021 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/1.20/reference/c-api/ufunc.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API