(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
);