类型通用数学
来自 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 中以实现定义的方式实现,但 C11 关键字 _Generic 使得能够以可移植的方式实现这些宏。
内容 |
[编辑] 复数/实数类型通用宏
对于所有具有实数和复数对应函数的函数,都存在一个类型通用宏 XXX
,它调用以下函数之一:
- 实数函数
- float 变体
XXXf
- double 变体
XXX
- long double 变体
XXXl
- float 变体
- 复数函数
- float 变体
cXXXf
- double 变体
cXXX
- long double 变体
cXXXl
- float 变体
上述规则的例外是 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 变体。
[编辑] 仅复数函数
对于所有没有实数对应函数的复数函数,都存在一个类型通用宏 cXXX
,它调用以下复数函数之一:
要调用的函数确定如下:
- 如果通用参数的任何参数是实数、复数或虚数,则调用相应的复数函数。
类型通用宏 | 复数函数 变体 | ||
---|---|---|---|
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)); // 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
[编辑] 参考文献
- C17 标准 (ISO/IEC 9899:2018)
- 7.25 类型通用数学 <tgmath.h> (p: 272-273)
- C11 标准 (ISO/IEC 9899:2011)
- 7.25 类型通用数学 <tgmath.h> (p: 373-375)
- C99 标准 (ISO/IEC 9899:1999)
- 7.22 类型泛型数学 <tgmath.h> (p: 335-337)