命名空间
变体
操作

类型通用数学

来自 cppreference.com
< c‎ | numeric

头文件 <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 变体 cXXXf
  • double 变体 cXXX
  • long double 变体 cXXXl

上述规则的例外是 fabs 宏(见下表)。

要调用的函数确定如下:

  • 如果通用参数的任何参数是虚数,则每个函数引用页面分别指定行为(特别是,sincostagcoshsinhtanhasinatanasinhatanh 调用 *实数* 函数,sintansinhtanhasinatanasinhatanh 的返回类型是虚数,coscosh 的返回类型是实数)。
  • 如果通用参数的任何参数是复数,则调用复数函数,否则调用实数函数。
  • 如果通用参数的任何参数是 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
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)