/* * My implementation of Orz's test. Usage: "count5x4 20" will run the * generator defined by ranval() for 2^^20 values. * * Given a subsequence of 5 32-bit random numbers, compute the number * of bits set in each term, reduce that to 0..15 somehow, and * concatenate those 5 4-bit integers into a single 20-bit integer. * Do this for len overlapping sequences. And report the chi-square * measure of the results compared to the ideal distribution. */ #include #include #include #include #include #include typedef unsigned char u1; typedef unsigned long u4; typedef unsigned long long u8; typedef struct ranctx { u4 a; u4 b; u4 c; u4 d;} ranctx; #define rot(x,k) ((x<>(32-k))) /* xxx: place the generator you want to test in ranval() */ static u4 ranval( ranctx *x ) { u4 e = x->a; x->a = rot(x->b,15); x->b = x->c + rot(x->d, 27); x->c = x->d + x->a; x->d = e + x->b; return x->c; } static void raninit( ranctx *x, u4 seed ) { u4 i; x->a = 0xf1ea5eed; x->b = x->c = x->d = seed; for (i=0; i<20; ++i) { (void)ranval(x); } } /* count how many bits are set in a 32-bit integer, returns 0..32 */ static u4 count(u4 x) { u4 c = x; c = (c & 0x55555555) + ((c>>1 ) & 0x55555555); c = (c & 0x33333333) + ((c>>2 ) & 0x33333333); c = (c & 0x0f0f0f0f) + ((c>>4 ) & 0x0f0f0f0f); c = (c & 0x00ff00ff) + ((c>>8 ) & 0x00ff00ff); c = (c & 0x0000ffff) + ((c>>16) & 0x0000ffff); return c; } /* somehow covert 0..32 into 0..15 */ static u4 f( u4 x) { return (x>>1)&0xf; } /* (a,b,c,d,e)->(x,y) where the most common (a,b,c,d,e) have the same x */ static void g( u4 a, u4 b, u4 c, u4 d, u4 e, u4 *z) { u4 w,x,y; w = (a+(b<<4)+(c<<8))+(d<<12)+(e<<16); x = (w&0xcc)|((w&0xccc00)>>10); /* the most significant bits */ y = (w&0x333)|((w&0x33000)>>10); /* the least significant bits */ *z = y|(x<<10); } /* initialize the data collection array */ static void datainit( u8 *data) { u4 a,b,c,d,e,z; for (a=0; a<16; ++a) for (b=0; b<16; ++b) for (c=0; c<16; ++c) for (d=0; d<16; ++d) for (e=0; e<16; ++e) { g(a,b,c,d,e,&z); data[z] = 0; } } /* gather statistics on len overlapping subsequences of length 5 each */ static void gather( ranctx *r, u8 *data, u8 len) { u8 i; u4 z; u4 a=f(count(ranval(r))); u4 b=f(count(ranval(r))); u4 c=f(count(ranval(r))); u4 d=f(count(ranval(r))); u4 e=f(count(ranval(r))); for (i=0; i