Created
August 20, 2012 10:19
-
-
Save josher19/3402885 to your computer and use it in GitHub Desktop.
ISAAC random number generator
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
------------------------------------------------------------------------------ | |
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; | |
})(); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment