Type-generic math (Numerics) – C 中文开发手册

[
  •   C 语言中文开发手册

    Type-generic math (Numerics) - C 中文开发手册
    头文件<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,它调用以下任一项:实际功能: float 变型 XXXf double 变型 XXX long double 变型 XXXl 复杂功能: float 变型 cXXXf double 变型 cXXX long double 变型 cXXXl 上述规则的一个例外是晶圆厂宏(参见下表)。要调用的函数如下确定:如果通用参数的任何参数都是虚构的,则在每个函数参考页面上分别指定行为(特别是,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调用变体。类型通用宏如下所示:

    Type-generic macro Real function variants Complex function variants
    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变体。 否则,如果泛型参数的任何参数是双精度型,则调用双精度型。 否则,调用float变量。

    Type-generic macro Real function variants
    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 complex 变型 cXXXf double complex 变型 cXXX long double complex 变型 cXXXl 要调用的函数如下确定:如果通用参数的任何参数是实数,复数或虚数,则调用相应的复数函数。

    Type-generic macro Complex function variants
    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
    ", sqrt(i)); // argument type is int, calls sqrt
     
        float f = 0.5;
        printf("sin(0.5f) = %f
    ", 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
    ",
               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): 7.25类型通用数学<tgmath.h>(p:373-375) C99标准(ISO / IEC 9899:1999): 7.22类型通用数学<tgmath.h>(p:335-337)

  •   C 语言中文开发手册
    ]
    转载请保留页面地址:https://www.breakyizhan.com/c-3/28201.html
    原文地址:https://www.cnblogs.com/breakyizhan/p/13252739.html