Remembering to write sqrtf for float, sqrt for double, and sqrtl for long double is tedious and error-prone — forget the suffix and you silently get the wrong precision. tgmath.h (C99) provides type-generic wrappers that dispatch to the right variant based on the argument type, so you can just write sqrt and get the correct function.
#include <tgmath.h> float f = 2.0f; double d = 2.0; long double ld = 2.0L; sqrt(f) // calls sqrtf sqrt(d) // calls sqrt (double) sqrt(ld) // calls sqrtl
The dispatch happens at compile time via _Generic (C11) or compiler-specific mechanisms. All math functions from <math.h> that have f and l variants are covered, plus complex versions:
double complex z = 1.0 + 1.0 * I; sqrt(z) // dispatches to csqrt sin(z) // dispatches to csin
<tgmath.h> includes both <math.h> and <complex.h>, so all three headers' declarations become available when you include it.
The tradeoff is reduced explicitness. If you accidentally mix types in an expression, the dispatch may silently select a lower-precision variant. Precision-sensitive code — embedded DSP, signal processing, anything where you care about the exact FP operations — often prefers the explicit suffixes to make the precision choice visible in the source.
// compile: gcc -o tgtest tgtest.c -lm // run: ./tgtest // description: show that tgmath dispatches to different functions by type #include <tgmath.h> #include <stdio.h> int main(void) { float f = 2.0f; double d = 2.0; long double ld = 2.0L; printf("sqrt(float) = %.10f\n", (double)sqrt(f)); printf("sqrt(double) = %.10f\n", sqrt(d)); printf("sqrt(long double) = %.10Lf\n", sqrt(ld)); return 0; }
All three produce approximately 1.4142135624, but the internal computation uses float, double, and long double precision respectively. To confirm the dispatch, compile with -S and check the assembly — you will see calls to sqrtf, sqrt, and sqrtl in the generated code.