Namespaces
Variants
Actions

Type-generic math (since C99)

From cppreference.com
< c‎ | numeric

The header <tgmath.h> includes the headers <math.h> and <complex.h> and defines several type-generic macros that determine which real or, when applicable, complex function to call based on the types of the arguments.

For each macro, the parameters whose corresponding real type in the unsuffixed <math.h> function is double are known as generic parameters (for example, both parameters of pow are generic parameters, but only the first parameter of scalbn is a generic parameter).

When a <tgmath.h>'s 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.h>'s 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.

Contents

[edit] Complex/real type-generic macros

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

  • real function:
  • float variant XXXf
  • double variant XXX
  • long double variant XXXl
  • complex function:
  • float variant cXXXf
  • double variant cXXX
  • long double variant cXXXl

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

The function to call is determined as follows:

  • 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:

Type-generic
macro
Real function
variants
Complex function
variants
 floatdoublelong doublefloatdoublelong double
fabsfabsffabsfabslcabsfcabscabsl
expexpfexpexplcexpfcexpcexpl
loglogflogloglclogfclogclogl
powpowfpowpowlcpowfcpowcpowl
sqrtsqrtfsqrtsqrtlcsqrtfcsqrtcsqrtl
sinsinfsinsinlcsinfcsincsinl
coscosfcoscoslccosfccosccosl
tantanftantanlctanfctanctanl
asinasinfasinasinlcasinfcasincasinl
acosacosfacosacoslcacosfcacoscacosl
atanatanfatanatanlcatanfcatancatanl
sinhsinhfsinhsinhlcsinhfcsinhcsinhl
coshcoshfcoshcoshlccoshfccoshccoshl
tanhtanhftanhtanhlctanhfctanhctanhl
asinhasinhfasinhasinhlcasinhfcasinhcasinhl
acoshacoshfacoshacoshlcacoshfcacoshcacoshl
atanhatanhfatanhatanhlcatanhfcatanhcatanhl

[edit] Real-only functions

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 variant XXXf
  • double variant XXX
  • long double variant XXXl

The function to call is determined as follows:

  • 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.
Type-generic
macro
Real function
variants
 floatdoublelong double
atan2atan2fatan2atan2l
cbrtcbrtfcbrtcbrtl
ceilceilfceilceill
copysigncopysignfcopysigncopysignl
erferfferferfl
erfcerfcferfcerfcl
exp2exp2fexp2exp2l
expm1expm1fexpm1expm1l
fdimfdimffdimfdiml
floorfloorffloorfloorl
fmafmaffmafmal
fmaxfmaxffmaxfmaxl
fminfminffminfminl
fmodfmodffmodfmodl
frexpfrexpffrexpfrexpl
hypothypotfhypothypotl
ilogbilogbfilogbilogbl
ldexpldexpfldexpldexpl
lgammalgammaflgammalgammal
llrintllrintfllrintllrintl
llroundllroundfllroundllroundl
log10log10flog10log10l
log1plog1pflog1plog1pl
log2log2flog2log2l
logblogbflogblogbl
lrintlrintflrintlrintl
lroundlroundflroundlroundl
nearbyintnearbyintfnearbyintnearbyintl
nextafternextafterfnextafternextafterl
nexttowardnexttowardfnexttowardnexttowardl
remainderremainderfremainderremainderl
remquoremquofremquoremquol
rintrintfrintrintl
roundroundfroundroundl
scalblnscalblnfscalblnscalblnl
scalbnscalbnfscalbnscalbnl
tgammatgammaftgammatgammal
trunctruncftrunctruncl

[edit] Complex-only functions

For all complex number functions that do not have real counterparts, a type-generic macro cXXX exists, which calls either of the variants of a complex function:

The function to call is determined as follows:

  • If any of the arguments for the generic parameters is real, complex, or imaginary, then the appropriate complex function is called.
Type-generic
macro
Complex function
variants
 floatdoublelong double
cargcargfcargcargl
conjconjfconjconjl
crealcrealfcrealcreall
cimagcimagfcimagcimagl
cprojcprojfcprojcprojl

[edit] Example

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

Output:

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

[edit] References

  • C23 standard (ISO/IEC 9899:2024):
  • 7.25 Type-generic math <tgmath.h> (p: TBD)
  • C17 standard (ISO/IEC 9899:2018):
  • 7.25 Type-generic math <tgmath.h> (p: 272-273)
  • C11 standard (ISO/IEC 9899:2011):
  • 7.25 Type-generic math <tgmath.h> (p: 373-375)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.22 Type-generic math <tgmath.h> (p: 335-337)