#include #include #include #include /* ---------------------------------------------------------------------- By Bob Jenkins, amateur generator of random number generators, 1994 If you find a bug, you'll have to fix it yourself. Public Domain. Run chi-square tests on a random number generator rng. uni -- are values uniform; do they occur equally often gap -- are the gaps between values of the expected length run -- how long are strictly increasing subsequences? njk -- uni, but by conglomerating NJKBIT of multiple values. njg -- gap, but by conglomerating NJKBIT of multiple values. Instructions: If "get" is within "expect +- 3*sqrt(expect)", then the tests pass. Reduce ALPHA, OMEGA until the tests fail. Increase MYRUNS until the tests fail. Where does the bias come from? ---------------------------------------------------------------------- */ typedef unsigned char u1; /* u1 is unsigned, 1 byte */ typedef unsigned long int u4; /* u4 is unsigned, 4 bytes */ typedef unsigned long long u8; /* u8 is unsigned, 8 bytes */ static FILE *xx; #define ALPHA 2 /* arrays of size 2^alpha */ #define OMEGA 32 /* omega bits per value */ #define OMICRON 4 /* number of bits in values tested */ #define RSIZE ((u4)8) /* maximum run length to look for */ #define NJKBIT 0x1 /* which bit to conglomerate for njk,njg */ #define SHIFT 4 /* amount of barrelshift */ #define SIZE ((u4)1<>(32-19))) #define f(mm,x) (*(u4 *)(((u1 *)(mm))+((x)&(4*NNN-4)))) static void prng_loop(mm,rr,aa,bb) u4 *mm; /* secret memory */ u4 *rr; /* results given to the user */ u4 *aa; /* accumulator */ u4 *bb; /* the old m[SIZE-1] */ { register u4 a,b,i,x,y; a = *aa; b = *bb; for (i=0; i>NNL)) + x; } *bb = b; *aa = a; } #define prng(i,m,r,aa,bb) \ if (1) { \ if (++prngi>=NNN) {prng_loop((m),(r),(aa),(bb)); prngi=0;} \ (i) = (r)[prngi]; \ } /* ------------------------------------------------------------------ Experimental RNG -- place your RNG here Each call must fill rr[0..SIZE-1] with ALPHA-bit values. ------------------------------------------------------------------ */ #define rot(d, k) (((d<>(OMEGA-k))&WMASK)) static void rng(mm,rr,aa,bb,cc,m2,r2,aa2,bb2,ss,tt) u4 *mm; /* secret memory */ u4 *rr; /* results given to the user */ u4 *aa; /* accumulator */ u4 *bb; /* the old m[SIZE-1] */ u4 *cc; /* the old m[SIZE-2] */ u4 *m2; /* secret memory */ u4 *r2; /* results given to the user */ u4 *aa2; /* accumulator */ u4 *bb2; /* the old m[SIZE-1] */ u4 *ss; /* extra state */ u4 *tt; /* more extra state */ { register u4 a,b,c,d,x,y,z,i,j; a = *aa; b = *bb; c = *cc; d = mm[0]; for (i=0; i>13) + d; c = d ^ a; d = x + b; rr[i] = (c&0x3)|(((c>>19)&0x3)<<2); } *aa = a; *bb = b; *cc = c; mm[0] = d; } /* ------------------------------------------------------------------ cyc() assumes that the rng is a permutation, that is, the initial state is guaranteed to be repeated. cyc() relies on m, not r, so rng() needs to fill in m. ------------------------------------------------------------------ */ static int cyc( m, r, a, b, c, m2, r2, a2, b2, ss, tt, i8 ) u4 *m; /* random numbers */ u4 *r; /* random numbers */ u4 a; u4 b; u4 c; u4 *m2; u4 *r2; u4 *a2; u4 *b2; u4 *ss; u4 *tt; u8 i8; { int i; #ifdef NEVER if ((i8&1) == 1) rng(cycm,cycr,&cyca,&cycb,&cycz,m2,r2,a2,b2,ss,tt); #endif if (a != cyca) return 0; if (b != cycb) return 0; if (c != cycz) return 0; for (i=0; i>=1, ++k) if (j&1) R *= z[k]; prob[i] = R; } prob[len-1] *= (1/P); } /* Count runs of strictly decreasing sequences */ static void run( r, rl, d, dl ) u4 *r; /* random numbers */ u4 rl; /* length of r */ u8 *d; /* where to put measurements */ u4 dl; /* length of d */ { u4 i,c,x; x = rlast; c = rcount; for (i=0; i 1000) {c=0; x=r[i];} else if (x == r[i]) ; else if (x > r[i]) {++c; x=r[i];} else {if (c > dl-1) c=dl-1; ++d[c]; c=1001;} } rcount = c; rlast = x; } /* Count runs of strictly increasing sequences */ static void run2( r, rl, d, dl ) u4 *r; /* random numbers */ u4 rl; /* length of r */ u8 *d; /* where to put measurements */ u4 dl; /* length of d */ { u4 i,c,x; x = rlast2; c = rcount2; for (i=0; i 1000) {c=0; x=r[i];} else if (x == r[i]) ; else if (x < r[i]) {++c; x=r[i];} else {if (c > dl-1) c=dl-1; ++d[c]; c=1001;} } rcount2 = c; rlast2 = x; } static void rprob( prob, len) double *prob; u4 len; { u4 i,j,k; prob[0] = 1; for (i=1; i<=RSIZE; ++i) prob[i] = prob[i-1]*((double)USIZE-i)/((i+1)*((double)USIZE-1)); for (i=0; i