Математика с обобщением по типу (начиная с C99)
Заголовок <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 макросы с обобщением по типу реализовывались способом, определяемым реализацией, но ключевое слово C11 _Generic позволяет реализовать эти макросы переносимым способом.
Макросы с обобщением по типу для комплексных и вещественных чисел
Для всех функций, имеющих как вещественные, так и комплексные аналоги, существует макрос с обобщением по типу XXX, который вызывает одну из следующих функций:
- вещественная функция:
-
вариант float
XXXf -
вариант double
XXX -
вариант longdouble
XXXl - комплексная функция:
-
вариант float
cXXXf -
вариант double
cXXX -
вариант longdouble
cXXXl
Исключением из приведённого выше правила является макрос fabs (см. таблицу ниже).
Вызываемая функция определяется следующим образом:
- Если какой-либо аргумент обобщённого параметра является мнимым, поведение определяется отдельно на странице описания каждой функции (в частности,
sin,cos,tag,cosh,sinh,tanh,asin,atan,asinhиatanhвызывают вещественные функции, возвращаемые типыsin,tan,sinh,tanh,asin,atan,asinhиatanhявляются мнимыми, а возвращаемые типыcosиcosh— вещественными). - Если какой-либо аргумент обобщённого параметра является комплексным, вызывается комплексная функция, в противном случае — вещественная.
- Если какой-либо аргумент обобщённого параметра имеет тип longdouble, вызывается вариант longdouble. В противном случае, если какой-либо параметр имеет тип double или является целым числом, вызывается вариант double. Иначе вызывается вариант float.
Макросы с обобщением по типу представлены ниже:
| Макрос с обобщением по типу | Варианты вещественных функций | Варианты комплексных функций |
||||
|---|---|---|---|---|---|---|
| float | double | longdouble | float | double | longdouble | |
| 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 -
вариант longdouble
XXXl
Вызываемая функция определяется следующим образом:
- Если какой-либо аргумент обобщённого параметра имеет тип longdouble, вызывается вариант longdouble. В противном случае, если какой-либо аргумент обобщённого параметра имеет тип double, вызывается вариант double. Иначе вызывается вариант float.
Функции только для комплексных чисел
Для всех функций комплексных чисел, не имеющих вещественных аналогов, существует макрос с обобщением по типу cXXX, который вызывает один из вариантов комплексной функции:
-
вариант floatcomplex
cXXXf -
вариант doublecomplex
cXXX -
вариант longdoublecomplex
cXXXl
Вызываемая функция определяется следующим образом:
- Если какой-либо аргумент обобщённого параметра является вещественным, комплексным или мнимым, вызывается соответствующая комплексная функция.
| Макрос с обобщением по типу | Варианты комплексных функций |
||
|---|---|---|---|
| float | double | longdouble | |
| 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)); // argument type is int, calls sqrt
float f = 0.5;
printf("sin(0.5f) = %f\n", sin(f)); // argument type is float, calls sinf
float complex dc = 1 + 0.5*I;
float complex z = sqrt(dc); // argument type is float complex, calls csqrtf
printf("sqrt(1 + 0.5i) = %f+%fi\n",
creal(z), // argument type is float complex, calls crealf
cimag(z)); // argument type is float complex, calls cimagf
}
Вывод:
sqrt(2) = 1.414214 sin(0.5f) = 0.479426 sqrt(1 + 0.5i) = 1.029086+0.242934i
Ссылки
- Стандарт C23 (ISO/IEC 9899:2024):
- 7.25 Математика с обобщением по типу <tgmath.h> (стр.: уточняется)
- Стандарт 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)
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/c/numeric/tgmath