Historically (circa C89 and before), the math library contained only the double-precision versions of these functions, which is why those versions have no suffix. If you needed to compute the sine of a float
, you either wrote your own implementation, or (more likely!) you simply wrote:
float x;
float y = sin(x);
However, this introduces some overhead on modern architectures. Specifically, on the most common architectures today, it is necessary for the compiler to emit code that looks something like this:
convert x to double
call sin
convert result to float
These conversions are pretty fast (about the same as an addition, usually), but they still have some cost. On top of the cost of conversion, sin
needs to deliver a result that has ~53 bits of precision, more than half of which are completely wasted if the result is just going to be converted back to single precision. Between these two factors, it is possible for a dedicated single-precision sin
routine to be about twice as fast; that’s a significant win for some very frequently-used library functions!
If we look at functions like fabs
(and assume that the compiler does not simply inline and lower them), the situation is much, much worse. fabs
, on a typical modern architecture, is a simple bitwise-and operation. So the two conversions bracketing the call (if all you have is double
) are significantly more expensive than the operation itself, and can easily cause a 5x slowdown. That’s why multiple versions of these functions were added to support each FP type.
If you don’t want to keep track of all of them, you can #include <tgmath.h>
, which will infer the correct function to use based on the type of the argument (meaning
sin((float)x)
will generate a call to sinf(x)
, whereas
sin((long double)x)
will call sinl(x)
).
In your own code, you usually know a priori what the type of your arguments is, and only need to support one or maybe two types. clamp
and lerp
in particular are graphics operations, and almost universally are used only in single-precision variants.
Incidentally, the fact that you’re using clamp
and lerp
is a pretty good indication that you might want to look at writing your code in OpenCL instead of C/Obj-C; the OpenCL math library implements these operations (and many other similar operations) for you, and provides implementations that work with a wide range of basic types, including vectors.