Permalink
Browse files

Release 1.0.1

  • Loading branch information...
0 parents commit f605f491d13d62a13a2a8b5bc206b2814aa28048 @ForbesLindesay committed Nov 23, 2012
Showing with 229 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. 0 History.md
  3. +36 −0 Readme.md
  4. +13 −0 component.json
  5. +163 −0 index.js
  6. +15 −0 package.json
@@ -0,0 +1,2 @@
+components
+build
No changes.
@@ -0,0 +1,36 @@
+
+# seed-random
+
+ Generate random numbers with a seed, useful for reproducible tests
+
+## Installation
+
+ $ component install ForbesLindesay/seed-random
+
+ $ npm install seed-random
+
+## API
+
+ ```javascript
+ var seed = require('seed-random');
+
+ var trueRandomA = seed();
+ var trueRandomB = seed();
+ trueRandomA() != trueRandomB(); //almost always true
+
+ var fakeRandomA = seed('foo');
+ var fakeRandomB = seed('foo');
+ fakeRandomA() == fakeRandomB(); //always true
+
+ seed('foo', true);//over-ride global Math.random
+ var numA = Math.random();
+ seed('foo', true);
+ var numB = Math.random();
+ numA == numB;//always true
+
+ seed(undefined, true);//reset to default Math.random
+ ```
+
+## License
+
+ MIT
@@ -0,0 +1,13 @@
+{
+ "name": "seed-random",
+ "repo": "ForbesLindesay/seed-random",
+ "description": "Generate random numbers with a seed, useful for reproducible tests",
+ "version": "1.0.1",
+ "keywords": [],
+ "dependencies": {},
+ "development": {},
+ "license": "MIT",
+ "scripts": [
+ "index.js"
+ ]
+}
163 index.js
@@ -0,0 +1,163 @@
+var width = 256;// each RC4 output is 0 <= x < 256
+var chunks = 6;// at least six RC4 outputs for each double
+var significance = 52;// there are 52 significant digits in a double
+
+var overflow, startdenom; //numbers
+
+
+var oldRandom = Math.random;
+//
+// seedrandom()
+// This is the seedrandom function described above.
+//
+module.exports = function seedrandom(seed, overRideGlobal) {
+ if (!seed) {
+ if (overRideGlobal) {
+ Math.random = oldRandom;
+ }
+ return oldRandom;
+ }
+ var key = [];
+ var arc4;
+
+ // Flatten the seed string or build one from local entropy if needed.
+ seed = mixkey(flatten(seed, 3), key);
+
+ // Use the seed to initialize an ARC4 generator.
+ arc4 = new ARC4(key);
+
+ // Override Math.random
+
+ // This function returns a random double in [0, 1) that contains
+ // randomness in every bit of the mantissa of the IEEE 754 value.
+
+ function random() { // Closure to return a random double:
+ var n = arc4.g(chunks); // Start with a numerator n < 2 ^ 48
+ var d = startdenom; // and denominator d = 2 ^ 48.
+ var 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).
+ }
+ random.seed = seed;
+ if (overRideGlobal) {
+ Math['random'] = random;
+ }
+
+ // Return the seed that was used
+ return random;
+};
+
+//
+// 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, u, me = this, keylen = key.length;
+ var i = 0, j = me.i = me.j = me.m = 0;
+ me.S = [];
+ me.c = [];
+
+ // The empty key [] is treated as [0].
+ if (!keylen) { key = [keylen++]; }
+
+ // Set up S using the standard key scheduling algorithm.
+ while (i < width) { me.S[i] = i++; }
+ for (i = 0; i < width; i++) {
+ t = me.S[i];
+ j = lowbits(j + t + key[i % keylen]);
+ u = me.S[j];
+ me.S[i] = u;
+ me.S[j] = t;
+ }
+
+ // The "g" method returns the next (count) outputs as one number.
+ me.g = function getnext(count) {
+ var s = me.S;
+ var i = lowbits(me.i + 1); var t = s[i];
+ var j = lowbits(me.j + t); var u = s[j];
+ s[i] = u;
+ s[j] = t;
+ var r = s[lowbits(t + u)];
+ while (--count) {
+ i = lowbits(i + 1); t = s[i];
+ j = lowbits(j + t); u = s[j];
+ s[i] = u;
+ s[j] = t;
+ r = r * width + s[lowbits(t + u)];
+ }
+ me.i = i;
+ me.j = j;
+ return r;
+ };
+ // For robust unpredictability discard an initial batch of values.
+ // See http://www.rsa.com/rsalabs/node.asp?id=2009
+ me.g(width);
+}
+
+//
+// flatten()
+// Converts an object tree to nested arrays of strings.
+//
+/** @param {Object=} result
+ * @param {string=} prop
+ * @param {string=} typ */
+function flatten(obj, depth, result, prop, typ) {
+ result = [];
+ typ = typeof(obj);
+ if (depth && typ == 'object') {
+ for (prop in obj) {
+ if (prop.indexOf('S') < 5) { // Avoid FF3 bug (local/sessionStorage)
+ try { result.push(flatten(obj[prop], depth - 1)); } catch (e) {}
+ }
+ }
+ }
+ return (result.length ? result : obj + (typ != 'string' ? '\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.
+//
+/** @param {number=} smear
+ * @param {number=} j */
+function mixkey(seed, key, smear, j) {
+ seed += ''; // Ensure the seed is a string
+ smear = 0;
+ for (j = 0; j < seed.length; j++) {
+ key[lowbits(j)] =
+ lowbits((smear ^= key[lowbits(j)] * 19) + seed.charCodeAt(j));
+ }
+ seed = '';
+ for (j in key) { seed += String.fromCharCode(key[j]); }
+ return seed;
+}
+
+//
+// lowbits()
+// A quick "n mod width" for width a power of 2.
+//
+function lowbits(n) { return n & (width - 1); }
+
+//
+// The following constants are related to IEEE 754 limits.
+//
+startdenom = Math.pow(width, chunks);
+significance = Math.pow(2, significance);
+overflow = significance * 2;
@@ -0,0 +1,15 @@
+{
+ "name": "seed-random",
+ "version": "1.0.1",
+ "description": "Generate random numbers with a seed, useful for reproducible tests",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/ForbesLindesay/seed-random.git"
+ },
+ "author": "",
+ "license": "MIT"
+}

0 comments on commit f605f49

Please sign in to comment.