Skip to content

Instantly share code, notes, and snippets.

@josher19
Created August 20, 2012 10:19
Show Gist options
  • Save josher19/3402885 to your computer and use it in GitHub Desktop.
Save josher19/3402885 to your computer and use it in GitHub Desktop.
ISAAC random number generator
/**
------------------------------------------------------------------------------
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