MAIL, 2009-07-03

function Kiss2007() { /*

This is an ECMAScript implementation of George Marsaglia's latest
version of his KISS family of PRNGs, published 23 June 2007
with the mention "You are welcome to use [...]" in
http://groups.google.com/group/comp.lang.fortran/msg/6edb8ad6ec5421a5

It is deceptively simple, and yet one of the few PRNGs that pass
Pierre L'Ecuyer's UI01 BigCrush battery of tests - the Mersenne
Twister does not.

If called with "new" (hence the leading upper case), the present
constructor function returns a new object with two methods, kiss
and random, providing random UInt32s and 53-bit precision random
fractions in [0..1), respectively. Otherwise, it does nothing useful
and returns undefined.

It may be called with up to four arguments, which should be integers
between O and 4294967295. Any arguments that are not numbers (including
undefined arguments) are replaced by the current time.

var r = new Kiss2007(0, 0, 0, 0) will keep Marsaglia's original seed
values. If, then, r.kiss() is called 100 000 times (not 10 000, as a
typo in Marsaglia's post states), the last four should yield 199275006,
86473693, 2209597521, 1298124039, in agreement with the post.

*/

  var x = 123456789;
  var y = 362436069;
  var z =  21288629;
  var w =  14921776;
  var c =         0;

  this.kiss = function() {
  // No arguments, returns an integer in [0 .. 2^32 - 1]
    var t;

    x += 545925293;
    x >>>= 0;

    y ^= y << 13;
    y ^= y >>> 17;
    y ^= y << 5;

    t = z + w + c;
    z = w;
    c = t >>> 31;
    w = t & 0x7fffffff;

    return x + y + w >>> 0;
  } // end of method kiss

  this.random = function() {
/*
    No arguments, returns a fraction in [0 .. 1) with 53 significant bits.

    Compatible with Math.random, but better - longer period, excellent
    performance in tests (it passes BigCrush), more control over the seeds.
*/
    return this.kiss() * Math.pow(2, -32) +
      (this.kiss() >>> 11) * Math.pow(2, -53);
  } // end of method random

// Constructor : seed with the arguments

  for (var i =  0; i < 4; i++) {
    var arg = arguments[i];

    if (isNaN(arg)) {
      arg = +new Date();
    }

    switch (i) {
      case 0:
        x ^= arg;
        break;
      case 1:
        y ^= arg;
        break;
      case 2:
        z ^= arg;
        break;
      case 3:
        w ^= arg;
        break;
     }
   } // end loop over arguments

/*
  Make sure the state is correct according to the specifications.

  According to Professor Marsaglia :

  x can be any 32-bit integer,
  y can be any 32-bit integer not 0,
  z and w any 31-bit integers not multiples of 7559
  c can be 0 or 1.
*/
    if (y == 0) {
      y = 1;
    }

    c ^= z >>> 31;
    z &= 0x7fffffff;
    if (!(z % 7559)) {
      z++;
    }

    w &= 0x7fffffff;
      if (!(w % 7559)) {
      w++;
    }

} // end of Kiss2007 constructor


