tags:

views:

186

answers:

4

Can someone explain to me what this does?

#define ROUNDUP(n,width) (((n) + (width) - 1) & ~unsigned((width) - 1))
+6  A: 

Providing width is an even power of 2 (so 2,4,8,16,32 etc), it will return a number equal to or greater than n, which is a multiple of width, and which is the smallest value meeting that criteria.

So width = 16; 5->16, 7->16, 15->16, 16->16, 17->32, 18->32 etc.

EDIT I started out on providing an explanation of why this works as it does, as I sense that's really what the OP wants, but it turned into a rather convoluted story. If the OP is still confused, I'd suggest working through a few simple examples, say width = 16, n=15,16,17. Remember that & = bitwise AND, ~ = bitwise complement, and to use binary representation exclusively as you work through the examples.

Bill Forster
Note that the width *must* be a power of two... there are some cases where roundup seems to work for other widths (roundup width 3 works for n <5 for example) but only in a few bizarre corner cases.
Sam Post
@Bill - an *even* power of 2? That's odd...
tony
Cute tony :-) Since 2^(1.58496298..) = 3 (say), I think it is reasonable to add an extra qualifier to indicate that powers of 2 of that type are excluded. I think an "even power of two" is a common if colloquial way of doing that. Sorry for a pedantic reply to a humorous comment :-).
Bill Forster
@Bill here I was thinking you were excluding 1 ;) since that makes the part `~unsigned((width) - 1)` equal to 0 and thus the whole result equal to 0.
JPvdMerwe
@JPvdMerwe No I think we can include 1, because the mask isn't then 0, it's ~0 (complement of 0, i.e. all 1s) and the macro is thus a no-op, i.e. n->n, which is as you'd expect (round up to the nearest multiple of 1 = do nothing).
Bill Forster
You're right I had the orders of the operators in my head mixed up. It's when `width = 0` that what I said happens.
JPvdMerwe
@Bill - no problem.
tony
A: 

It won't work in C because of the unsigned. Here is what is does, as long as width is confined to powers of 2:

 n width ROUNDUP(n,width)
----------------
 0   4    0
 1   4    4
 2   4    4
 3   4    4
 4   4    4
 5   4    8
 6   4    8
 7   4    8
 8   4    8
 9   4    12
10   4    12
11   4    12
12   4    12
13   4    16
14   4    16
15   4    16
16   4    16
17   4    20
18   4    20
19   4    20
wallyk
+2  A: 

It rounds n up to the next 'width' - but I think width needs to be a power of 2.

For example width == 8, n = 5:

(5 + 8 - 1) & ~(7) = 12 & ~7 = 8

So 5 rounds to 8. Anything 1 - 8 rounds to 8. 9 to 16 rounds to 16. Etc. (0 rounds to 0)

tony
+2  A: 

It defines a macro called ROUNDUP which takes two parameters, n and width, and returns the value (n + width - 1) & ~unsigned(width - 1).

:)

Try this if you think you know what it does:

std::string s("WTF");
std::complex<double> c(-11,5);
ROUNDUP(s, c);
+1 for MACROS are EVIL example.
tony