Thread: Multiply with carry RNG by George Marsaglia

  1. #1
    Registered User
    Join Date
    Sep 2018
    Posts
    1

    Post Multiply with carry RNG by George Marsaglia

    Greetings. Hoping someone here is familiar with this RNG. I couldn't believe how deep the rabbit whole went when I started looking into RNGs. I thought the one that comes with the compiler would be ok, but after some research, it seems that it is inadequate. Anyhow, I stumbled upon this one and was happy to see that it worked after merely copying and pasting into my main.c file in Xcode 9.4.1. unlike about 3-4 others that did not. I have very little experience in C so this might be simple, but I don't know how to manipulate the RN it generates without running into problems. Here's the code:

    Code:
     
    // C99 Complementary Multiply With Carry generator
    #include <stdint.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    // CMWC working parts
    #define CMWC_CYCLE 4096// as Marsaglia recommends
    #define CMWC_C_MAX 809430660// as Marsaglia recommends
    struct cmwc_state {
    uint32_t Q[CMWC_CYCLE];
    uint32_t c;    // must be limited with CMWC_C_MAX
    unsigned i;
    };
    
    
    // Make 32 bit random number (some systems use 16 bit RAND_MAX [Visual C 2012 uses 15 bits!])
    uint32_t rand32(void)
    {
        uint32_t result = rand();
        return result << 16 | rand();
    }
    
    
    // Init the state with seed
    void initCMWC(struct cmwc_state *state, unsigned int seed)
    {
        srand(seed);
        for (int i = 0; i < CMWC_CYCLE; i++)
            state->Q[i] = rand32();
        do
            state->c = rand32();
        while (state->c >= CMWC_C_MAX);
        state->i = CMWC_CYCLE - 1;
    }
    
    
    // CMWC engine
    uint32_t randCMWC(structcmwc_state *state)  //EDITED parameter *state was missing
    {
    uint64_tconst a = 18782; // as Marsaglia recommends
    uint32_tconst m = 0xfffffffe; // as Marsaglia recommends
    uint64_t t;
    uint32_t x;
    
        state->i = (state->i + 1) & (CMWC_CYCLE - 1);
        t = a * state->Q[state->i] + state->c;
    /* Let c = t / 0xfffffff, x = t mod 0xffffffff */
        state->c = t >> 32;
        x = t + state->c;
        if (x < state->c) {
            x++;
            state->c++;
        }
        return state->Q[state->i] = m - x;
    }
    
    
    int main()
    {
        struct cmwc_state cmwc;
        unsigned int seed = time(NULL);
        initCMWC(&cmwc, seed);
    printf("Random CMWC: %u\n", randCMWC(&cmwc));
    }
    I kinda understand the last line

    Code:
    printf("Random CMWC: %u\n", randCMWC(&cmwc));


    where %u is being used to print the unsigned random integer. But I'm not clear how. I see in the previous line it's being generated with a time seed using then the result is a pointer (I believe), but the program as a whole is way above my pay grade. I have spent many hours trying to get a grip on pointer and memory locations, which I understand, but not with using the parentheses and such. Anyway, the bottom line is that I only really want to generate a series of random numbers between 0 and 107 that are all different. Meaning, that once that number is selected, the RNG can't choose that one again.

    After playing with the main() of this program for an extended period of time I have determined that even trying to print another random number comes out different because its being seeded by a different time integer again. Shows you how little c I know. And one last very important thing I would like to add is that I am not beholden to this particular RNG. If anybody know a better one that that I can cut and paste that would be easier for me to understand I am open to the idea.

  2. #2
    Registered User Sir Galahad's Avatar
    Join Date
    Nov 2016
    Location
    The Round Table
    Posts
    277
    You don't need to modify the generator. Just make an array containing the values 0 to 107 and then shuffle the elements using an algorithm like Fisher-Yates.
    Last edited by Sir Galahad; 09-14-2018 at 06:17 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Is George correct?
    By std10093 in forum General Discussions
    Replies: 16
    Last Post: 02-15-2014, 12:27 PM
  2. generic add with carry
    By Sebastiani in forum C++ Programming
    Replies: 20
    Last Post: 11-10-2007, 06:54 PM
  3. George and Alice
    By Korhedron in forum C++ Programming
    Replies: 2
    Last Post: 09-27-2003, 12:31 PM
  4. Is it just me or does Hayao Miyazaki look a lot a lot like George Lucas
    By Scourfish in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 04-16-2003, 06:32 AM
  5. Using carry bits
    By wildman6801 in forum C Programming
    Replies: 1
    Last Post: 02-13-2002, 12:52 PM

Tags for this Thread