Namensräume
Varianten
Aktionen

Typ-generische Mathematik (seit C99)

Von cppreference.com
< c‎ | numerisch

Die Headerdatei <tgmath.h> inkludiert die Headerdateien <math.h> und <complex.h> und definiert mehrere typ-generische Makros, die basierend auf den Typen der Argumente entscheiden, welche reelle oder, falls zutreffend, komplexe Funktion aufgerufen wird.

Für jedes Makro werden die Parameter, deren entsprechender reeller Typ in der unsuffixierten <math.h>-Funktion double ist, als generische Parameter bezeichnet (zum Beispiel sind beide Parameter von pow generische Parameter, aber nur der erste Parameter von scalbn ist ein generischer Parameter).

Wenn ein Makro aus <tgmath.h> verwendet wird, bestimmen die an die generischen Parameter übergebenen Argumenttypen, welche Funktion vom Makro ausgewählt wird, wie unten beschrieben. Wenn die Typen der Argumente nicht kompatibel mit den Parametertypen der ausgewählten Funktion sind, ist das Verhalten undefiniert (z.B. wenn ein komplexes Argument in ein nur reelles Makro von <tgmath.h> übergeben wird: float complex fc; ceil(fc); oder double complex dc; double d; fmax(dc, d); sind Beispiele für undefiniertes Verhalten).

Hinweis: Typ-generische Makros wurden in C99 implementierungsabhängig implementiert, aber das C11-Schlüsselwort _Generic ermöglicht die portable Implementierung dieser Makros.

Inhalt

[bearbeiten] Komplexe/reelle typ-generische Makros

Für alle Funktionen, die sowohl reelle als auch komplexe Gegenstücke haben, existiert ein typ-generisches Makro XXX, das eine der folgenden aufruft:

  • reelle Funktion
  • float-Variante XXXf
  • double-Variante XXX
  • long double-Variante XXXl
  • komplexe Funktion
  • float-Variante cXXXf
  • double-Variante cXXX
  • long double-Variante cXXXl

Eine Ausnahme von der obigen Regel ist das Makro fabs (siehe Tabelle unten).

Die aufzurufende Funktion wird wie folgt bestimmt:

  • Wenn eines der Argumente für die generischen Parameter imaginär ist, wird das Verhalten auf jeder Funktionsreferenzseite individuell spezifiziert (insbesondere rufen sin, cos, tag, cosh, sinh, tanh, asin, atan, asinh und atanh *reelle* Funktionen auf, die Rückgabetypen von sin, tan, sinh, tanh, asin, atan, asinh und atanh sind imaginär, und die Rückgabetypen von cos und cosh sind reell).
  • Wenn eines der Argumente für die generischen Parameter komplex ist, wird die komplexe Funktion aufgerufen, andernfalls wird die reelle Funktion aufgerufen.
  • Wenn eines der Argumente für die generischen Parameter long double ist, wird die long double-Variante aufgerufen. Andernfalls, wenn eines der Parameter double oder Integer ist, wird die double-Variante aufgerufen. Andernfalls wird die float-Variante aufgerufen.

Die typ-generischen Makros sind wie folgt:

Typ-generisch
Makro
Reelle Funktion
Varianten
Komplexe Funktion
Varianten
  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

[bearbeiten] Nur reelle Funktionen

Für alle Funktionen, die keine komplexen Gegenstücke haben, mit Ausnahme von modf, existiert ein typ-generisches Makro XXX, das eine der Varianten einer reellen Funktion aufruft.

  • float-Variante XXXf
  • double-Variante XXX
  • long double-Variante XXXl

Die aufzurufende Funktion wird wie folgt bestimmt:

  • Wenn eines der Argumente für die generischen Parameter long double ist, wird die long double-Variante aufgerufen. Andernfalls, wenn eines der Argumente für die generischen Parameter double ist, wird die double-Variante aufgerufen. Andernfalls wird die float-Variante aufgerufen.
Typ-generisch
Makro
Reelle Funktion
Varianten
  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

[bearbeiten] Nur komplexe Funktionen

Für alle komplexen Zahlenfunktionen, die keine reellen Gegenstücke haben, existiert ein typ-generisches Makro cXXX, das eine der Varianten einer komplexen Funktion aufruft.

Die aufzurufende Funktion wird wie folgt bestimmt:

  • Wenn eines der Argumente für die generischen Parameter reell, komplex oder imaginär ist, wird die entsprechende komplexe Funktion aufgerufen.
Typ-generisch
Makro
Komplexe Funktion
Varianten
  float double long double
carg cargf carg cargl
conj conjf conj conjl
creal crealf creal creall
cimag cimagf cimag cimagl
cproj cprojf cproj cprojl

[bearbeiten] Beispiel

#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
}

Ausgabe

sqrt(2) = 1.414214
sin(0.5f) = 0.479426
sqrt(1 + 0.5i) = 1.029086+0.242934i

[bearbeiten] Referenzen

  • C23-Standard (ISO/IEC 9899:2024)
  • 7.25 Typ-generische Mathematik <tgmath.h> (S. TBD)
  • C17-Standard (ISO/IEC 9899:2018)
  • 7.25 Typ-generische Mathematik <tgmath.h> (S. 272-273)
  • C11-Standard (ISO/IEC 9899:2011)
  • 7.25 Typ-generische Mathematik <tgmath.h> (S. 373-375)
  • C99-Standard (ISO/IEC 9899:1999)
  • 7.22 Typ-generische Mathematik <tgmath.h> (S. 335-337)