Circular Increment

While some of the larger articles are still in the oven, I’ll drop a little programming tip that most experienced programmers should already know, but I happen to find quite useful in a lot of scenarios. Here’s the problem: you have an array of size n and an index i into that array. You’d like to increment i so that it points to the next position in the array, but have it return to the first position once the end of the array is reached. The most obvious way to write this would be something like:

But for some situations it’s useful to know that you can also write this operation as a single statement, either by using the modulus operator or the ternary operator:

I have personally grown to prefer the modulus operator version, because it is shorter, and because I’ve come to associate the modulus operator with range limiting whenever I see it.

Usage Example

Before continuing I should note that some readers have pointed out that the modulus operator is expensive, so it shouldn’t be placed inside of any large loops. Therefore if you’re worried about a performance hit, do not use this technique inside any loop (like I’ll be doing next), and save it for one-shot scenarios. Having said that, I still find it useful when prototyping since it lets me get things done in fewer lines of code. And of course, it’s perfectly fine to use it for things that won’t be running every frame. For instance, if your character has a bunch of different weapons, and you’d like to cycle through them when the user presses a key, that’s a nice place to use it!

Here’s a XNA example where I find this trick useful. Let’s say we have a list of vertices defining a polygon, and we’d like to draw the polygon’s outline by using a DrawLine(from, to) function such as the one described here. Before I discovered this trick, I’d loop through each vertex in the list and draw a line from that vertex to the next one, and then handle the final line connecting the last and the first vertices separatedly:

But using one of the tricks outlined earlier, you can easily handle the final case inside the for loop with minor modifications:

Like I said, this trick does come at a performance cost since the modulus operator is likely more expensive than a simple branch. Despite that, I can’t say I’ve ever noticed any sort of slowdown due to this, probably because I have only been developing for Windows, and all of the loops I use it in are rather small. Either way, it’s a nice trick to have in the bag, if only so that you won’t get alienated the next time you see that % operator used this way (e.g. I’ve seen it used today in one of the XNA education samples).

  1. David Amador says:

    Great article
    Just keep in mind that using the modulus operator on big loops can cause performance drop and in most cases the conventional way is much better.

    • You’re right! Using the modulus operator is certainly more expensive than the alternative. But I think that by today’s computers standards, you’d have to be looping over something *really* big to even notice any difference.

      Years ago people also used arithmetic shifts in place of multiplications and divisions (e.g. replace n * 2 with n << 1) but who really does that anymore? I've seen these called "pico-optimizations", which I happen to find quite amusing. 😀

  2. Keep in mind that the optimizations changing a * 2 into a << 1 are done by the compiler because it can, where as % 14 cannot be optimized in any way; it really does have to do that very slow division in there, no matter how smart your compiler is. The only saving grace is if you can do &7 to replace a %8, if the number is an even power of 2, in which case the compiler may step in. I've grown to desire using powers of 2 on purpose and then purposely using & to handle the cutoff, but I come from an assembly language background so this makes sense to me.

    So the real question is if division is too slow. Of course it's ok for a one shot deal, but in a loop, XNA math can be excruciatingly slow. Literally something that runs in 1/60th of a second on a slow PC can take over a second, that's 60 frames, on the Xbox 360 due to the lack of optimization of the Compact .NET Framework that the Xbox 360 uses, that barely even has support, let alone optimization, for floating point numbers.

    There are several articles on optimizing XNA for the Xbox 360 that covers a lot of such things, all the way to initializing Vector2's outside the constructor = faster, and believe me, I routinely find myself having to resort to such methods to squeeze some more time out. So no divisions in loops for me with XNA.

    • Thank you for your feedback, and using operator & like that is actually new to me. I think I might have seen it used before that way, but didn’t realize what was the intent.

      And perhaps the reason why I never experienced any slow down so far is because I’ve been developing for Windows exclusively, and have been using it only in small loops such as looping over the vertices of a polygon and such.

      So I’ll keep this advice in mind and choose carefully when it should be okay to use it and when I shouldn’t. 🙂

Leave a Reply