Typ-generische Mathematik (seit C99)
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
- float-Variante
- komplexe Funktion
- float-Variante
cXXXf - double-Variante
cXXX - long double-Variante
cXXXl
- float-Variante
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,asinhundatanh*reelle* Funktionen auf, die Rückgabetypen vonsin,tan,sinh,tanh,asin,atan,asinhundatanhsind imaginär, und die Rückgabetypen voncosundcoshsind 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.
[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)