Type-generic math
Type-generic math
头文件<tgmath.h>包含头文件<math.h>和<complex.h>,并定义了几个类型泛型宏,它们根据参数的类型确定哪些实际的或适用的复杂函数。
对于每个宏,参数的相应的实数类型在未被混合的math.h函数中是double的,被称为泛型参数(例如pow的两个参数都是泛型参数,但只有scalbn的第一个参数是泛型参数)。
当使用<tgmath.h>宏时,传递给泛型参数的参数类型决定了如下所述由宏选择哪个函数。 如果参数的类型与所选函数的参数类型不兼容,则行为是未定义的(例如,如果将一个复杂参数传递给实数tgmath宏:float complex fc; ceil(fc)或double complex dc ; double d; fmax(dc,d)是未定义行为的示例)。
注意:类型通用宏在C99中以实现定义的方式实现,但C11关键字_Generic使得可以以便携方式实现这些宏。
复杂/实型通用宏
对于既有真实对象又有复杂对象的所有函数,都存在一个类型通用宏XXX,它调用以下任一项:
- 实际功能:
上述规则的一个例外是晶圆厂宏(参见下表)。
要调用的函数如下确定:
- 如果通用参数的任何参数都是虚构的,则在每个函数参考页面上分别指定行为(特别是,sin,cos,tag,cosh,sinh,tanh,asin,atan,asinh和atanh称为
实
函数, sin,tan,sinh,tanh,asin,atan,asinh和atanh的返回类型是虚构的,cos和cosh的返回类型是实
数)
类型通用宏如下所示:
Type-generic macro | Real function variants | Complex function variants |
---|---|---|
| float | double |
fabs | fabsf | fabs |
exp | expf | exp |
log | logf | log |
pow | powf | pow |
sqrt | sqrtf | sqrt |
sin | sinf | sin |
cos | cosf | cos |
tan | tanf | tan |
asin | asinf | asin |
acos | acosf | acos |
atan | atanf | atan |
sinh | sinhf | sinh |
cosh | coshf | cosh |
tanh | tanhf | tanh |
asinh | asinhf | asinh |
acosh | acoshf | acosh |
atanh | atanhf | atanh |
真正的唯一功能
对于没有复杂对象的所有函数,除了modf之外,还有一个类型通用宏XXX存在,它调用实函数的变体之一:
float
变型XXXf
要调用的函数如下确定:
- 如果通用参数的任何参数是long double,则调用long double变体。 否则,如果泛型参数的任何参数是双精度型,则调用双精度型。 否则,调用float变量。
Type-generic macro | Real function variants |
---|---|
| float |
atan2 | atan2f |
cbrt | cbrtf |
ceil | ceilf |
copysign | copysignf |
erf | erff |
erfc | erfcf |
exp2 | exp2f |
expm1 | expm1f |
fdim | fdimf |
floor | floorf |
fma | fmaf |
fmax | fmaxf |
fmin | fminf |
fmod | fmodf |
frexp | frexpf |
hypot | hypotf |
ilogb | ilogbf |
ldexp | ldexpf |
lgamma | lgammaf |
llrint | llrintf |
llround | llroundf |
log10 | log10f |
log1p | log1pf |
log2 | log2f |
logb | logbf |
lrint | lrintf |
lround | lroundf |
nearbyint | nearbyintf |
nextafter | nextafterf |
nexttoward | nexttowardf |
remainder | remainderf |
remquo | remquof |
rint | rintf |
round | roundf |
scalbln | scalblnf |
scalbn | scalbnf |
tgamma | tgammaf |
trunc | truncf |
复杂功能
对于所有没有实际对应项的复数函数,都存在一个类型通用宏cXXX,它调用复杂函数的任何一种变体:
float
complex
变型cXXXf
要调用的函数如下确定:
- 如果通用参数的任何参数是实数,复数或虚数,则调用相应的复数函数。
Type-generic macro | Complex function variants |
---|---|
| float |
carg | cargf |
conj | conjf |
creal | crealf |
cimag | cimagf |
cproj | cprojf |
例
#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
参考
- C11标准(ISO / IEC 9899:2011):