I need a PRNG for a simulation project, and found a resource which, given my limited but not nonexistent knowledge of PRNG's seems sound and well-informed. I'm trying to encapsulate the algorithms given in this report in a class, but for some reason I get a lot of repeated values. It might just be that the PRNG isn't as good as the report states it is, but I suspect that it's rather something in my implementation that fails.
The following code sample is given on page 3:
/* Public domain code for JKISS RNG */
// seed variables
static unsigned int x = 123456789,y = 987654321,z = 43219876,c = 6543217;
unsigned int JKISS()
{
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}
In connection with it, the report claims that
The period of JKISS is ≈2 127 = 1.7x10 38 (2 32 x (2 32 -1) x (1/2 * 4294584393 x 2 32 - 1)) and it passes all of the Dieharder tests and the complete BigCrunch test set in TestU01.
so this definitely seems good enough to me. Later in the report (page 6), it is stated
The following C code generate [sic] a random (double precision) floating point number 0 <= x < 1:
double x; x = JKISS() / 4294967296.0;
I have the following in a header file:
class JKISS : public IPRNG {
private:
// Seed variables
static unsigned int x;
static unsigned int y;
static unsigned int z;
static unsigned int c;
public:
static unsigned int randui32();
static double randdouble();
};
with the following implementation file
#include "prng.hpp"
unsigned int JKISS::x = 123456789;
unsigned int JKISS::y = 987654321;
unsigned int JKISS::z = 43219876;
unsigned int JKISS::c = 6543217;
unsigned int JKISS::randui32() {
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}
double JKISS::randdouble() {
return randui32() / 4294967296.0;
}
and the following main program
#include <iostream>
#include "prng.hpp"
int main() {
for (int i = 0; i < 10000; ++i) {
std::cout << JKISS::randdouble() << std::endl;
}
}
As you can see, I've copy-pasted most of the code.
However, when I run this, I get 68 repeated values, even though I'm just fetching 10 000 values. This suggests to me that something is wrong with my encapsulation, but I can't figure out what the problem is.
In case it matters, I'm running GCC 4.8.1 on Ubuntu 13.10 with the following specs:
Platform Info:
System: Linux (x86_64-linux-gnu)
CPU: Intel(R) Xeon(R) CPU E5410 @ 2.33GHz
WORD_SIZE: 64
Any ideas as to what could cause this are most welcome.
I get the same results as you do, but no duplicates ;p
What I mean is that if I run your program as directed I get 68 duplicates, but if I switch randdouble()
=> randui32()
there are no more duplicates, so I'll bet they were an artifact due to the precision of the printing routine.
You could try to collect the doubles in an array and compare to make 100% sure.