Best way to rotate a sprite?

angle = (angle + 1) % 32;
angle = (angle + 31) % 32;

To generalize this trick a bit, (a + b) % c can be written as
(a + b + c) % c, to get positive results from a negative “b”, as long as
abs(b) < c (that is, as long as the +c is enough to push it back >= 0). If
that’s not the case, there’s “t = (a + b) % c” (gives a number between
-c and c, exclusive) and then “(t + c) % c”.On Wed, Jan 29, 2003 at 03:16:51AM +0200, Sami N??t?nen wrote:

This is good if the divisor is not an exact power of two. How ever if it
is the original example, which uses and is faster, so no reason to use
this.

(Oh. I had to read this for a moment to figure out what you meant.
Tip: it helps to capitalize boolean operations–“which uses AND”–for
readability.)

This is incorrect. The compiler will use a bitwise AND for integer MOD
when possible; using AND has no effect except to make the code harder to
understand.

If you’d like an example of this, let me know in private (too off-topic)
and I’ll show you how this can be demonstrated.

(Apologies for the off-topic post; I have difficulty letting misdirected
optimization advise go without being corrected, as it leads to ugly code
that I may some day have to deal with. :slight_smile:


Glenn Maynard

angle = (angle + 1) % 32;
angle = (angle + 31) % 32;

To generalize this trick a bit, (a + b) % c can be written as
(a + b + c) % c, to get positive results from a negative “b”, as long
as abs(b) < c (that is, as long as the +c is enough to push it back

= 0). If that’s not the case, there’s “t = (a + b) % c” (gives a
number between -c and c, exclusive) and then “(t + c) % c”.

This is the faworable way to use clamped values I think, because it is
general and takes only about twice the time that the AND version uses.

This is good if the divisor is not an exact power of two. How ever
if it is the original example, which uses and is faster, so no
reason to use this.

(Oh. I had to read this for a moment to figure out what you meant.
Tip: it helps to capitalize boolean operations–“which uses AND”–for
readability.)

Yep my mistake didn’t hit the caps lock while writing. No I made sure I
did. :wink:

This is incorrect. The compiler will use a bitwise AND for integer
MOD when possible; using AND has no effect except to make the code
harder to understand.

No it is not. Try it out. I did.
If you do, make sure you don’t let the compiler ingnore the result you
calculate in the loop ie use it in some where after the loop. Or even
the lowest level optimization will optimize the test code off as
unnecessary code. And make sure the loop limit value is not trivially
known at compile time.

My test code results:

The a = 0 print out is used to make sure that the looped code will not
be optimized out.

Result with gcc 2.95.3

sami at voltage ~/prog/tests $ gcc -O3 loop_testing.c
sami at voltage ~/prog/tests $ ./a.out
a = 0
Running a = (a + 1) % 32 100000000 times
Took: 1 sec 340 ms
Begin: 1043810358.157 sec End: 1043810359.497 sec

a = 0
Running a = (a + 31) % 32 100000000 times
Took: 1 sec 356 ms
Begin: 1043810359.499 sec End: 1043810360.855 sec

a = 0
Running a = (a + 1) & 31 100000000 times
Took: 0 sec 266 ms
Begin: 1043810360.857 sec End: 1043810361.123 sec

a = 0
Running a = (a - 1) & 31 100000000 times
Took: 0 sec 263 ms
Begin: 1043810361.125 sec End: 1043810361.388 sec

Result with gcc 3.2.1

sami at voltage ~/prog/tests $ source /etc/profile
sami at voltage ~/prog/tests $ gcc -O3 loop_testing.c
sami at voltage ~/prog/tests $ ./a.out
a = 0
Running a = (a + 1) % 32 100000000 times
Took: 0 sec 693 ms
Begin: 1043811297.99 sec End: 1043811297.792 sec

a = 0
Running a = (a + 31) % 32 100000000 times
Took: 0 sec 675 ms
Begin: 1043811297.794 sec End: 1043811298.469 sec

a = 0
Running a = (a + 1) & 31 100000000 times
Took: 0 sec 273 ms
Begin: 1043811298.471 sec End: 1043811298.744 sec

a = 0
Running a = (a - 1) & 31 100000000 times
Took: 0 sec 269 ms
Begin: 1043811298.746 sec End: 1043811299.15 sec

Oh and now I shut up. ;)On Wednesday 29 January 2003 03:48, Glenn Maynard wrote:

On Wed, Jan 29, 2003 at 03:16:51AM +0200, Sami N??t?nen wrote:

Yep you are right I got the correctness mixed you in my head. Too much
compilers too litle math. I think I have to start reading a bit math
again so that I don’t make too many mistakes. ;)On Wednesday 29 January 2003 03:36, Daniel Phillips wrote:

On Tuesday 28 January 2003 23:30, Sami N??t?nen wrote:

On Tuesday 28 January 2003 22:54, Sami N??t?nen wrote:
In fact the above thing doesn’t work correctly, because the C
standard defines the %-operator as mathematically correct reminder
operation.

So the -1 % 32 = -1, but we want it to be 31.

Niggle time:

You meant to say the C standard defines the % operator as the
mathematically incorrect remainder, otherwise known as truncation
towards zero, and formally defined as discarding any fractional part
of the result. This is purely for efficiency - mathematically it’s
offensive, but unfortunately we can’t go back in time and add the few
extra transistors it would have taken to do the job properly in the
early CPUs.

By the way you can get the mathematically correct answer if you make it
like this.

int a = 0;
a = (unsigned int)(a - 1) % 32;On Wednesday 29 January 2003 05:53, Sami N??t?nen wrote:

On Wednesday 29 January 2003 03:36, Daniel Phillips wrote:

On Tuesday 28 January 2003 23:30, Sami N??t?nen wrote:

On Tuesday 28 January 2003 22:54, Sami N??t?nen wrote:
In fact the above thing doesn’t work correctly, because the C
standard defines the %-operator as mathematically correct
reminder operation.

So the -1 % 32 = -1, but we want it to be 31.

Niggle time:

You meant to say the C standard defines the % operator as the
mathematically incorrect remainder, otherwise known as truncation
towards zero, and formally defined as discarding any fractional
part of the result. This is purely for efficiency - mathematically
it’s offensive, but unfortunately we can’t go back in time and add
the few extra transistors it would have taken to do the job
properly in the early CPUs.

Yep you are right I got the correctness mixed you in my head. Too
much compilers too litle math. I think I have to start reading a bit
math again so that I don’t make too many mistakes. :wink:

Right, but then you are laying a trap for the unsuspecting person who changes
32 to 36.

Regards,

DanielOn Wednesday 29 January 2003 05:16, you wrote:

By the way you can get the mathematically correct answer if you make it
like this.

int a = 0;
a = (unsigned int)(a - 1) % 32;

(I’ll reply to this off-list.)On Wed, Jan 29, 2003 at 05:49:27AM +0200, Sami N??t?nen wrote:

No it is not. Try it out. I did.


Glenn Maynard

Please take this thread to an appropriate forum.

Thanks,
-Sam Lantinga, Software Engineer, Blizzard Entertainment> On Tuesday 28 January 2003 23:30, Sami N??t?nen wrote:

On Tuesday 28 January 2003 22:54, Sami N??t?nen wrote:
In fact the above thing doesn’t work correctly, because the C standard
defines the %-operator as mathematically correct reminder operation.

So the -1 % 32 = -1, but we want it to be 31.

Niggle time: