Универсальная математика
Заголовочный файл <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вариантXXXfdoubleвариантXXXlong doubleвариантXXXl
- комплексную функцию:
floatвариантcXXXfdoubleвариантcXXXlong 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вариантXXXfdoubleвариантXXXlong doubleвариантXXXl
Вызов функции определяется, как указано ниже:
- Если любой аргумент универсальных параметров
long double, то вызываетсяlong doubleвариант. Иначе, если любой аргумент универсальных параметровdouble, то вызываетсяdoubleвариант. Иначе вызываетсяfloatвариант.
Функции только комплексного аргумента
Для всех комплексных функций, не имеющих вещественных аналогов, существует универсальный макрос cXXX, который вызывает следующие варианты комплексных функций:
float complexвариантcXXXfdouble complexвариантcXXXlong 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)