Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Mathew Hendry's macro for binary integer literals

Reply
Thread Tools

Mathew Hendry's macro for binary integer literals

 
 
Tomás Ó hÉilidhe
Guest
Posts: n/a
 
      06-17-2008

Here's a macro that Mathew Hendry posted back in the year 2000 for
achieving binary integer literals that evaluate to compile-time
constants:

#define BIN8(n)\
(((0x##n##ul&1<< 0)>> 0)|((0x##n##ul&1<< 4)>> 3)\
|((0x##n##ul&1<< >> 6)|((0x##n##ul&1<<12)>> 9)\
|((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
|((0x##n##ul&1<<24)>>1|((0x##n##ul&1<<2>>21))

Now admittedly I don't know how it works mathematically, but still I
want to perfect it. The first thing I did was made it more readable
(in my own opinion of course):

#define BIN8(n)\
(

((0x##n##ul & 1<<0) >> 0) | ((0x##n##ul & 1<<0) >>
3) \
| ((0x##n##ul & 1<< >> 6) | ((0x##n##ul & 1<<12)>>
9) \
| ((0x##n##ul & 1<<16)>>12) | ((0x##n##ul &
1<<20)>>15) \
| ((0x##n##ul & 1<<24)>>1 | ((0x##n##ul &
1<<2>>21) \
)

From there, the only flaw I can see is in the expression "1 << 24",
which I think should be "1lu << 24", so that gives us:

#define BIN8(n)\
(

((0x##n##ul & 1lu<<0) >> 0) | ((0x##n##ul & 1lu<<0)
>> 3) \

| ((0x##n##ul & 1lu<< >> 6) | ((0x##n##ul &
1lu<<12)>> 9) \
| ((0x##n##ul & 1lu<<16)>>12) | ((0x##n##ul &
1lu<<20)>>15) \
| ((0x##n##ul & 1lu<<24)>>1 | ((0x##n##ul &
1lu<<2>>21) \
)

Is that perfect now? Or does it need more tweaking? Even if you post
to say you think it's perfect then that'd be a help.

 
Reply With Quote
 
 
 
 
badc0de4@gmail.com
Guest
Posts: n/a
 
      06-17-2008
Tomás Ó hÉilidhe wrote:
> Here's a macro that Mathew Hendry posted back in the year 2000 for
> achieving binary integer literals that evaluate to compile-time
> constants:
>
> #define BIN8(n)\
> (((0x##n##ul&1<< 0)>> 0)|((0x##n##ul&1<< 4)>> 3)\
> |((0x##n##ul&1<< >> 6)|((0x##n##ul&1<<12)>> 9)\
> |((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
> |((0x##n##ul&1<<24)>>1|((0x##n##ul&1<<2>>21))
>
> Now admittedly I don't know how it works mathematically


The 0, 4, 8, ... correspond to the "bit position" when interpreted as
a hexadecimal value.

For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
so
0x00100000 & (1 << 20) isolates that bit, and
0x00100000 >> 15 "moves it (back) to its 'proper' hexadecimal
position.

> , but still I
> want to perfect it. The first thing I did was made it more readable
> (in my own opinion of course):
>

... so that gives us:
>
> #define BIN8(n)\
> (
>
> ((0x##n##ul & 1lu<<0) >> 0) | ((0x##n##ul & 1lu<<0)
> >> 3) \

> | ((0x##n##ul & 1lu<< >> 6) | ((0x##n##ul &
> 1lu<<12)>> 9) \
> | ((0x##n##ul & 1lu<<16)>>12) | ((0x##n##ul &
> 1lu<<20)>>15) \
> | ((0x##n##ul & 1lu<<24)>>1 | ((0x##n##ul &
> 1lu<<2>>21) \
> )
>
> Is that perfect now?


Two things come to mind:

a) it doesn't cope well with usenet (re-)formatting
b) you have the original "ul" mixed with your "lu". I'd like it better
if all suffixes were the same.
 
Reply With Quote
 
 
 
 
Kaz Kylheku
Guest
Posts: n/a
 
      06-17-2008
On Jun 17, 6:51*am, (E-Mail Removed) wrote:
> Tomás Ó hÉilidhe wrote:
> > Here's a macro that Mathew Hendry posted back in the year 2000 for
> > achieving binary integer literals that evaluate to compile-time
> > constants:

>
> > * #define BIN8(n)\
> > * * (((0x##n##ul&1<< 0)>> 0)|((0x##n##ul&1<< 4)>> 3)\
> > * * |((0x##n##ul&1<< >> 6)|((0x##n##ul&1<<12)>> 9)\
> > * * |((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
> > * * |((0x##n##ul&1<<24)>>1|((0x##n##ul&1<<2>>21))

>
> > Now admittedly I don't know how it works mathematically

>
> The 0, 4, 8, ... correspond to the "bit position" when interpreted as
> a hexadecimal value.
>
> For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
> so
> 0x00100000 & (1 << 20) isolates that bit, and
> 0x00100000 >> 15 "moves it (back) to its 'proper' hexadecimal
> position.
>
> > , but still I
> > want to perfect it. The first thing I did was made it more readable
> > (in my own opinion of course):

>
> ... so that gives us:
>
>
>
> > #define BIN8(n)\
> > * * (

>
> > * * * * * * ((0x##n##ul & 1lu<<0) >> 0) * *| * * ((0x##n##ul & 1lu<<0)
> > >> 3) * *\

> > * * * * | * ((0x##n##ul & 1lu<< >> 6) * *| * * ((0x##n##ul &
> > 1lu<<12)>> 9) * *\
> > * * * * | * ((0x##n##ul & 1lu<<16)>>12) * *| * * ((0x##n##ul &
> > 1lu<<20)>>15) * *\
> > * * * * | * ((0x##n##ul & 1lu<<24)>>1 * *| * * ((0x##n##ul &
> > 1lu<<2>>21) * *\
> > * * )

>
> > Is that perfect now?

>
> Two things come to mind:
>
> a) it doesn't cope well with usenet (re-)formatting
> b) you have the original "ul" mixed with your "lu". I'd like it better
> if all suffixes were the same.


- Too much repetition. Adding 0x and UL can be done by a helper macro.

- Suggest parentheses for awkward precedence of & relative to <<:

#define HEX_CODED_BIN(N)\
(((N & 1 << 0) >> 0)|((N & 1 << 4) >> 3)\
|((N & 1 << >> 6)|((N & 1 << 12) >> 9)\
|((N & 1 << 16) >>12)|((N & 1 << 20) >> 15)\
|((N & 1 << 24) >>1|((N & 1 << 2 >> 21))


#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

Furthermore, the shifting can be done first and then the masking,
which simplifies the choice of shift values:

#define HEX_CODED_BIN(N) \
((((N >> 0) & 1) << 0) | (((N >> 16) & 1) << 4) | \
(((N >> 4) & 1) << 1) | (((N >> 20) & 1) << 5) |\
(((N >> & 1) << 2) | (((N >> 24) & 1) << 6) | \
(((N >> 12) & 1) << 3) | (((N >> 2 & 1) << 7))

See? The logic is is a lot clearer now, because offsets in hex space
don't have to be translated into shift amounts in binary space. The 0,
4, 8, 12 ... values are obvious: we are shifting a hex digit into the
least significant digit position. The & 1 tells us we are masking out
a 0 or 1, and the 0, 1, 2, 3 ... shifts are obvious also: shifting a
bit into the correct position within the byte.

I transposed the calculation into columns, for further readability.

- Remark: A BIN32 macro is easy to make:

#define BIN32(A, B, C, D) \
(BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << | (BIN8(D))

- Complete program:

#include <stdio.h>

#define HEX_CODED_BIN(N) \
((((N >> 0) & 1) << 0) | (((N >> 16) & 1) << 4) | \
(((N >> 4) & 1) << 1) | (((N >> 20) & 1) << 5) | \
(((N >> & 1) << 2) | (((N >> 24) & 1) << 6) | \
(((N >> 12) & 1) << 3) | (((N >> 2 & 1) << 7))

#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)

#define BIN32(A, B, C, D) \
(BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << | (BIN8(D))

int main(void)
{
unsigned int bin1 = BIN8(10101010);
unsigned int bin2 = BIN8(01010101);
unsigned int bin3 = BIN8(11111111);
unsigned int bin4 = BIN8(00000000);
unsigned long bin5 = BIN32(10101010, 01010101, 11110000,
00001111);

printf("bin1 == %x\n", bin1);
printf("bin2 == %x\n", bin2);
printf("bin3 == %x\n", bin3);
printf("bin4 == %x\n", bin4);
printf("bin5 == %lx\n", bin5);

return 0;
}

Output:

bin1 == aa
bin2 == 55
bin3 == ff
bin4 == 0
bin5 == aa55f00f

Cheers.





 
Reply With Quote
 
Tomás Ó hÉilidhe
Guest
Posts: n/a
 
      06-17-2008
On Jun 17, 6:51*pm, Kaz Kylheku <(E-Mail Removed)> wrote:

> - Complete program:
>
> #include <stdio.h>
>
> #define HEX_CODED_BIN(N) \
> * ((((N >> *0) & 1) << 0) | (((N >> 16) & 1) << 4) | \
> * *(((N >> *4) & 1) << 1) | (((N >> 20) & 1) << 5) | \
> * *(((N >> * & 1) << 2) | (((N >> 24) & 1) << 6) | \
> * *(((N >> 12) & 1) << 3) | (((N >> 2 & 1) << 7))
>
> #define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)
>
> #define BIN32(A, B, C, D) \
> * (BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << | (BIN8(D))
>
> int main(void)
> {
> * * unsigned int bin1 = BIN8(10101010);
> * * unsigned int bin2 = BIN8(01010101);
> * * unsigned int bin3 = BIN8(11111111);
> * * unsigned int bin4 = BIN8(00000000);
> * * unsigned long bin5 = BIN32(10101010, 01010101, 11110000,
> 00001111);
>
> * * printf("bin1 == %x\n", bin1);
> * * printf("bin2 == %x\n", bin2);
> * * printf("bin3 == %x\n", bin3);
> * * printf("bin4 == %x\n", bin4);
> * * printf("bin5 == %lx\n", bin5);
>
> * * return 0;
>
> }
>
> Output:
>
> bin1 == aa
> bin2 == 55
> bin3 == ff
> bin4 == 0
> bin5 == aa55f00f



Very nice, good stuff.
 
Reply With Quote
 
Kaz Kylheku
Guest
Posts: n/a
 
      06-18-2008
On Jun 17, 10:51*am, Kaz Kylheku <(E-Mail Removed)> wrote:
> On Jun 17, 6:51*am, (E-Mail Removed) wrote:
>
>
>
>
>
> > Tomás Ó hÉilidhe wrote:
> > > Here's a macro that Mathew Hendry posted back in the year 2000 for
> > > achieving binary integer literals that evaluate to compile-time
> > > constants:

>
> > > * #define BIN8(n)\
> > > * * (((0x##n##ul&1<< 0)>> 0)|((0x##n##ul&1<< 4)>> 3)\
> > > * * |((0x##n##ul&1<< >> 6)|((0x##n##ul&1<<12)>> 9)\
> > > * * |((0x##n##ul&1<<16)>>12)|((0x##n##ul&1<<20)>>15)\
> > > * * |((0x##n##ul&1<<24)>>1|((0x##n##ul&1<<2>>21))

>
> > > Now admittedly I don't know how it works mathematically

>
> > The 0, 4, 8, ... correspond to the "bit position" when interpreted as
> > a hexadecimal value.

>
> > For example, the "1" at '0b00100000' occupies bit 20 in 0x00100000,
> > so
> > 0x00100000 & (1 << 20) isolates that bit, and
> > 0x00100000 >> 15 "moves it (back) to its 'proper' hexadecimal
> > position.

>
> > > , but still I
> > > want to perfect it. The first thing I did was made it more readable
> > > (in my own opinion of course):

>
> > ... so that gives us:

>
> > > #define BIN8(n)\
> > > * * (

>
> > > * * * * * * ((0x##n##ul & 1lu<<0) >> 0) * *| * * ((0x##n##ul & 1lu<<0)
> > > >> 3) * *\
> > > * * * * | * ((0x##n##ul & 1lu<< >> 6) * *| * * ((0x##n##ul &
> > > 1lu<<12)>> 9) * *\
> > > * * * * | * ((0x##n##ul & 1lu<<16)>>12) * *| * * ((0x##n##ul &
> > > 1lu<<20)>>15) * *\
> > > * * * * | * ((0x##n##ul & 1lu<<24)>>1 * *| * * ((0x##n##ul &
> > > 1lu<<2>>21) * *\
> > > * * )

>
> > > Is that perfect now?

>
> > Two things come to mind:

>
> > a) it doesn't cope well with usenet (re-)formatting
> > b) you have the original "ul" mixed with your "lu". I'd like it better
> > if all suffixes were the same.

>
> - Too much repetition. Adding 0x and UL can be done by a helper macro.
>
> - Suggest parentheses for awkward precedence of & relative to <<:
>
> * *#define HEX_CODED_BIN(N)\
> * * *(((N & 1 << *0) >> 0)|((N & 1 << *4) >> *3)\
> * * *|((N & 1 << * >> 6)|((N & 1 << 12) >> *9)\
> * * *|((N & 1 << 16) >>12)|((N & 1 << 20) >> 15)\
> * * *|((N & 1 << 24) >>1|((N & 1 << 2 >> 21))
>
> * *#define BIN8(BITS) HEX_CODED_BIN(0x ## BITS ## UL)
>
> Furthermore, the shifting can be done first and then the masking,
> which *simplifies the choice of shift values:
>
> * *#define HEX_CODED_BIN(N) \
> * * * ((((N >> *0) & 1) << 0) | (((N >> 16) & 1) << 4) | \
> * * * *(((N >> *4) & 1) << 1) | (((N >> 20) & 1) << 5) |\
> * * * *(((N >> * & 1) << 2) | (((N >> 24) & 1) << 6) | \
> * * * *(((N >> 12) & 1) << 3) | (((N >> 2 & 1) << 7))
>
> See? The logic is is a lot clearer now, because offsets in hex space
> don't have to be translated into shift amounts in binary space. The 0,
> 4, 8, 12 ... values are obvious: we are shifting a hex digit into the
> least significant digit position. The & 1 tells us we are masking out
> a 0 or 1, and the 0, 1, 2, 3 ... shifts are obvious also: shifting a
> bit into the correct position within the byte.
>
> I transposed the calculation into columns, for further readability.
>
> - Remark: A BIN32 macro is easy to make:
>
> * *#define BIN32(A, B, C, D) \
> * * * (BIN8(A) << 24) | (BIN8(B) << 16) | (BIN8(C) << | (BIN8(D))
>
> - Complete program:
>
> #include <stdio.h>
>
> #define HEX_CODED_BIN(N) \
> * ((((N >> *0) & 1) << 0) | (((N >> 16) & 1) << 4) | \
> * *(((N >> *4) & 1) << 1) | (((N >> 20) & 1) << 5) | \
> * *(((N >> * & 1) << 2) | (((N >> 24) & 1) << 6) | \
> * *(((N >> 12) & 1) << 3) | (((N >> 2 & 1) << 7))


Furthermore, this pattern can be easily reduced like this:

#define BIT(N, K) (((N >> (4*K)) & 1) << K)

#define HEX_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7))


Let's have some fun: how about a decimal version of this? Decimal
constants give us more digits (without having to go to C99).

#define POW10_0 1
#define POW10_1 10
#define POW10_2 100
#define POW10_3 1000
#define POW10_4 10000
#define POW10_5 100000
#define POW10_6 1000000
#define POW10_7 10000000
#define POW10_8 100000000
#define POW10_9 1000000000

#define POW10(K) POW10_ ## K

#define BIT(N, K) (((N / POW10(K)) % 2) << K)

#define DEC_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7) | \
BIT(N, | BIT(N, 9))

#define BIN10(N) DEC_CODED_BIN(N ## UL)

But this version has serious bug---or, at least, a programmer pitfall.
That bug brings me to the next point: if we switch to octal, we
portably get 11 digits!

#define BIT(N, K) (((N >> (3*K)) & 1) << K)

#define OCT_CODED_BIN(N) \
(BIT(N, 0) | BIT(N, 1) | BIT(N, 2) | BIT(N, 3) | \
BIT(N, 4) | BIT(N, 5) | BIT(N, 6) | BIT(N, 7) | \
BIT(N, | BIT(N, 9) | BIT(N, 10))

#define BIN11(N) OCT_CODED_BIN(0 ## N ## UL)


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
negative integer literals Ivan Novick C++ 15 12-10-2006 09:24 PM
Integer Literals bradeck@gmail.com C++ 5 10-19-2006 02:31 PM
Java: byte literals and short literals John Goche Java 8 01-17-2006 11:12 PM
Template argument deduction on integer literals Bart Samwel C++ 14 04-22-2005 10:03 PM
Generic class literals - e.g,, Class<Map<String, Integer>>.class Purush Java 4 04-13-2005 08:40 PM



Advertisments