

C99 defines three versions for most mathematical functions: one for float, one for double, and one for long double parameters. For example, C99 defines these functions for the sine operation:
double sin(double arg);
float sinf(float arg);
long double sinl(long double arg);
The operation of all three functions is the same, except for the data upon which they operate. In all cases, the double version is the original function defined by C89. The float and long double versions were added by C99. The float versions use the f suffix, and long double versions use the l suffix. (Different names are required because C does not support function overloading.) By providing three different functions, C99 enables you to call the one that most precisely fits the circumstances. As described earlier in this chapter, the complex math functions also provide three versions of each function, for the same reason.
As useful as the three versions of the math and complex functions are, they are not particularly convenient. First, you have to remember to specify the proper suffix for the data you are passing. This is both tedious and errorprone. Second, if you change the type of data being passed to one of these functions during project development, you will need to remember to change the suffix as well. Again, this is tedious and errorprone. To address these (and other) issues, C99 defines a set of typegeneric macros that can be used in place of the math or complex functions. These macros automatically translate into the proper function based upon the type of the argument. The typegeneric macros are defined in <tgmath.h>, which automatically includes <math.h> and <complex.h>.
The typegeneric macros use the same names as the double version of the math or complex functions to which they translate. (These are also the same names defined by C89 and C++.) Thus, the typegeneric macro for sin( ), sinf( ), and sinl( ) is sin( ). The typegeneric macro of csin( ), csinf( ), and csinl( ) is also sin( ). As explained, the proper function is called based upon the argument. For example, given
long double ldbl; float complex fcmplx;
Then,
cos(ldbl)
translates into
cosl(ldbl)
and
cos(fcmplx)
translates into
ccosf(fcmplx)
As these examples illustrate, the use of typegeneric macros offers the C programmer convenience without loss of performance, precision, or portability.
NOTE: If you are programming in C++, the typegeneric macros are not needed because C++ provides overloaded versions of the math and complex functions.

