Search code examples
cprngroguelike

Implementation of the WELLRNG512


I have seen a lot of posts about the WELLRNG512. Supposedly I have concluded that it would be a better choice than the Mersenne Twister for a roguelike dungeon crawler. I am trying to get this piece of code to generate random numbers and behave much like rand().

Code used:

static unsigned long state[16];
static unsigned int index = 0;

int main (void) {
    int i;

    for (i = 0; i < 16; i++) {
        index = i;
        printf("random: %lu\n", WELLRNG512());
    }

    return 0;
}

unsigned long WELLRNG512 (void) {
    unsigned long a, b, c, d;

    a = state[index];
    c = state[(index+13)&15];
    b = a^c^(a<<16)^(c<<15);
    c = state[(index+9)&15];
    c ^= (c>>11);
    a = state[index] = b^c;
    d = a^((a<<5)&0xDA442D24UL);
    index = (index + 15)&15;
    a = state[index];
    state[index] = a^b^d^(a<<2)^(b<<18)^(c<<28);

    return state[index];
}

Expected results:

random: 231544
random: 542312
random: 588690
(...etc...)

Acquired results:

random: 4195755
random: 4195755
random: 4195755
(...etc...)

Has anyone got any idea how I can successfully make that piece of code behave like rand()?

P.S.: I'm a student, definitely not a mathematician, so please, explain your answer in great detail if you're going to use any kind of hieroglyphs to explain formula's, etc.


Solution

  • There are some things wrong with the code. The most important one: You are never calling the random number generator. This line here:

       printf("random: %lu\n", WELLRNG512);
    

    Prints the address of the WELLRNG512 function. It doesn't call it. To fix this try:

       printf("random: %lu\n", WELLRNG512());
    

    Second: The state array have to be filled with random data. Just for testing I threw something together based on the rand() function. That may or may not be a clever way to seed the state array, but it is good enough to get some random data out of your function.

    /* seed the state array */
    for (i = 0; i < 16; i++)
      state[i] = rand()^(rand()<<16)^(rand()<<31);
    

    Last thing: The function WELLRNG512 increments the index variable itself. There is no need to do this in the test loop found in main.

    My complete main function looks like this:

    int main (void) {
        int i;
    
        /* seed */
        for (i = 0; i < 16; i++)
          state[i] = rand()^(rand()<<16)^(rand()<<31);
    
        for (i = 0; i < 16; i++) {
            printf("random: %lu\n", WELLRNG512());
        }
    
        return 0;
    }
    

    That should fix your problems.