Skip to main content
GameDev.net gamedev.net
🔒 Locked

fastest way to do (int) floor(double) nowadays ?

Started by Malc0lm Feb 28, 2012 at 3:47 PM 9 replies 15.7k views
Original Post
Malc0lm
Malc0lm
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)
VladimirBondarev
VladimirBondarev
there is a fast cast with SIMD (float to int) with 2 instructions, there should be also a double floor to int.
21st Century Moose
21st Century Moose
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. 
forb
forb
Just assign the double to an int? The floating point value is instantly truncated without casts or (formal) conversions.


inline int MyFloor(double d) {
int f = d;
return f;
}
Cornstalks
Cornstalks

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?
Brother Bob
Brother Bob
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.
Cornstalks
Cornstalks

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.

Ah, I see. Subtle difference. Thanks.
Hodgman
Hodgman
Smart arse answer here tongue.png -- 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 wink.png
gekko
gekko
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).
-- gekko
japro
japro

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.


Smart arse answer here tongue.png -- 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 wink.png


So how do you guys then do anything that involves array/grid indices that depend on floating point values... i'm unaware of any way to index arrays with floats tongue.png. Perlin noise also requires this.

I usually also just call floor. Nothing else i tried so far was actually faster (I did measure this). One exception is Java but that is more because it tends to not inline Math functions so just removing the call will give performance gains there, not so much the actual method of conversion.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.