ISAAC 随机数生成器
/** ------------------------------------------------------------------------------ isaacRand.js: By Josh Weinstein, based on Rand.java: By Bob Jenkins. My random number generator, ISAAC. rand.init() -- initialize rand.val() -- get a random value MODIFIED: 960327: Creation (addition of randinit, really) 970719: use context, not global variables, for internal state 980224: Translate to Java 20120820: Translate to Javascript ------------------------------------------------------------------------------ */ Rand = (function () { /* final static int */ var SIZEL = 8; /* log of size of rsl[] and mem[] */ var SIZE = 1<<SIZEL; /* size of rsl[] and mem[] */ var MASK = (SIZE-1)<<2; /* for pseudorandom lookup */ /* public */ var count; /* count through the results in rsl[] */ var rsl = []; /* the results given to the user */ /* private */ var mem = []; /* the internal state */ var a = 0; /* accumulator */ var b = 0; /* the last result */ var c = 0; /* counter, guarantees cycle is at least 2^^40 */ function Rand(seed) { var that = this; this.count = 0; /* no seed, equivalent to randinit(ctx,FALSE) in C */ function start_Rand() { mem = new Array(SIZE); that.rsl = rsl = new Array(SIZE); that.Init(false); } /* equivalent to randinit(ctx, TRUE) after putting seed in randctx in C */ function start_seed_Rand(seed) { mem = new Array(SIZE); that.rsl = rsl = new Array(SIZE); for (var i=0; i<seed.length; ++i) { rsl[i] = seed[i]; } that.Init(true); } if (seed) { start_seed_Rand(this,seed); } else { start_Rand(this); } console.log(this.count, this.rsl[0], this.rsl[0] === rsl[0]); } /* Generate 256 results. This is a fast (not small) implementation. */ /* public final void */ function Isaac() { /* int */ var i, j, x, y; if (this.rsl && typeof this.rsl[0] === "number") rsl = this.rsl; b += ++c; for (i=0, j=SIZE/2; i<SIZE/2;) { x = mem[i]; a ^= a<<13; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a>>>6; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a<<2; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a>>>16; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; } for (j=0; j<SIZE/2;) { x = mem[i]; a ^= a<<13; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a>>>6; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a<<2; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; x = mem[i]; a ^= a>>>16; a += mem[j++]; mem[i] = y = mem[(x&MASK)>>2] + a + b; rsl[i++] = b = mem[((y>>SIZEL)&MASK)>>2] + x; } } /* initialize, or reinitialize, this instance of rand */ /* public final void */ function Init(/* boolean */ flag) { var i; var a,b,c,d,e,f,g,h; a=b=c=d=e=f=g=h=0x9e3779b9; /* the golden ratio */ for (i=0; i<4; ++i) { 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; } for (i=0; i<SIZE; i+=8) { /* fill in mem[] with messy stuff */ if (flag) { a+=rsl[i ]; b+=rsl[i+1]; c+=rsl[i+2]; d+=rsl[i+3]; e+=rsl[i+4]; f+=rsl[i+5]; g+=rsl[i+6]; h+=rsl[i+7]; } 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; mem[i ]=a; mem[i+1]=b; mem[i+2]=c; mem[i+3]=d; mem[i+4]=e; mem[i+5]=f; mem[i+6]=g; mem[i+7]=h; } if (flag) { /* second pass makes all of seed affect all of mem */ for (i=0; i<SIZE; i+=8) { a+=mem[i ]; b+=mem[i+1]; c+=mem[i+2]; d+=mem[i+3]; e+=mem[i+4]; f+=mem[i+5]; g+=mem[i+6]; h+=mem[i+7]; 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; mem[i ]=a; mem[i+1]=b; mem[i+2]=c; mem[i+3]=d; mem[i+4]=e; mem[i+5]=f; mem[i+6]=g; mem[i+7]=h; } } this.Isaac(); this.count = count = SIZE; } /* Call rand.val() to get a random value */ /* public final int */ function val() { if (0 == this.count--) { this.Isaac(); this.count = SIZE-1; } return this.rsl[this.count]; } /* public static void */ function main(/* String[] */ args) { var seed = new Array(256); // int[256]; /* Rand */ x = new Rand(seed); for (var i=0; i<2; ++i) { x.Isaac(); for (var j=0; j<Rand.SIZE; ++j) { /* String z = Integer.toHexString(x.rsl[j]); */ var z = x.get(j).toString(16); while (z.length < 8) z = "0"+z; console.log(z); if ((j&7)==7) console.log(""); } } } //} /* public */ Rand.prototype = { Isaac: Isaac, Init: Init, val: val, get: function(j) { return this.rsl[j]; }, cloned: function() { return this.rsl.slice() }, SIZE:SIZE } /* public static */ Rand.main = main; Rand.SIZE=SIZE; return Rand; })();