mirror of
https://github.com/meteor/meteor.git
synced 2026-05-02 03:01:46 -04:00
141 lines
3.6 KiB
JavaScript
141 lines
3.6 KiB
JavaScript
(function() {
|
|
|
|
Random = {};
|
|
|
|
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript
|
|
// for a full discussion and Alea implementation.
|
|
Random._Alea = function () {
|
|
function Mash() {
|
|
var n = 0xefc8249d;
|
|
|
|
var mash = function(data) {
|
|
data = data.toString();
|
|
for (var i = 0; i < data.length; i++) {
|
|
n += data.charCodeAt(i);
|
|
var h = 0.02519603282416938 * n;
|
|
n = h >>> 0;
|
|
h -= n;
|
|
h *= n;
|
|
n = h >>> 0;
|
|
h -= n;
|
|
n += h * 0x100000000; // 2^32
|
|
}
|
|
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32
|
|
};
|
|
|
|
mash.version = 'Mash 0.9';
|
|
return mash;
|
|
}
|
|
|
|
return (function (args) {
|
|
var s0 = 0;
|
|
var s1 = 0;
|
|
var s2 = 0;
|
|
var c = 1;
|
|
|
|
if (args.length == 0) {
|
|
args = [+new Date];
|
|
}
|
|
var mash = Mash();
|
|
s0 = mash(' ');
|
|
s1 = mash(' ');
|
|
s2 = mash(' ');
|
|
|
|
for (var i = 0; i < args.length; i++) {
|
|
s0 -= mash(args[i]);
|
|
if (s0 < 0) {
|
|
s0 += 1;
|
|
}
|
|
s1 -= mash(args[i]);
|
|
if (s1 < 0) {
|
|
s1 += 1;
|
|
}
|
|
s2 -= mash(args[i]);
|
|
if (s2 < 0) {
|
|
s2 += 1;
|
|
}
|
|
}
|
|
mash = null;
|
|
|
|
var random = function() {
|
|
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32
|
|
s0 = s1;
|
|
s1 = s2;
|
|
return s2 = t - (c = t | 0);
|
|
};
|
|
random.uint32 = function() {
|
|
return random() * 0x100000000; // 2^32
|
|
};
|
|
random.fract53 = function() {
|
|
return random() +
|
|
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53
|
|
};
|
|
random.version = 'Alea 0.9';
|
|
random.args = args;
|
|
return random;
|
|
|
|
} (Array.prototype.slice.call(arguments)));
|
|
};
|
|
|
|
// instantiate RNG. Heuristically collect entropy from various sources
|
|
|
|
// client sources
|
|
var height = (typeof window !== 'undefined' && window.innerHeight) ||
|
|
(typeof document !== 'undefined'
|
|
&& document.documentElement
|
|
&& document.documentElement.clientHeight) ||
|
|
(typeof document !== 'undefined'
|
|
&& document.body
|
|
&& document.body.clientHeight) ||
|
|
1;
|
|
|
|
var width = (typeof window !== 'undefined' && window.innerWidth) ||
|
|
(typeof document !== 'undefined'
|
|
&& document.documentElement
|
|
&& document.documentElement.clientWidth) ||
|
|
(typeof document !== 'undefined'
|
|
&& document.body
|
|
&& document.body.clientWidth) ||
|
|
1;
|
|
|
|
var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || "";
|
|
|
|
// server sources
|
|
var pid = (typeof process !== 'undefined' && process.pid) || 1;
|
|
|
|
// XXX On the server, use the crypto module (OpenSSL) instead of this PRNG.
|
|
// (Make Random.fraction be generated from Random.hexString instead of the
|
|
// other way around, and generate Random.hexString from crypto.randomBytes.)
|
|
Random.fraction = new Random._Alea([
|
|
new Date(), height, width, agent, pid, Math.random()]);
|
|
|
|
Random.choice = function (arrayOrString) {
|
|
var index = Math.floor(Random.fraction() * arrayOrString.length);
|
|
if (typeof arrayOrString === "string")
|
|
return arrayOrString.substr(index, 1);
|
|
else
|
|
return arrayOrString[index];
|
|
};
|
|
|
|
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz";
|
|
Random.id = function() {
|
|
var digits = [];
|
|
// Length of 17 preserves around 96 bits of entropy, which is the
|
|
// amount of state in our PRNG
|
|
for (var i = 0; i < 17; i++) {
|
|
digits[i] = Random.choice(UNMISTAKABLE_CHARS);
|
|
}
|
|
return digits.join("");
|
|
};
|
|
|
|
var HEX_DIGITS = "0123456789abcdef";
|
|
Random.hexString = function (digits) {
|
|
var hexDigits = [];
|
|
for (var i = 0; i < digits; ++i) {
|
|
hexDigits.push(Random.choice("0123456789abcdef"));
|
|
}
|
|
return hexDigits.join('');
|
|
};
|
|
|
|
})();
|