C
数值 | Numerics

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 macroReal function variantsComplex function variants
floatdouble
fabsfabsffabs
expexpfexp
loglogflog
powpowfpow
sqrtsqrtfsqrt
sinsinfsin
coscosfcos
tantanftan
asinasinfasin
acosacosfacos
atanatanfatan
sinhsinhfsinh
coshcoshfcosh
tanhtanhftanh
asinhasinhfasinh
acoshacoshfacosh
atanhatanhfatanh

真正的唯一功能

对于没有复杂对象的所有函数,除了modf之外,还有一个类型通用宏XXX存在,它调用实函数的变体之一:

  • float 变型 XXXf

要调用的函数如下确定:

  • 如果通用参数的任何参数是long double,则调用long double变体。 否则,如果泛型参数的任何参数是双精度型,则调用双精度型。 否则,调用float变量。

Type-generic macroReal function variants
float
atan2atan2f
cbrtcbrtf
ceilceilf
copysigncopysignf
erferff
erfcerfcf
exp2exp2f
expm1expm1f
fdimfdimf
floorfloorf
fmafmaf
fmaxfmaxf
fminfminf
fmodfmodf
frexpfrexpf
hypothypotf
ilogbilogbf
ldexpldexpf
lgammalgammaf
llrintllrintf
llroundllroundf
log10log10f
log1plog1pf
log2log2f
logblogbf
lrintlrintf
lroundlroundf
nearbyintnearbyintf
nextafternextafterf
nexttowardnexttowardf
remainderremainderf
remquoremquof
rintrintf
roundroundf
scalblnscalblnf
scalbnscalbnf
tgammatgammaf
trunctruncf

复杂功能

对于所有没有实际对应项的复数函数,都存在一个类型通用宏cXXX,它调用复杂函数的任何一种变体:

  • float complex 变型 cXXXf

要调用的函数如下确定:

  • 如果通用参数的任何参数是实数,复数或虚数,则调用相应的复数函数。

Type-generic macroComplex function variants
float
cargcargf
conjconjf
crealcrealf
cimagcimagf
cprojcprojf

#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):