close
Пространства имён
Варианты
Действия

Универсальная математика

Материал из cppreference.com

Заголовочный файл <tgmath.h> включает заголовочные файлы <math.h> и <complex.h> и задаёт несколько универсальных макросов, которые определяют, какую функцию, вещественную или, если возможно, комплексную, следует вызывать в зависимости от типов аргументов.

В каждом макросе параметры, чей соответствующий вещественный тип в бессуффиксной функции из math.h является double, известны как универсальные параметры (например, оба параметра pow универсальные, но только первый параметр scalbn универсальный).

При использовании макроса из <tgmath.h> типы аргументов, передаваемых в универсальные параметры, определяют, какая функция выбирается, как описано ниже. Если типы аргументов не совместимы с типами параметров выбранной функции, то поведение не определено (напр., если комплексный аргумент передаётся в только вещественный макрос из <tgmath.h>: float complex fc; ceil(fc); или double complex dc; double d; fmax(dc, d); — примеры неопределённого поведения).

Замечание: универсальные макросы появились в C99 как определяемые реализацией, но ключевое слово _Generic в C11 позволяет сделать эти макросы переносимыми.

Комплексные/вещественные универсальные макросы

Для всех функций, имеющих как вещественные, так и комплексные аналоги, существует универсальный макрос XXX, который вызывает:

  • вещественную функцию:
  • float вариант XXXf
  • double вариант XXX
  • long double вариант XXXl
  • комплексную функцию:
  • float вариант cXXXf
  • double вариант cXXX
  • long double вариант cXXXl

Исключением из этого правила является макрос fabs (см. таблицу ниже).

Вызываемая функция определяется, как указано ниже:

  • Если любой из аргументов универсальных параметров мнимый, поведение определяется для каждой функции индивидуально (в частности, sin, cos, tag, cosh, sinh, tanh, asin, atan, asinh и atanh вызывают вещественные функции, тип значений, возвращаемых sin, tan, sinh, tanh, asin, atan, asinh и atanh, мнимый, и тип значений, возвращаемых cos и cosh, вещественный).
  • Если любой из аргументов универсальных параметров комплексный, то вызывается комплексная функция, иначе вещественная.
  • Если любой из аргументов универсальных параметров long double, то вызывается long double вариант. Иначе, если любой из параметров double или целый, то вызывается double вариант. Иначе вызывается float вариант.

Универсальные макросы указаны ниже:

Универсальный макрос Варианты вещественных
функций
Варианты комплексных
функций
 
float
double
long double
float
double
long double
fabs fabsf fabs fabsl cabsf cabs cabsl
exp expf exp expl cexpf cexp cexpl
log logf log logl clogf clog clogl
pow powf pow powl cpowf cpow cpowl
sqrt sqrtf sqrt sqrtl csqrtf csqrt csqrtl
sin sinf sin sinl csinf csin csinl
cos cosf cos cosl ccosf ccos ccosl
tan tanf tan tanl ctanf ctan ctanl
asin asinf asin asinl casinf casin casinl
acos acosf acos acosl cacosf cacos cacosl
atan atanf atan atanl catanf catan catanl
sinh sinhf sinh sinhl csinhf csinh csinhl
cosh coshf cosh coshl ccoshf ccosh ccoshl
tanh tanhf tanh tanhl ctanhf ctanh ctanhl
asinh asinhf asinh asinhl casinhf casinh casinhl
acosh acoshf acosh acoshl cacoshf cacosh cacoshl
atanh atanhf atanh atanhl catanhf catanh catanhl

Функции только вещественного аргумента

Для всех функций, которые не имеют комплексных аналогов, за исключением modf, существует универсальный макрос XXX, который вызывает следующие варианты вещественных функций:

  • float вариант XXXf
  • double вариант XXX
  • long double вариант XXXl

Вызов функции определяется, как указано ниже:

  • Если любой аргумент универсальных параметров long double, то вызывается long double вариант. Иначе, если любой аргумент универсальных параметров double, то вызывается double вариант. Иначе вызывается float вариант.
Универсальный макрос Варианты вещественных
функций
 
float
double
long double
atan2 atan2f atan2 atan2l
cbrt cbrtf cbrt cbrtl
ceil ceilf ceil ceill
copysign copysignf copysign copysignl
erf erff erf erfl
erfc erfcf erfc erfcl
exp2 exp2f exp2 exp2l
expm1 expm1f expm1 expm1l
fdim fdimf fdim fdiml
floor floorf floor floorl
fma fmaf fma fmal
fmax fmaxf fmax fmaxl
fmin fminf fmin fminl
fmod fmodf fmod fmodl
frexp frexpf frexp frexpl
hypot hypotf hypot hypotl
ilogb ilogbf ilogb ilogbl
ldexp ldexpf ldexp ldexpl
lgamma lgammaf lgamma lgammal
llrint llrintf llrint llrintl
llround llroundf llround llroundl
log10 log10f log10 log10l
log1p log1pf log1p log1pl
log2 log2f log2 log2l
logb logbf logb logbl
lrint lrintf lrint lrintl
lround lroundf lround lroundl
nearbyint nearbyintf nearbyint nearbyintl
nextafter nextafterf nextafter nextafterl
nexttoward nexttowardf nexttoward nexttowardl
remainder remainderf remainder remainderl
remquo remquof remquo remquol
rint rintf rint rintl
round roundf round roundl
scalbln scalblnf scalbln scalblnl
scalbn scalbnf scalbn scalbnl
tgamma tgammaf tgamma tgammal
trunc truncf trunc truncl

Функции только комплексного аргумента

Для всех комплексных функций, не имеющих вещественных аналогов, существует универсальный макрос cXXX, который вызывает следующие варианты комплексных функций:

  • float complex вариант cXXXf
  • double complex вариант cXXX
  • long double complex вариант cXXXl

Вызов функции определяется, как указано ниже:

  • Если любой аргумент универсальных параметров вещественный, комплексный или мнимый, то вызывается соответствующая комплексная функция.
Универсальный макрос Варианты комплексных
функций
 
float
double
long double
carg cargf carg cargl
conj conjf conj conjl
creal crealf creal creall
cimag cimagf cimag cimagl
cproj cprojf cproj cprojl

Пример

#include <stdio.h>
#include <tgmath.h>

int main(void)
{
    int i = 2;
    printf("sqrt(2) = %f\n", sqrt(i)); // тип аргумента int, вызывает sqrt

    float f = 0.5;
    printf("sin(0.5f) = %f\n", sin(f));   // тип аргумента float, вызывает sinf

    float complex dc = 1 + 0.5*I;
    float complex z = sqrt(dc);      // тип аргумента float complex, вызывает csqrtf
    printf("sqrt(1 + 0.5i) = %f+%fi\n",
           creal(z),  // тип аргумента float complex, вызывает crealf
           cimag(z)); // тип аргумента float complex, вызывает cimagf
}

Вывод:

sqrt(2) = 1.414214
sin(0.5f) = 0.479426
sqrt(1 + 0.5i) = 1.029086+0.242934i

Ссылки

  • Стандарт C17 (ISO/IEC 9899:2018):
  • 7.25 Универсальная математика <tgmath.h> (стр. 272-273)
  • Стандарт C11 (ISO/IEC 9899:2011):
  • 7.25 Универсальная математика <tgmath.h> (стр. 373-375)
  • Стандарт C99 (ISO/IEC 9899:1999):
  • 7.22 Универсальная математика <tgmath.h> (стр. 335-337)