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 error-prone. 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 error-prone. To address these (and other) issues, C99 defines a set of type-generic 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 type-generic macros are defined in <tgmath.h>, which automatically includes <math.h> and <complex.h>.
The type-generic 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 type-generic macro for sin( ), sinf( ), and sinl( ) is sin( ). The type-generic 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;
As these examples illustrate, the use of type-generic macros offers the C programmer convenience without loss of performance, precision, or portability.
NOTE: If you are programming in C++, the type-generic macros are not needed because C++ provides overloaded versions of the math and complex functions.