(function (global, pool, math, width, chunks, digits, module, define, rngname) { // // The following constants are related to IEEE 754 limits. // var startdenom = math.pow(width, chunks), significance = math.pow(2, digits), overflow = significance * 2, mask = width - 1, nodecrypto; // // seedrandom() // This is the seedrandom function described above. // var impl = (math["seed" + rngname] = function (seed, options, callback) { var key = []; options = options == true ? { entropy: true } : options || {}; // Flatten the seed string or build one from local entropy if needed. var shortseed = mixkey( flatten( options.entropy ? [seed, tostring(pool)] : seed == null ? autoseed() : seed, 3 ), key ); // Use the seed to initialize an ARC4 generator. var arc4 = new ARC4(key); // Mix the randomness into accumulated entropy. mixkey(tostring(arc4.S), pool); // Calling convention: what to return as a function of prng, seed, is_math. return ( options.pass || callback || // If called as a method of Math (Math.seedrandom()), mutate Math.random // because that is how seedrandom.js has worked since v1.0. Otherwise, // it is a newer calling convention, so return the prng directly. function (prng, seed, is_math_call) { if (is_math_call) { math[rngname] = prng; return seed; } else return prng; } )( // This function returns a random double in [0, 1) that contains // randomness in every bit of the mantissa of the IEEE 754 value. function () { var n = arc4.g(chunks), // Start with a numerator n < 2 ^ 48 d = startdenom, // and denominator d = 2 ^ 48. x = 0; // and no 'extra last byte'. while (n < significance) { // Fill up all significant digits by n = (n + x) * width; // shifting numerator and d *= width; // denominator and generating a x = arc4.g(1); // new least-significant-byte. } while (n >= overflow) { // To avoid rounding up, before adding n /= 2; // last byte, shift everything d /= 2; // right using integer math until x >>>= 1; // we have exactly the desired bits. } return (n + x) / d; // Form the number within [0, 1). }, shortseed, "global" in options ? options.global : this == math ); }); // // ARC4 // // An ARC4 implementation. The constructor takes a key in the form of // an array of at most (width) integers that should be 0 <= x < (width). // // The g(count) method returns a pseudorandom integer that concatenates // the next (count) outputs from ARC4. Its return value is a number x // that is in the range 0 <= x < (width ^ count). // /** @constructor */ function ARC4(key) { var t, keylen = key.length, me = this, i = 0, j = (me.i = me.j = 0), s = (me.S = []); // The empty key [] is treated as [0]. if (!keylen) { key = [keylen++]; } // Set up S using the standard key scheduling algorithm. while (i < width) { s[i] = i++; } for (i = 0; i < width; i++) { s[i] = s[(j = mask & (j + key[i % keylen] + (t = s[i])))]; s[j] = t; } // The "g" method returns the next (count) outputs as one number. (me.g = function (count) { // Using instance members instead of closure state nearly doubles speed. var t, r = 0, i = me.i, j = me.j, s = me.S; while (count--) { t = s[(i = mask & (i + 1))]; r = r * width + s[mask & ((s[i] = s[(j = mask & (j + t))]) + (s[j] = t))]; } me.i = i; me.j = j; return r; // For robust unpredictability, the function call below automatically // discards an initial batch of values. This is called RC4-drop[256]. // See http://google.com/search?q=rsa+fluhrer+response&btnI })(width); } // // flatten() // Converts an object tree to nested arrays of strings. // function flatten(obj, depth) { var result = [], typ = typeof obj, prop; if (depth && typ == "object") { for (prop in obj) { try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {} } } return result.length ? result : typ == "string" ? obj : obj + "\0"; } // // mixkey() // Mixes a string seed into a key that is an array of integers, and // returns a shortened string seed that is equivalent to the result key. // function mixkey(seed, key) { var stringseed = seed + "", smear, j = 0; while (j < stringseed.length) { key[mask & j] = mask & ((smear ^= key[mask & j] * 19) + stringseed.charCodeAt(j++)); } return tostring(key); } // // autoseed() // Returns an object for autoseeding, using window.crypto if available. // /** @param {Uint8Array|Navigator=} seed */ function autoseed(seed) { try { if (nodecrypto) return tostring(nodecrypto.randomBytes(width)); global.crypto.getRandomValues((seed = new Uint8Array(width))); return tostring(seed); } catch (e) { return [ +new Date(), global, (seed = global.navigator) && seed.plugins, global.screen, tostring(pool), ]; } } // // tostring() // Converts an array of charcodes to a string // function tostring(a) { return String.fromCharCode.apply(0, a); } // // When seedrandom.js is loaded, we immediately mix a few bits // from the built-in RNG into the entropy pool. Because we do // not want to interfere with deterministic PRNG state later, // seedrandom will not call math.random on its own again after // initialization. // mixkey(math[rngname](), pool); // // Nodejs and AMD support: export the implementation as a module using // either convention. // if (module && module.exports) { module.exports = impl; try { // When in node.js, try using crypto package for autoseeding. nodecrypto = require("crypto"); } catch (ex) {} } else if (define && define.amd) { define(function () { return impl; }); } // // Node.js native crypto support. // // End anonymous scope, and pass initial values. })( this, // global window object [], // pool: entropy pool starts empty Math, // math: package containing random, pow, and seedrandom 256, // width: each RC4 output is 0 <= x < 256 6, // chunks: at least six RC4 outputs for each double 52, // digits: there are 52 significant digits in a double typeof module == "object" && module, // present in node.js typeof define == "function" && define, // present with an AMD loader "random" // rngname: name for Math.random and Math.seedrandom );