views:

531

answers:

6

what's a fast way to roundup a unsigned int to a multiple of 4?

a multiple of 4 has the two least significant bits 0, right? so i could mask them out and then do a switch statement, adding either 1,2 or 3 to the given uint. that's not a very elegant solution..

there's also the arithmetic roundup:

myint==0?0:((myint+3)/4)*4

probably there's a better way including some bit operations?

thx!

+7  A: 
(myint + 3) & ~0x03

The addition of 3 is so that the next multiple of 4 becomes previous multiple of 4, which is produced by a modulo operation, doable by masking since the divisor is a power of 2.

jk
this won't give the next multiple if the myint is already a multiple of 4
Michael Bray
It does: a multiple of 4 gets its two lowest bits set, which then get masked away, leaving the original, which is how the OP's code works too.
jk
yes that's what i meant =) thanks! :)
genesys
what if myint is 0 ?
gameover
Michael Brays criticism is correct. If myint is already a multiple of 4, it is unchanged. jk's expression gives the smallest multiple of 4 that is the same or larger than the original value. This is not what I'd genereally understand "the next multple of 4" to mean.
Stephen C. Steel
it's what i meant with the question - i changed the description to fit better what i actually meant :)
genesys
If `myint` is 0, this produces 0. @Stephen: The OP provided code that performs the operation he wanted, and "next multiple" can be read as rounding up (and in my experience, much more commonly is), so Michael Bray's criticism does not apply to this case.
jk
+1  A: 

(myint + 4) & 0xFFFC

Michael Bray
I suppose this depends on how "next" is defined when the number is already divisible by 4.
tvanfosson
This also depends upon the size of `myint` being 2 bytes, and sets the most significant bytes to 0 if `sizeof myint` > 2.
Alok
+1 adding 4 seems to work..not adding 3.
gameover
@Alok: true, but trivial to fix.
Michael Bray
The trivial fix is to use ~0x3, which is independent of the size of int.
Alok
@Alok: that's what I meant. sheesh.
Michael Bray
@Michael: I was being pedantic, because this is a programming website. Your answer, in the current form, is wrong. No offense meant (and no, I didn't downvote you).
Alok
+2  A: 

If by "next multiple of 4" you mean the smallest multiple of 4 that is larger than your unsigned int value myint, then this will work:

(myint | 0x03) + 1;
Stephen C. Steel
Nice one, especially since an increment might be faster than adding a constant. But seems it's not what the OP wanted.
0xA3
A: 

If you want the next multiple of 4 strictly greater than myint, this solution will do (similar to previous posts):

(myint + 4) & ~3u

If you instead want to round up to the nearest multiple of 4 (leaving myint unchanged if it is a multiple of 4), this should work:

(0 == myint & 0x3) ? myint : ((myint + 4) & ~3u);
Kevin
A: 

myint = (myint + 4) & 0xffffffc

This is assuming that by "next multiple of 4" that you are always moving upwards; i.e. 5 -> 8 and 4 -> 8.

DonaldRay
+3  A: 

I assume that what you are trying to achieve is the alignment of the input number, i.e. if the original number is already a multiple of 4, then it doesn't need to be changed. However, this is not clear from your question. Maybe you want next multiple even when the original number is already a multiple? Please, clarify.

In order to align an arbitrary non-negative number i on an arbitrary boundary n you just need to do

i = i / n * n;

But this will align it towards the negative infinity. In order to align it to the positive infinity, add n - 1 before peforming the alignment

i = (i + n - 1) / n * n;

This is already good enough for all intents and purposes. In your case it would be

i = (i + 3) / 4 * 4;

However, if you would prefer to to squeeze a few CPU clock out of this, you might use the fact that the i / 4 * 4 can be replaced with a bit-twiddling i & ~0x3, giving you

i = (i + 3) & ~0x3;

although it wouldn't surprise me if moder compilers could figure out the latter by themselves.

AndreyT