function Random() {
/*

If called with "new" (hence the leading upper case), returns a new Random
object. Otherwise, does nothing useful and returns undefined.

May be called with any number of arguments of any kind.

In order to achieve repeatable output, use only constant arguments, like
new Random('Any arbitrary fixed string will give a fixed sequence') or
new Random('Any arbitrary fixed string', ' will give', ' a fixed sequence')
or simply new Random(''), or new Random(0). Both new Random('foo', 'bar')
and new Random('bar', 'foo') will provide repeatable output, but not the
same repeatable output.

Plain new Random(), on the other hand, will not produce repeatable
output, since it is converted internally into new Random(new Date())
for convenience in the more usual case where one does *not* want to be
able to predict output. One may, however, save the state with the getState
method and reset it to the saved value with setState.

The pseudo-random number generator is George Marsaglia's latest version
of his KISS family of PRNGs, published with the mention "You are welcome
to use [...] and perhaps try assessing the randomness yourself" 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.

It also has more possible states than there are legal Version 4 UUIDs,
which should make accidental collisions quite unlikely provided one
seeds in a truly random way.

*/

  var x = 123456789;
  var y = 362436069;
  var z =  21288629;
  var w =  14921776;
  var c =         0;

  this.randomUInt32 = 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 randomUInt32

  this.random = function() {
/*
    No arguments, returns a fraction in [0 .. 1) with 53 significant bits

    Compatible with Math.random, but much safer - longer period, better
    performance in tests (it passes BigCrush), far more control.

*/
    return this.randomUInt32() * Math.pow(2, -32) +
      (this.randomUInt32() >>> 11) * Math.pow(2, -53);
  } // end of method random

  var hash = 31415; // used to hash successive characters in the seeds

  this.addNoise = function() {
/*
    Any number of arguments of any kind.

    There is no point in using this function if one wants to obtain
    a controlled and repeatable sequence of outputs.

    The purpose is on the contrary to approximate *true* randomness,
    by calling this function frequently in an unpredictable way.
    
    It should be called either with no argument at all or a new Date()
    argument (the former implicitely converts to the latter), or in
    event handlers with the DOM Event object passed as argument, which
    is then exploited for its inherent randomness.
    
    Any other arguments may be used as well, e.g. document.location.href
    or window width and height obtained by whatever method is
    appropriate or even cookies, but it doesn't make much sense to use
    them *repeatedly*, they won't add significant entropy more than once.

*/

    var gotEntropy = false; // becomes true in case of Date or DOM Event
                            // objects

    var seed = ''; // a String, which means that '+' means concatenation
    var i, arg, prop;

    if (arguments.length === 0) {
      this.addNoise(new Date()); // If no argument at all,
                                 // assume current time
    }

    for (i = 0; i < arguments.length; i++) {
      arg = arguments[i];

      if (arg instanceof Date) {
        seed += +arg; // concatenate the numerical value, i.e., milliseconds
        gotEntropy = true;
      } else if ((typeof Event != 'undefined') && (arg instanceof Event)) {
        for (prop in arg) {
          seed += arg[prop]; // concatenate all the properties
        }
        gotEntropy = true;
      } else {
        seed += arg; // simply concatenate any other arguments
      }
    } // end of loop over arguments

    for (i = seed.length - 1; i >= 0; i--) {
      // Hash the successive character codes of the seed string in a
      // UInt32, using a Lehmer-like hash method

      hash = (hash + seed.charCodeAt(i)) * 69069 >>> 0;

      // Each round alters one of the main variables in turn
      // c contains only one bit which will be extracted from z later

      switch (i % 4) {
        case 0:
          x ^= hash;
          break;
        case 1:
          y ^= hash;
          break;
        case 2:
          z ^= hash;
          break;
        case 3:
          w ^= hash;
          break;
      }
    } // end of loop over seed characters

/*

  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++;
    }

/*
  Increment an "entropy" counter if one of the arguments is a Date or
  an Event object. That has to happen at least 128 times for the UUID
  function to accept to return a usable value.

  No claim is make that this estimate of entropy is anywhere close to the
  truth, only that it is quite unlikely that the true value is *lower*,
  provided that the 128 calls do not occur in too rapid succession.

  It is of course possible to fool that mechanism, e.g, by calling
  addNoise() in a simple for (...) loop, or Date objects constructed with
  arguments. Don't, except for tests. The provided mechanism is there
  for your protection against two users ever generating the same UUID,
  which is the point of UUIDs. If you choose to ignore it, your IDs have
  less chance of beeing unique, and should not be called UUIDs.
*/
    if (gotEntropy) {
      entropy++;
    }
  } // end of method addNoise

  var entropy = 0;

  this.uuid = function() {
/*
     No arguments.

     Returns either a RFC 4122 Version 4 (truly-random or pseudo-random)
     UUID, or null if there is not enough entropy.

     Ex: 796483d9-f657-41c0-b4c2-9e0774d244fc
                            ^
                            always 8, 9, a or b
                            means "Leach-Salz variant, RFC 4122"
                       ^
                       always 4
                       means "random or pseudo-random version"

    Cf. http://www.faqs.org/rfcs/rfc4122.html

*/

    if (entropy < 128) {
      return null;
    }

    function normalHex(number) {
      number >>>= 0;
      var literal = number.toString(16);
        while (literal.length < 8) {
          literal = '0' + literal;
        }
        return literal;
    } // end of local function normalHex

    var id = (
      normalHex(this.randomUInt32())
    + normalHex(this.randomUInt32() & 0xffff0fff | 0x00004000) // type 4
    + normalHex(this.randomUInt32() & 0x3fffffff | 0x80000000) // rfc 4122
    + normalHex(this.randomUInt32())
    );

    return id.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/,
      "$1-$2-$3-$4-$5");
  } // end of method uuid

  this.getState = function() {
    // No arguments, returns a state which can be used for replays

    return {
      x: x,
      y: y,
      z: z,
      w: w,
      c: c,
      hash: hash
    };
  } // end of method getState

  this.setState = function(state) {
    // Resets the state of the generator to a value saved by getState()

    x = state.x;
    y = state.y;
    z = state.z,
    w = state.w;
    c = state.c;
    hash = state.hash;
    entropy = 0;
  } // end of method setState

// Initialisation
  this.addNoise.apply(this, arguments);
  
} // end of Random constructor

