<tgmath.h> is a header provided by the standard C library,
introduced in C99 to allow easier porting of Fortran numerical software to C.
Fortran, unlike C, provides “intrinsic functions”, which are a part of the language and behave more like
operators. While ordinary (”external”) functions behave similarly to C functions with respect to types
(the types of arguments and parameters must match and the restult type is fixed), intrinsic functions accept arguments of several types and their return type may depend on the type of their arguments.
For example Fortran 77 provides, among others, an INT function which accepts Integer, Real, Double or Complex arguments and always returns an Integer,
and a SIN function which accepts Real, Double or Complex
arguments and returns a value of the same type.
This helps the programmer somewhat because the function calls don’t have to be changed
if variable types change. On the other hand user-defined
functions can’t behave this way, so the additional flexibility is really limited to single subroutines that don’t
need to call user-defined functions.
Some C programmers would call the feature ugly from the above description already, for the same
reason integrating printf into the language would be ugly.
This functionality was incorporated in C99 together with other features for better support of numerical
computation and it is provided in the abovementioned <tgmath.h> header.
Provided are goniometric and logarithmic functions, functions for rounding and a few others.
The header defines macros that shadow the existing functions from <math.h>; e.g. the cos macro behaves like the cos function when its parameter has type
double, like cosf for float, cosl for long double, ccos for double _Complex, ccosf for float _Complex, ccosl for long double _Complex. Finally, when the parameter has any integer type, the
cos function is called, as if the parameter were implicitly converted to double.
The second reason why this feature is ugly is that it attempts to imitate functions, but the imitation is imperfect and even dangerous:
If you try to pass the generic macro cos as a function parameter, you actually always supply the cos function operating on doubles because the macro expansion doesn’t happen when cos is not followed
by a left parenthesis.
The final reason why this feature is ugly is that such macros can’t be implemented in strictly conforming C, they have to rely on some kind of compiler support – and experience (e.g. the speed with which bugs in the
glibc implementation are discovered) seems to suggest this features is used very rarely and doesn’t deserve
to be a part of the “core language”, especially because the underlying feature is not available.
(Contrast this to <stdarg.h>, which is available for portable use.)
Now, if the feature is both ugly and not used in practice, why mention it at all? I’m writing this article because I have examined the glibc implementation and it is such an ingenious hack that I feel it should
be recorded for posterity, in some better way than this commit message:
2000-08-01 Ulrich Drepper <drepper@redhat.com>
Joseph S. Myers <jsm28@cam.ac.uk>
* math/tgmath.h: Make standard compliant. Don't ask how.
(more…)