Jump to content
  • Advertisement
Sign in to follow this  
ChrisPepper1989

if statements V.S. % for wrapping values

This topic is 2946 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi Guys,

I was just wondering is there any efficiency / other reasons to use one or the other in the following two examples:

Example A:


angle= (angle+ diff) % 360;
angle= angle< 0 ? angle= 360+angle: angle;





Example B:


float angleTemp = angle+diff;
if(angleTemp >= 360)
{
angleTemp -= 360;
}
if(angleTemp < 0)
{
angleTemp += 360;
}

angle = angleTemp;





The modulator approach only just occurred to me and I was wondering whether it would be more or less efficient. Especially as some people would consider Example A less readable. My initial thought is that the difference would be more or less negligible but I thought i'd pose the question and find out.

-Thanks Chris

Share this post


Link to post
Share on other sites
Advertisement
How about

angle= (angle+ diff+360) % 360;



Avoiding conditional statements could be faster, but never try to estimate the behavour of a CPU compiler, they are really good nowadways :-)

Share this post


Link to post
Share on other sites
If you're after efficiency the best option is to use a new unit of angular measure, where a full circle is a power of two. For example 512 units in a circle. You can then simply do this:

angle = (angle + diff) & 511;

Edit: You can simplify even further if you use 2^32 as a full circle (assuming you store angles in 32-bit unsigned integers). If you do that the code becomes:

angle += diff;

Share this post


Link to post
Share on other sites
If this is not only for efficiency, how about

while (angle < 0) angle += 360;
while (angle >= 360) angle -= 360;


which also works in case some angular speed exceeds 360 by some factor.

Share this post


Link to post
Share on other sites
I don't see how example A is any less readable, since it's usually pretty clear what you're trying to do with a modulus operator (especially in the context of angles and '360'). Plus it doesn't matter how large angle/diff are, you only need a single conditional to normalize the result. Using loops would work for example B (instead of 'if' statements which don't properly normalize all angle values), but then you linearize the amount of time it takes to normalize the angle and in the worst case you're counting down from INT_MAX/FLT_MAX/etc. in 360 increments.

Share this post


Link to post
Share on other sites
An if that may or may not execute a simple statement is often converted into a cmov instruction, which doesn't involve a branch. That's probably the fastest thing to do. But, as always, only worry about this after a profiler tells you it's a bottleneck. Then check your compiler's output (in assembly code) and test what is faster in your particular usage.

Also, since you seem to be using floating-point numbers, % won't work: You should use fmod instead. Unfortunately the same brain-dead logic that lead to defining integer division as rounding towards zero made its way to the behavior of fmod, so you may have to do something about the negatives. Or you could roll your own:
double sane_fmod(double x, double y) {
return x - y * std::floor(x / y);
}

//...
angle = sane_fmod(angle, 2*Pi); // You should be using radians anyway


Share this post


Link to post
Share on other sites
Thanks guys, thats really interesting!

Im not 100% sure how Adam_42s solution works, cause bit manipulation isnt a strong point. but the concept makes sense! so thanks for that I will have to play with that!

I also really liked Ashaman73 solution, its definitely an improvement on example A!

And phresnel, that is a very good point and a good improvement on example b I will definitely keep that in mind! As well as Zipsters comment on the potential problems which is another good point! I think Ashaman73s example is my favourite and I think I might stick to that for all future wrapping!

Thanks for all your comments its always good to see different ways of doing things and why! I appreciate all your input! Thanks, Chris

Share this post


Link to post
Share on other sites
Oh, one more thing: You can almost always avoid using angles, if you use unit vectors instead. Your code is usually faster, shorter and easier to understand if you ditch angles altogether.

Share this post


Link to post
Share on other sites
Oops.

angle = angle >= 0
? angle % 360
: 360 - (-angle % 360);




Constant time for negative and constant time for positive numbers, and works for arbitrary large angles in the integer case.

Share this post


Link to post
Share on other sites
IF statements are faster than modulo/division by at least an order of magnitude on most modern machines. Of course it won't make any difference unless the code is a hot spot, but modulo/division is slower than virtually any other operation.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!