C++11: Compile-time pseudo random number generator

One of the best feature of modern C++ has to be constexpr. Its flexibility allows for a more streamlined transition from runtime to compile-time computations for both values and expressions that are or can be known during compilation, the resulting executable can take longer to compile but will contain less instructions to process. Potentially producing a (sometimes drastically) faster program.

A simple yet interesting example of its usage is this compile time, pseudo random number generator that computes a "random" 32 bit integer and directly hard-codes it into the executable. Stripping away the algorithm behind its origin. I originally came across a more bare bones implementation while surfing around and modified it to the source below, though I still ignore if the scrambling function itself is a known algorithm or just a quick attempt at pseudo randomization, either way this only goes to show how far C++ has come.

To compile:


$ g++ -std=c++11 -Wall -Wextra  lrng.cpp -o lrng
                        

If you're using an older compiler you may have to add an optimization flag (-O1, -O2 or -O3) to get the full use of constexpr.

Source code:


#include cstdint
#include limits

// #include iostream
// #include string

// Note on the gcc standard predifined macro __TIME__
//
// __TIME__
// This macro expands to a string constant that describes the time
// at which the preprocessor is being run. The string constant contains
// eight characters and looks like "23:59:01".
// If GCC cannot determine the current time, it will emit a warning
// message (once per compilation) and __TIME__ will expand to "??:??:??".


// Scramble the macro once per character (8 times) using the previous
// result as base
constexpr auto seed()
{
    std::uint64_t base = 0;
    for (const auto c : __TIME__)
    {
        base <<= 8;
        base |= c;
    }

    return base;
}

class LRNG
{
private:
    // Further scramble the __TIME__ generated integer, each iteration uses
    // the previous state as base. Member to use the std implementation of
    // integers to support arbitrary amounts of iterations without overflowing
    constexpr std::uint32_t random_32()
        {
            std::uint64_t delta = random.state;
            random.state = delta * 6364136223846793005ULL + (random.inc|1);
            std::uint64_t xord = ((delta >> 18u) ^ delta) >> 27u;
            std::uint64_t rot = delta >> 59u;
            return (xord >> rot) | (xord << ((-rot) & 31));
        }

public:
    struct LRNG_SEED { std::uint64_t state = 0; std::uint64_t inc = seed(); };
    LRNG_SEED random;

    constexpr std::uint32_t operator()()
        {
            return random_32();
        }

};

constexpr auto getRandom(int count)
{
    LRNG rng;
    while(count > 0)
    {
        rng();
        --count;
    }
    return rng();
}

int main(int argc, char *argv[])
{
    constexpr auto r = getRandom(5);
    //std::cout << "RNG: " << std::to_string(r) <<"\n";
    // std::cout << "RNG: " << std::to_string(getRandom(5)) <<"\n";
    return r;
}

                            

A quick analysis using radare2 proves that the number was indeed generated at compile time and hard-coded into the executable, abstracting away all the responsible code.

The entire main function with the hardocded (pseudo) random number (optimization disabled)

Printing the number using std::cout would of course add overhead initialization code irrelevant to the example, but do note that simply returning the number from main() will truncate it into an 8-bit unsigned integer that the parent shell can interpret as a C exit status-table or bash return code. As such:


$ g++ -std=c++20 -Wall -Wextra  lrng.cpp -o lrng
$ ./lrng
$ echo $?
                        

Will not return the actual, generated number!