المتغيرات
فضاءات التسمية
أفعال

Type-generic math

من cppreference.com
< c‏ | numeric

الملف ‎<tgmath.h>‎ يتضمن الملفات ‎<math.h>‎ و ‎<complex.h>‎ ويعرف العديد من الماكرو عامة النوع التي تستدعي الدالة المناسبة للمعطى على حسب نوعا سواء كان حقيقيا أم مركبا.

كل ماكرو يأخذ معطى أو أكثر عام النوع generic parameter. المعطى عام النوع هو الذي نوعه double بالنسبة للدول الحقيقية المجردة (أي بدون حرف يدل على نوع المعطى) المعرفة في math.h. فمثلا كلا معطيا pow‎ عام بينما فقط المعطى الأول من scalbn‎ معطى عام.


When a ‎<tgmath.h>‎ macro is used the types of the arguments passed to the generic parameters determine which function is selected by the macro as described below. If the types of the arguments are not compatible with the parameter types of the selected function, the behavior is undefined (e.g. if a complex argument is passed into a real-only tgmath macro: float complex fc; ceil(fc) or double complex dc; double d; fmax(dc, d) are examples of undefined behavior)

Note: type-generic macros were implemented in implementation-defined manner in C99, but C11 keyword _Generic makes it possible to implement these macros in portable manner.

محتويات

[تعديل] ماكرو عامة للمعطيات المركبة والحقيقية

For all functions that have both real and complex counterparts, a type-generic macro ‎XXX‎ exists, which calls either of:

  • real function:
  • float يؤدي إلى استدعاء ‎XXXf‎
  • double يؤدي إلى استدعاء ‎XXX‎
  • long double يؤدي إلى استدعاء ‎XXXl‎
  • complex function:
  • float يؤدي إلى استدعاء ‎cXXXf‎
  • double يؤدي إلى استدعاء ‎cXXX‎
  • long double يؤدي إلى استدعاء ‎cXXXl‎

An exception to the above rule is the ‎fabs‎ macro (see the table below).

تحديد الدالة المطلوبة يتم كالآتي:

  • If any of the arguments for the generic parameters is imaginary, the behavior is specified on each function reference page individually (in particular, sin, cos, tag, cosh, sinh, tanh, asin, atan, asinh, and atanh call real functions, the return types of sin, tan, sinh, tanh, asin, atan, asinh, and atanh are imaginary, and the return types of cos and cosh are real)
  • If any of the arguments for the generic parameters is complex, then the complex function is called, otherwise the real function is called.
  • If any of the arguments for the generic parameters is long double, then the long double variant is called. Otherwise, if any of the parameters is double or integer, then the double variant is called. Otherwise, float variant is called.

The type-generic macros are as follows:

ماكرو عام النوع الدوال الحقيقية
variants
الدوال المركبة
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

[تعديل] دوال حقيقية فقط

For all functions that do not have complex counterparts, with the exception of ‎modf‎, a type-generic macro ‎XXX‎ exists, which calls either of the variants of a real function:

  • float يؤدي إلى استدعاء ‎XXXf‎
  • double يؤدي إلى استدعاء ‎XXX‎
  • long double يؤدي إلى استدعاء ‎XXXl‎

تحديد الدالة المطلوبة يتم كالآتي:

  • If any of the arguments for the generic parameters is long double, then the long double variant is called. Otherwise, if any of the arguments for the generic parameters is double, then the double variant is called. Otherwise, float variant is called.
ماكرو عام النوع الدوال الحقيقية
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‎

تحديد الدالة المطلوبة يتم كالآتي:

ماكرو عام النوع الدوال المركبة
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\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