qwr
qwr

Reputation: 10891

C compile-time lookup table generation

In this answer about brute-forcing 2048 AI, a lookup table storing "2048 array shifts" is precomputed to save needless repetitive calculation. In C, to compute this lookup table at compile time, the way I know of is the "caveman-simple solution" where the table itself is generated as another file that is then #included, something like this python script to generate lut.include (replace with 2048-specific code):

#!/usr/bin/python

def swapbits(x):
    ret=0
    for i in range(8):
        if x&(1<<i): ret |= 1<<(7-i)
    return ret

print "const uint8_t bitswap[] = {",
print ", ".join("0x%02x"%swapbits(x) for x in range(256)),
print "}"

Is there any cleaner approach? That is, maybe some preprocessor trickery to generate these tables? With C++ this should be possible with constexpr.

Upvotes: 0

Views: 936

Answers (1)

KamilCuk
KamilCuk

Reputation: 140960

C preprocessor has no loops. You have to write all numbers in C preprocessor, one way or the other.

Cleaner meaning does not involve another script and included file

First, implement a constant expression swapping bits:

#define SWAPBITS(x)  ((x&1)<<7)|((x&2)<<6)|((x&3)<<5).... etc.

Then you just write all the numbers:

const uint8_t arr[] = 
   SWAPBITS(0),
   SWAPBITS(1),
   ... etc. ...
   // Because you do not want to use external script, write all the numbers manually here.
};

If the "included file" can be lifted, you can use BOOST_PP_REPEAT. Note that that macro literally lists all iterations it can be called with. Similar with P99_REPEAT from p99 library.

#include <boost/preprocessor/repetition/repeat.hpp>
#define SWAPBITS(x)  .. as above ..
#define SWAPBITS_DECL(z, n, t)  SWAPBITS(n),
const uint8_t arr[] = {
   BOOST_PP_REPEAT(256, SWAPBITS_DECL,)
};

Upvotes: 1

Related Questions