Standard C++ functions to convert a float or double to int, or to take the integer floor of a float or double, have always been very slow.
I've seen various alternatives in the past, but I'm wondering: what is generally considered the best (as in fastest) solution these days?
This one (using standard functions) obviously sucks: inline int MyFloor( double x )
{
return static_cast<int> (floor(x));
}
When limiting to x86, I guess some inline asm FISTP approach might be faster, although I guess that depends on the current rounding mode (and changing + restoring that kinda defeats the purpose).
I've also seen several methods using 'magic numbers': interpreting the binary float representation as integer (i.e. no conversion takes place), adding some magic value, and you have a valid integer. Probably limited precision, but it seemed to do the job.
What should I use? (besides optimizing my entire algorithm in the first place, and only consider this kind of optimizations at the end - I know)
Unless I was doing lots of these inside a really tight deeply nested loop (in which case I'd be asking serious questions about my design), and unless I knew it was a measurable bottleneck, I'd generally just trust the compiler to do the right thing here.
Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.
Just assign the double to an int? The floating point value is instantly truncated without casts or conversions.
inline int MyFloor(double d) {
int f = d;
return f;
}
If your compiler isn't giving you a warning about that, then you're using your compiler wrong. Casting definitely should be used.
Although I will ask (in partial agreement with forb's comment about truncation, though there should be a cast), is there a reason for flooring before casting?
Casting a floating point value to an integer rounds towards zero, but the floor-function rounds towards negative infinity. Thus, simply casting the value to an integer does not round the value in the same way as the OP requested.
Casting a floating point value to an integer rounds towards zero, but the floor-function rounds towards negative infinity. Thus, simply casting the value to an integer does not round the value in the same way as the OP requested.
Smart arse answer here -- but the fastest way is probably to keep the result in floating-point and avoid mixing integer and float math together, especially on PPC CPUs
I agree with Hodgman. The biggest problem here is the LHS caused by moving the value from the FPU to integer registers. For the biggest bang for your buck, leave the value in floating-point or move the math to use SIMD or some other registers that can store both floats and ints (if your hardware supports it).