A
Adem24
I put the CMWC4096 PRNG of Prof. Marsaglia into a
simple C++ class. It works as intended, ie. as a 32-bit PRNG.
But my question is:
what must be changed in the code to make an LCG of it?
< fup set to sci.math.num-analysis >
file: Rand_CMWC4096.hpp
#ifndef Rand_CMWC4096_hpp
#define Rand_CMWC4096_hpp
/*******************************************************************
CMWC4096 ported to C++
For the original C code as was posted by Prof. George Marsaglia to sci.math.num-analysis see:
http://groups.google.com/group/sci.math.num-analysis/msg/2a37cb18f98210e8
It is also discussed in his paper
Random Number Generators, Journal of Modern Applied Statistical Methods, May 2003, Vol 2 No 1; 2-13
The following is just my Q&D port to C++ :
*/
#ifdef _MSC_VER
#define UINT32 unsigned long
#define UINT64 unsigned __int64
#else
/* we assume it's a std unix/linux, nothing exotic */
#define UINT32 unsigned long
#define UINT64 unsigned long long
#endif
#include <stdlib.h>
class Rand_CMWC4096
{ // 32-bit Rand, but internally uses also two 64-bit fields (a and t)
private:
#define NSEED 4096U /* don't change; or consult the paper before changing */
UINT32 Q[NSEED], c, i;
const UINT64 a;
const UINT32 r;
public:
Rand_CMWC4096() : c(362436), a(18782), r(0xfffffffe), i(NSEED - 1)
{ // initialize the RNG
// init seedtab with random values; here using the systems' ::srand() and ::rand() !!!
const UINT32 myInitialSeed = 4711;
::srand(myInitialSeed); // system RNG
UINT32 j;
for (j = 0; j < NSEED; ++j)
Q[j] = ::rand(); // system RNG
// generate rands by using and overwriting the seed tab:
srand(myInitialSeed); // this RNG
for (j = 0; j < NSEED; ++j)
rand();
}
void srand(UINT32 s)
{
c = s % a;
}
UINT32 rand(UINT64 An = 0x100000000UL)
{
i = (i + 1U) & (NSEED - 1U);
UINT64 t = UINT32(a * Q + c);
c = UINT32(t >> 32U);
UINT32 x = UINT32(t + c);
if (x < c)
{
++x;
++c;
}
if ((x + 1) == 0)
{
x = 0;
++c;
}
Q = r - x;
return UINT32(UINT64(Q) % An);
}
};
#endif
simple C++ class. It works as intended, ie. as a 32-bit PRNG.
But my question is:
what must be changed in the code to make an LCG of it?
< fup set to sci.math.num-analysis >
file: Rand_CMWC4096.hpp
#ifndef Rand_CMWC4096_hpp
#define Rand_CMWC4096_hpp
/*******************************************************************
CMWC4096 ported to C++
For the original C code as was posted by Prof. George Marsaglia to sci.math.num-analysis see:
http://groups.google.com/group/sci.math.num-analysis/msg/2a37cb18f98210e8
It is also discussed in his paper
Random Number Generators, Journal of Modern Applied Statistical Methods, May 2003, Vol 2 No 1; 2-13
The following is just my Q&D port to C++ :
*/
#ifdef _MSC_VER
#define UINT32 unsigned long
#define UINT64 unsigned __int64
#else
/* we assume it's a std unix/linux, nothing exotic */
#define UINT32 unsigned long
#define UINT64 unsigned long long
#endif
#include <stdlib.h>
class Rand_CMWC4096
{ // 32-bit Rand, but internally uses also two 64-bit fields (a and t)
private:
#define NSEED 4096U /* don't change; or consult the paper before changing */
UINT32 Q[NSEED], c, i;
const UINT64 a;
const UINT32 r;
public:
Rand_CMWC4096() : c(362436), a(18782), r(0xfffffffe), i(NSEED - 1)
{ // initialize the RNG
// init seedtab with random values; here using the systems' ::srand() and ::rand() !!!
const UINT32 myInitialSeed = 4711;
::srand(myInitialSeed); // system RNG
UINT32 j;
for (j = 0; j < NSEED; ++j)
Q[j] = ::rand(); // system RNG
// generate rands by using and overwriting the seed tab:
srand(myInitialSeed); // this RNG
for (j = 0; j < NSEED; ++j)
rand();
}
void srand(UINT32 s)
{
c = s % a;
}
UINT32 rand(UINT64 An = 0x100000000UL)
{
i = (i + 1U) & (NSEED - 1U);
UINT64 t = UINT32(a * Q + c);
c = UINT32(t >> 32U);
UINT32 x = UINT32(t + c);
if (x < c)
{
++x;
++c;
}
if ((x + 1) == 0)
{
x = 0;
++c;
}
Q = r - x;
return UINT32(UINT64(Q) % An);
}
};
#endif