1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
|
// ISAAC .cpp file
void IsaacRNG::Reseed(u32 seed)
{
// use the GMSimple32 RNG to fill the seeds for this RNG
GMSimple32RNG r(false);
r.Reseed(seed);
u32 seeds[256];
int i;
for(i = 0; i < 256; ++i)
seeds[i] = r();
ReseedFull(seeds);
}
//=============================================================
static inline void mix(u32& a,u32& b,u32& c,u32& d,u32& e,u32& f,u32& g,u32& h)
{
a^=b<<11; d+=a; b+=c;
b^=c>>2; e+=b; c+=d;
c^=d<<8; f+=c; d+=e;
d^=e>>16; g+=d; e+=f;
e^=f<<10; h+=e; f+=g;
f^=g>>4; a+=f; g+=h;
g^=h<<8; b+=g; h+=a;
h^=a>>9; c+=h; a+=b;
}
void IsaacRNG::ReseedFull(const u32 seeds[256])
{
aa = 0;
bb = 0;
cc = 0;
step = 0;
static const u32 GOLDENRATIO = 0x9E3779B9;
u32 a, b, c, d, e, f, g, h;
a=b=c=d=e=f=g=h=GOLDENRATIO;
// scramble the golden ratio
int i;
for(i = 0; i < 4; ++i)
mix(a,b,c,d,e,f,g,h);
// shuffle up mm
for(i = 0; i < 256; i += 8)
{
a += seeds[i ]; b += seeds[i+1]; c += seeds[i+2]; d += seeds[i+3];
e += seeds[i+4]; f += seeds[i+5]; g += seeds[i+6]; h += seeds[i+7];
mix(a,b,c,d,e,f,g,h);
mm[i ] = a; mm[i+1] = b; mm[i+2] = c; mm[i+3] = d;
mm[i+4] = e; mm[i+5] = f; mm[i+6] = g; mm[i+7] = h;
}
// do another pass to make sure the seed has full effect
for(i = 0; i < 256; i += 8)
{
a += mm[i ]; b += mm[i+1]; c += mm[i+2]; d += mm[i+3];
e += mm[i+4]; f += mm[i+5]; g += mm[i+6]; h += mm[i+7];
mix(a,b,c,d,e,f,g,h);
mm[i ] = a; mm[i+1] = b; mm[i+2] = c; mm[i+3] = d;
mm[i+4] = e; mm[i+5] = f; mm[i+6] = g; mm[i+7] = h;
}
// count and discard the first 256 numbers
// not sure why, but the original algorithm did this.. so what the hell
for(i = 0; i < 256; ++i)
Get();
}
//=======================================================
u32 IsaacRNG::Get()
{
if(!step)
{
cc += 1;
bb += cc;
}
switch(step & 3)
{
case 0: aa ^= (aa<<13); break;
case 1: aa ^= (aa>> 6); break;
case 2: aa ^= (aa<< 2); break;
case 3: aa ^= (aa>>16); break;
}
u32 x, y;
x = mm[step];
aa = mm[ step ^ 0x80] + aa;
mm[step] = y = mm[(x>>2) & 0xFF] + aa + bb;
bb = mm[(y>>10) & 0xFF] + x;
++step; // wraps at 8 bits
return bb;
}
|