Библиотека математических функций NumPy
Библиотека математических функций NumPy (npymath) — это первый шаг в этом направлении. Эта библиотека содержит большинство математических функций C99, которые могут использоваться на платформах, где C99 не поддерживается должным образом. Основные математические функции имеют тот же API, что и функции C99, за исключением npy_* префикса.
Доступные функции определены в <numpy/npy_math.h> — обращайтесь к этому заголовку в случае сомнений.
Примечание
Ведётся работа по уменьшению npymath (поскольку совместимость компиляторов с C99 улучшилась со временем) и упрощению её использования как зависимости только на основе заголовков. Это позволит избежать проблем с поставкой статической библиотеки, скомпилированной с компилятором, который может не совпадать с компилятором, используемым зависимыми пакетами или конечными пользователями. Подробнее см. gh-20880.
Классификация чисел с плавающей точкой
- NPY_NAN
-
Эта макрос определяет значение NaN (Not a Number), и гарантируется, что бит знака не установлен (‘положительное’ NaN). Соответствующие макросы одинарной и расширенной точности доступны с суффиксом F и L.
- NPY_INFINITY
-
Эта макрос определяет положительную бесконечность. Соответствующие макросы одинарной и расширенной точности доступны с суффиксом F и L.
- NPY_PZERO
-
Эта макрос определяет положительный ноль. Соответствующие макросы одинарной и расширенной точности доступны с суффиксом F и L.
- NPY_NZERO
-
Эта макрос определяет отрицательный ноль (то есть с установленным битом знака). Соответствующие макросы одинарной и расширенной точности доступны с суффиксом F и L.
- npy_isnan(x)
-
Это псевдоним для C99 isnan: работает для одинарной, двойной и расширенной точности и возвращает ненулевое значение, если x — NaN.
- npy_isfinite(x)
-
Это псевдоним для C99 isfinite: работает для одинарной, двойной и расширенной точности и возвращает ненулевое значение, если x не является ни NaN, ни бесконечностью.
- npy_isinf(x)
-
Это псевдоним для C99 isinf: работает для одинарной, двойной и расширенной точности и возвращает ненулевое значение, если x бесконечен (положительный и отрицательный).
- npy_signbit(x)
-
Это псевдоним для C99 signbit: работает для одинарной, двойной и расширенной точности и возвращает ненулевое значение, если x имеет установленный бит знака (то есть число отрицательное).
- npy_copysign(x, y)
-
Это псевдоним для C99 copysign: возвращает x со знаком, совпадающим со знаком y. Работает для любых значений, включая inf и nan. Одинарная и расширенная точность доступны с суффиксом f и l.
Полезные математические константы
Следующие математические константы доступны в npy_math.h. Одинарная и расширенная точность также доступны, добавив f и l суффиксы соответственно.
- NPY_E
-
Основание натурального логарифма (\(e\))
- NPY_LOG2E
-
Логарифм по основанию 2 от константы Эйлера (\(\frac{\ln(e)}{\ln(2)}\))
- NPY_LOG10E
-
Логарифм по основанию 10 от константы Эйлера (\(\frac{\ln(e)}{\ln(10)}\))
- NPY_LOGE2
-
Натуральный логарифм 2 (\(\ln(2)\))
- NPY_LOGE10
-
Натуральный логарифм 10 (\(\ln(10)\))
- NPY_PI
-
Пи (\(\pi\))
- NPY_PI_2
-
Пи, делённое на 2 (\(\frac{\pi}{2}\))
- NPY_PI_4
-
Пи, делённое на 4 (\(\frac{\pi}{4}\))
- NPY_1_PI
-
Обратная величина пи (\(\frac{1}{\pi}\))
- NPY_2_PI
-
Двойная обратная величина пи (\(\frac{2}{\pi}\))
- NPY_EULER
-
- Константа Эйлера
-
\(\lim_{n\rightarrow\infty}({\sum_{k=1}^n{\frac{1}{k}}-\ln n})\)
Низкоуровневая обработка чисел с плавающей точкой
Они могут быть полезны для точного сравнения чисел с плавающей точкой.
- doublenpy_nextafter(doublex, doubley)
-
Это псевдоним для C99 nextafter: возвращает следующее представимое значение числа с плавающей точкой от x в направлении y. Для одинарной и расширенной точности доступны суффиксы f и l.
- doublenpy_spacing(doublex)
-
Это функция, эквивалентная встроенной функции Fortran. Возвращает расстояние между x и следующим представимым значением числа с плавающей точкой от x, например, spacing(1) == eps. Для NaN и +/- inf возвращает NaN. Для одинарной и расширенной точности доступны суффиксы f и l.
- voidnpy_set_floatstatus_divbyzero()
-
Устанавливает исключение деления на ноль для чисел с плавающей точкой
- voidnpy_set_floatstatus_overflow()
-
Устанавливает исключение переполнения для чисел с плавающей точкой
- voidnpy_set_floatstatus_underflow()
-
Устанавливает исключение недополнения для чисел с плавающей точкой
- voidnpy_set_floatstatus_invalid()
-
Устанавливает исключение некорректного значения для чисел с плавающей точкой
- intnpy_get_floatstatus()
-
Получение статуса чисел с плавающей точкой. Возвращает битовую маску со следующими возможными флагами:
- NPY_FPE_DIVIDEBYZERO
- NPY_FPE_OVERFLOW
- NPY_FPE_UNDERFLOW
- NPY_FPE_INVALID
Обратите внимание, что
npy_get_floatstatus_barrierпредпочтительнее, так как он предотвращает агрессивную оптимизацию компилятора, переупорядочивающую вызов относительно кода, устанавливающего статус, что может привести к неверным результатам.
- intnpy_get_floatstatus_barrier(char*)
-
Получение статуса чисел с плавающей точкой. В качестве параметра передаётся указатель на локальную переменную, чтобы предотвратить агрессивную оптимизацию компилятора, переупорядочивающую этот вызов относительно кода, устанавливающего статус, что может привести к неверным результатам.
Возвращает битовую маску со следующими возможными флагами:
- NPY_FPE_DIVIDEBYZERO
- NPY_FPE_OVERFLOW
- NPY_FPE_UNDERFLOW
- NPY_FPE_INVALID
Добавлена в версии 1.15.0.
- intnpy_clear_floatstatus()
-
Очищает статус чисел с плавающей точкой. Возвращает предыдущую маску статуса.
Обратите внимание, что
npy_clear_floatstatus_barrierпредпочтительнее, так как он предотвращает агрессивную оптимизацию компилятора, переупорядочивающую вызов относительно кода, устанавливающего статус, что может привести к неверным результатам.
- intnpy_clear_floatstatus_barrier(char*)
-
Очищает статус чисел с плавающей точкой. В качестве параметра передаётся указатель на локальную переменную, чтобы предотвратить агрессивную оптимизацию компилятора. Возвращает предыдущую маску статуса.
Добавлена в версии 1.15.0.
Поддержка комплексных чисел
Добавлены функции комплексных чисел в стиле C99. Их можно использовать, если вы хотите реализовать переносимые C-расширения. С NumPy 2.0 мы используем типы комплексных чисел C99 в качестве базового типа:
typedef double _Complex npy_cdouble; typedef float _Complex npy_cfloat; typedef long double _Complex npy_clongdouble;
MSVC не поддерживает тип _Complex сам по себе, но добавил поддержку заголовка C99 complex.h путём предоставления собственной реализации. Таким образом, под MSVC будут использоваться эквивалентные типы MSVC:
typedef _Dcomplex npy_cdouble; typedef _Fcomplex npy_cfloat; typedef _Lcomplex npy_clongdouble;
Поскольку MSVC всё ещё не поддерживает синтаксис C99 для инициализации комплексного числа, вам необходимо ограничиться синтаксисом, совместимым с C90, например:
/* a = 1 + 2i \*/ npy_complex a = npy_cpack(1, 2); npy_complex b; b = npy_log(a);
Несколько утилит также были добавлены в numpy/npy_math.h, чтобы получить или установить действительную или мнимую часть комплексного числа:
npy_cdouble c;
npy_csetreal(&c, 1.0);
npy_csetimag(&c, 0.0);
printf("%d + %di\n", npy_creal(c), npy_cimag(c));
Изменено в версии 2.0.0: Базовые C-типы для всех типов комплексных чисел numpy были изменены на типы комплексных чисел C99. До этого использовалось следующее для представления комплексных типов:
typedef struct { double real, imag; } npy_cdouble;
typedef struct { float real, imag; } npy_cfloat;
typedef struct {npy_longdouble real, imag;} npy_clongdouble;
Использование представления struct гарантировало, что комплексные числа можно использовать на всех платформах, даже на тех, где не поддерживаются встроенные типы комплексных чисел. Это также означало, что вместе с NumPy необходимо было поставлять статическую библиотеку, чтобы предоставить слой совместимости C99 для использования нижестоящими пакетами. Однако в последние годы поддержка собственных типов комплексных чисел значительно улучшилась, и MSVC добавил встроенную поддержку заголовка complex.h в 2019 году.
Для облегчения межверсионной совместимости были добавлены макросы, использующие новые API набора.
#define NPY_CSETREAL(z, r) npy_csetreal(z, r) #define NPY_CSETIMAG(z, i) npy_csetimag(z, i)
В numpy/npy_2_complexcompat.h также предоставляется слой совместимости. Он проверяет, существуют ли макросы, и переходит к синтаксису 1.x в случае их отсутствия.
#include <numpy/npy_math.h> #ifndef NPY_CSETREALF #define NPY_CSETREALF(c, r) (c)->real = (r) #endif #ifndef NPY_CSETIMAGF #define NPY_CSETIMAGF(c, i) (c)->imag = (i) #endif
Мы рекомендуем всем нижестоящим пакетам, которым необходима эта функциональность, скопировать код слоя совместимости в свои собственные исходные файлы и использовать его, чтобы они могли продолжать поддерживать как NumPy 1.x, так и 2.x без проблем. Также обратите внимание, что заголовок complex.h включён в numpy/npy_common.h, что делает complex зарезервированным ключевым словом.
Связывание со встроенной математической библиотекой в расширении
Чтобы использовать встроенную математическую библиотеку, которую NumPy поставляет в виде статической библиотеки, в собственном расширении Python, необходимо добавить опции компиляции и компоновки npymath к своему расширению. Точные действия зависят от используемой вами системы сборки. Общие шаги:
- Добавьте каталог включения numpy (= значение
np.get_include()) в свои каталоги заголовков, - Статическая библиотека
npymathнаходится в каталогеlibрядом с каталогом заголовков numpy (т. е.,pathlib.Path(np.get_include()) / '..' / 'lib'). Добавьте его в свои каталоги поиска библиотек, - Свяжите с
libnpymathиlibm.
Примечание
Помните, что при кросс-компиляции необходимо использовать numpy для платформы, для которой вы создаёте, а не для родной платформы машины сборки. В противном случае вы получите статическую библиотеку, скомпилированную для неправильной архитектуры.
При сборке с numpy.distutils (устарело), используйте это в setup.py.
>>> from numpy.distutils.misc_util import get_info
>>> info = get_info('npymath')
>>> _ = config.add_extension('foo', sources=['foo.c'], extra_info=info)
Другими словами, использование info такое же, как при использовании blas_info и т. д.
При сборке с помощью Meson используйте:
# Note that this will get easier in the future, when Meson has
# support for numpy built in; most of this can then be replaced
# by `dependency('numpy')`.
incdir_numpy = run_command(py3,
[
'-c',
'import os; os.chdir(".."); import numpy; print(numpy.get_include())'
],
check: true
).stdout().strip()
inc_np = include_directories(incdir_numpy)
cc = meson.get_compiler('c')
npymath_path = incdir_numpy / '..' / 'lib'
npymath_lib = cc.find_library('npymath', dirs: npymath_path)
py3.extension_module('module_name',
...
include_directories: inc_np,
dependencies: [npymath_lib],
Функции с половинной точностью
Заголовочный файл <numpy/halffloat.h> предоставляет функции для работы со значениями с плавающей точкой IEEE 754-2008 16-бит. Хотя этот формат обычно не используется для численных вычислений, он полезен для хранения значений, которые требуют плавающей точки, но не нуждаются в высокой точности. Его также можно использовать в качестве образовательного инструмента для понимания природы ошибки округления с плавающей точкой.
Как и для других типов, NumPy включает typedef npy_half для 16-битного float. В отличие от большинства других типов, вы не можете использовать это как обычный тип в C, так как это typedef для npy_uint16. Например, 1.0 выглядит как 0x3c00 для C, и если вы выполните сравнение равенства между различными знаковыми нулями, вы получите -0.0 != 0.0 (0x8000 != 0x0000), что неверно.
По этим причинам NumPy предоставляет API для работы со значениями npy_half, доступный путем включения <numpy/halffloat.h> и связывания с npymath. Для функций, которые не предоставляются напрямую, таких как арифметические операции, предпочтительным методом является преобразование в float или double и обратно, как в следующем примере.
npy_half sum(int n, npy_half *array) {
float ret = 0;
while(n--) {
ret += npy_half_to_float(*array++);
}
return npy_float_to_half(ret);
}
Внешние ссылки:
- 754-2008 IEEE Standard for Floating-Point Arithmetic
- Half-precision Float Wikipedia Article.
- OpenGL Half Float Pixel Support
- The OpenEXR image format.
- NPY_HALF_ZERO
-
Этот макрос определен как положительный ноль.
- NPY_HALF_PZERO
-
Этот макрос определен как положительный ноль.
- NPY_HALF_NZERO
-
Этот макрос определен как отрицательный ноль.
- NPY_HALF_ONE
-
Этот макрос определен как 1.0.
- NPY_HALF_NEGONE
-
Этот макрос определен как -1.0.
- NPY_HALF_PINF
-
Этот макрос определен как +inf.
- NPY_HALF_NINF
-
Этот макрос определен как -inf.
- NPY_HALF_NAN
-
Этот макрос определен как значение NaN, гарантированно имеющее сброшенный бит знака.
- floatnpy_half_to_float(npy_halfh)
-
Преобразует число с плавающей точкой половинной точности в число с плавающей точкой одинарной точности.
- doublenpy_half_to_double(npy_halfh)
-
Преобразует число с плавающей точкой половинной точности в число с плавающей точкой двойной точности.
- npy_halfnpy_float_to_half(floatf)
-
Преобразует число с плавающей точкой одинарной точности в число с плавающей точкой половинной точности. Значение округляется до ближайшего представимого значения половинной точности, а при равенстве расстояний — до ближайшего чётного. Если значение слишком мало или слишком велико, будет установлен бит переполнения или потери точности с плавающей точкой системы.
- npy_halfnpy_double_to_half(doubled)
-
Преобразует число с плавающей точкой двойной точности в число с плавающей точкой половинной точности. Значение округляется до ближайшего представимого значения половинной точности, а при равенстве расстояний — до ближайшего чётного. Если значение слишком мало или слишком велико, будет установлен бит переполнения или потери точности с плавающей точкой системы.
- intnpy_half_eq(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 == h2).
- intnpy_half_ne(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 != h2).
- intnpy_half_le(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 <= h2).
- intnpy_half_lt(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 < h2).
- intnpy_half_ge(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 >= h2).
- intnpy_half_gt(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности (h1 > h2).
- intnpy_half_eq_nonan(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности, которые, как известно, не являются NaN (h1 == h2). Если значение является NaN, результат не определен.
- intnpy_half_lt_nonan(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности, которые, как известно, не являются NaN (h1 < h2). Если значение является NaN, результат не определен.
- intnpy_half_le_nonan(npy_halfh1, npy_halfh2)
-
Сравнивает два числа с плавающей точкой половинной точности, которые, как известно, не являются NaN (h1 <= h2). Если значение является NaN, результат не определен.
- intnpy_half_iszero(npy_halfh)
-
Проверяет, равен ли полуточечный float нулю. Это может быть немного быстрее, чем вызов npy_half_eq(h, NPY_ZERO).
- intnpy_half_isnan(npy_halfh)
-
Проверяет, является ли полуточечный float NaN.
- intnpy_half_isinf(npy_halfh)
-
Проверяет, является ли полуточечный float плюс или минус Inf.
- intnpy_half_isfinite(npy_halfh)
-
Проверяет, является ли полуточечный float конечным (не NaN или Inf).
- intnpy_half_signbit(npy_halfh)
-
Возвращает 1, если h отрицательный, в противном случае 0.
- npy_halfnpy_half_copysign(npy_halfx, npy_halfy)
-
Возвращает значение x со знаком, скопированным от y. Работает для любого значения, включая Inf и NaN.
- npy_halfnpy_half_spacing(npy_halfh)
-
Это то же самое для полуточечного float, что и npy_spacing и npy_spacingf, описанные в разделе о низкоуровневых числах с плавающей точкой.
- npy_halfnpy_half_nextafter(npy_halfx, npy_halfy)
-
Это то же самое для полуточечного float, что и npy_nextafter и npy_nextafterf, описанные в разделе о низкоуровневых числах с плавающей точкой.
- npy_uint16npy_floatbits_to_halfbits(npy_uint32f)
-
Функция низкого уровня, которая преобразует 32-битное число с плавающей точкой одинарной точности, хранящееся как uint32, в 16-битное число с плавающей точкой полуточной точности.
- npy_uint16npy_doublebits_to_halfbits(npy_uint64d)
-
Функция низкого уровня, которая преобразует 64-битное число с плавающей точкой двойной точности, хранящееся как uint64, в 16-битное число с плавающей точкой полуточной точности.
- npy_uint32npy_halfbits_to_floatbits(npy_uint16h)
-
Функция низкого уровня, которая преобразует 16-битное число с плавающей точкой полуточной точности в 32-битное число с плавающей точкой одинарной точности, хранящееся как uint32.
- npy_uint64npy_halfbits_to_doublebits(npy_uint16h)
-
Функция низкого уровня, которая преобразует 16-битное число с плавающей точкой полуточной точности в 64-битное число с плавающей точкой двойной точности, хранящееся как uint64.
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/reference/c-api/coremath.html