Compute buffer size at compile-time

S

Spoon

Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0

I came up with: (BS stands for BUFFER_SIZE)

(BS & ~15) + ((BS&15 != 0) << 4)

which can be written in a simpler way:

((BS-1) & ~15) + 16

Although there might be a problem if BS is an int and 0.
I think 0-1 is well-defined if BS is an unsigned int?

I welcome your comments.

I also toyed with the idea of returning the next power of 2:

31 -> 32
32 -> 32
33 -> 64
48 -> 64
64 -> 64
65 -> 128

but I couldn't figure out how to compute it at compile-time elegantly.
(I need a loop which I could completely unroll... ugly.)

Regards.
 
I

Ico

Spoon said:
Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0

#define N (BS / 16) * 16 + 16 ?
 
E

Eric Sosman

Ico said:
Spoon said:
Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0


#define N (BS / 16) * 16 + 16 ?

Be careful of those boundary cases. If BS is divisible
by 16, the above formula adds an extra 16 instead of just
leaving it alone.

#define N ((BS + 15) & ~15)

More generally,

#define ROUNDUP(min,chunk) \
(((min) + (chunk) - 1) / (chunk) * (chunk))
 
I

Ico

Ico said:
Spoon said:
Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0

#define N (BS / 16) * 16 + 16 ?

Hmm, please ignore this, it's wrong *and* doesnt answer the OP's
question.
 
R

Rod Pemberton

Spoon said:
Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0

That returns one if N is a multiple of sixteen and over 1234. Don't you
want it to return one if N is a multiple of sixteen below 1234 and return
one for all values over 1234? I think you want an logical or, '||', instead
of a logical and, '&&'.

That would be this:
(N >= 1234) || ((N % 16) == 0)

If your compiler uses two's complement (most do), that simplifies to this
(for unsigned values):

(N >= 1234) || (!(N&0x0F))

The value '1234' isn't expressed in binary in a manner which could eliminate
the comparison (i.e., all bits set).

(BS & ~15) + ((BS&15 != 0) << 4)

Except for zero which returns 0, this returns the multiple of sixteen larger
than the current value. I don't think you wanted that.
((BS-1) & ~15) + 16

Again, except for zero which returns 0, this returns the multiple of sixteen
larger than the current value.


HTH,

Rod Pemberton
 
R

Rod Pemberton

Eric Sosman said:
Ico said:
Spoon said:
Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0


#define N (BS / 16) * 16 + 16 ?

Be careful of those boundary cases. If BS is divisible
by 16, the above formula adds an extra 16 instead of just
leaving it alone.

#define N ((BS + 15) & ~15)

More generally,

#define ROUNDUP(min,chunk) \
(((min) + (chunk) - 1) / (chunk) * (chunk))

While you corrected Spoon's post, you didn't realize his or two of the OP's
calculations don't compute "N >= 1234 && N % 16 == 0" properly.


Rod Pemberton
 
E

Eric Sosman

Rod said:
Ico wrote:

Spoon <none> wrote:


Hello,

Consider:

#define BUFFER_SIZE 1234 /* or some other value */
uint8_t buffer[BUFFER_SIZE];
int do_stuff(uint8_t *buf);

where do_stuff() does something with each octet in the buffer.

Assume I've come up with do_stuff_2() similar to do_stuff() but
that works with 16 octets at a time.

I need to compute N at compile time
such that N >= 1234 && N % 16 == 0



#define N (BS / 16) * 16 + 16 ?

Be careful of those boundary cases. If BS is divisible
by 16, the above formula adds an extra 16 instead of just
leaving it alone.

#define N ((BS + 15) & ~15)

More generally,

#define ROUNDUP(min,chunk) \
(((min) + (chunk) - 1) / (chunk) * (chunk))


While you corrected Spoon's post, you didn't realize his or two of the OP's
calculations don't compute "N >= 1234 && N % 16 == 0" properly.

That expression isn't the result he's trying to compute.
He's trying to find an N such that the above expression will
be true, not to test whether it is true for a given N.

He didn't say so, but I assumed from context that he wants
not just any such N, but the least such N. It was on the basis
of that assumption that I responded -- not to Spoon's post but
to Ico's, by the way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,566
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top