# [SDL] Best way to rotate a sprite?

Sami Näätänen sami.naatanen at kolumbus.fi
Tue Jan 28 19:48:01 PST 2003

```On Wednesday 29 January 2003 03:48, Glenn Maynard wrote:
> > > 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.

> 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

Yep my mistake didn't hit the caps lock while writing. No I made sure I
did. ;)

> 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. ;)

```