# all files / random-seed/ index.js

100% Statements 101/101
100% Branches 18/18
100% Functions 20/20
100% Lines 93/93

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    263
    264
    265
    266
    267
    268
    269

    1

    64
    64
    15696
    15666
    15666
    85245
    85245
    85245
    85245
    85245
    85245
    85245
    85245

    15666

    30

    64

    1
    64
    64
    64
    64
    64
    64
    64
    64

    64

    3072
    64

    53286
    1130

    53286

    64

    26643
    64

    900
    900
    900
    4500

    900
    64

    1
    1
    1
    48
    48
    22

    64

    19
    19
    19

    64

    18
    18

    231

    11088
    11088
    5570

    64

    16
    5

    16
    12
    23
    1

    22

    16
    16
    64

    1
    1
    1

    1
    64

    31

    1440

    30

    64

    1
    64

    8
    64

    5000
    64

    7000
    64

    3000
    64

    3000
    64

    1

    64

    1
     /*
     * random-seed
     * https://github.com/skratchdot/random-seed
     *
     * This code was originally written by Steve Gibson and can be found here:
     *
     * https://www.grc.com/otg/uheprng.htm
     *
     * It was slightly modified for use in node, to pass jshint, and a few additional
     * helper functions were added.
     *
     * Copyright (c) 2013 skratchdot
     * Dual Licensed under the MIT license and the original GRC copyright/license
     * included below.
     */
    /*	============================================================================
    									Gibson Research Corporation
    				UHEPRNG - Ultra High Entropy Pseudo-Random Number Generator
    	============================================================================
    	LICENSE AND COPYRIGHT:  THIS CODE IS HEREBY RELEASED INTO THE PUBLIC DOMAIN
    	Gibson Research Corporation releases and disclaims ALL RIGHTS AND TITLE IN
    	THIS CODE OR ANY DERIVATIVES. Anyone may be freely use it for any purpose.
    	============================================================================
    	This is GRC's cryptographically strong PRNG (pseudo-random number generator)
    	for JavaScript. It is driven by 1536 bits of entropy, stored in an array of
    	48, 32-bit JavaScript variables.  Since many applications of this generator,
    	including ours with the "Off The Grid" Latin Square generator, may require
    	the deteriministic re-generation of a sequence of PRNs, this PRNG's initial
    	entropic state can be read and written as a static whole, and incrementally
    	evolved by pouring new source entropy into the generator's internal state.
    	----------------------------------------------------------------------------
    	ENDLESS THANKS are due Johannes Baagoe for his careful development of highly
    	robust JavaScript implementations of JS PRNGs.  This work was based upon his
    	JavaScript "Alea" PRNG which is based upon the extremely robust Multiply-
    	With-Carry (MWC) PRNG invented by George Marsaglia. MWC Algorithm References:
    	http://www.GRC.com/otg/Marsaglia_PRNGs.pdf
    	http://www.GRC.com/otg/Marsaglia_MWC_Generators.pdf
    	----------------------------------------------------------------------------
    	The quality of this algorithm's pseudo-random numbers have been verified by
    	multiple independent researchers. It handily passes the fermilab.ch tests as
    	well as the "diehard" and "dieharder" test suites.  For individuals wishing
    	to further verify the quality of this algorithm's pseudo-random numbers, a
    	256-megabyte file of this algorithm's output may be downloaded from GRC.com,
    	and a Microsoft Windows scripting host (WSH) version of this algorithm may be
    	downloaded and run from the Windows command prompt to generate unique files
    	of any size:
    	The Fermilab "ENT" tests: http://fourmilab.ch/random/
    	The 256-megabyte sample PRN file at GRC: https://www.GRC.com/otg/uheprng.bin
    	The Windows scripting host version: https://www.GRC.com/otg/wsh-uheprng.js
    	----------------------------------------------------------------------------
    	Qualifying MWC multipliers are: 187884, 686118, 898134, 1104375, 1250205,
    	1460910 and 1768863. (We use the largest one that's < 2^21)
    	============================================================================ */
    'use strict';
    var stringify = require('json-stringify-safe');

    /*	============================================================================
    This is based upon Johannes Baagoe's carefully designed and efficient hash
    function for use with JavaScript.  It has a proven "avalanche" effect such
    that every bit of the input affects every bit of the output 50% of the time,
    which is good.	See: http://baagoe.com/en/RandomMusings/hash/avalanche.xhtml
    ============================================================================
    */
    var Mash = function () {
    	var n = 0xefc8249d;
    	var mash = function (data) {
    		if (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
    		} else {
    			n = 0xefc8249d;
    		}
    	};
    	return mash;
    };

    var uheprng = function (seed) {
    	return (function () {
    		var o = 48; // set the 'order' number of ENTROPY-holding 32-bit values
    		var c = 1; // init the 'carry' used by the multiply-with-carry (MWC) algorithm
    		var p = o; // init the 'phase' (max-1) of the intermediate variable pointer
    		var s = new Array(o); // declare our intermediate variables array
    		var i; // general purpose local
    		var j; // general purpose local
    		var k = 0; // general purpose local

    		// when our "uheprng" is initially invoked our PRNG state is initialized from the
    		// browser's own local PRNG. This is okay since although its generator might not
    		// be wonderful, it's useful for establishing large startup entropy for our usage.
    		var mash = new Mash(); // get a pointer to our high-performance "Mash" hash

    		// fill the array with initial mash hash values
    		for (i = 0; i < o; i++) {
    			s[i] = mash(Math.random());
    		}

    		// this PRIVATE (internal access only) function is the heart of the multiply-with-carry
    		// (MWC) PRNG algorithm. When called it returns a pseudo-random number in the form of a
    		// 32-bit JavaScript fraction (0.0 to <1.0) it is a PRIVATE function used by the default
    		// [0-1] return function, and by the random 'string(n)' function which returns 'n'
    		// characters from 33 to 126.
    		var rawprng = function () {
    			if (++p >= o) {
    				p = 0;
    			}
    			var t = 1768863 * s[p] + c * 2.3283064365386963e-10; // 2^-32
    			return s[p] = t - (c = t | 0);
    		};

    		// this EXPORTED function is the default function returned by this library.
    		// The values returned are integers in the range from 0 to range-1. We first
    		// obtain two 32-bit fractions (from rawprng) to synthesize a single high
    		// resolution 53-bit prng (0 to <1), then we multiply this by the caller's
    		// "range" param and take the "floor" to return a equally probable integer.
    		var random = function (range) {
    			return Math.floor(range * (rawprng() + (rawprng() * 0x200000 | 0) * 1.1102230246251565e-16)); // 2^-53
    		};

    		// this EXPORTED function 'string(n)' returns a pseudo-random string of
    		// 'n' printable characters ranging from chr(33) to chr(126) inclusive.
    		random.string = function (count) {
    			var i;
    			var s = '';
    			for (i = 0; i < count; i++) {
    				s += String.fromCharCode(33 + random(94));
    			}
    			return s;
    		};

    		// this PRIVATE "hash" function is used to evolve the generator's internal
    		// entropy state. It is also called by the EXPORTED addEntropy() function
    		// which is used to pour entropy into the PRNG.
    		var hash = function () {
    			var args = Array.prototype.slice.call(arguments);
    			for (i = 0; i < args.length; i++) {
    				for (j = 0; j < o; j++) {
    					s[j] -= mash(args[i]);
    					if (s[j] < 0) {
    						s[j] += 1;
    					}
    				}
    			}
    		};

    		// this EXPORTED "clean string" function removes leading and trailing spaces and non-printing
    		// control characters, including any embedded carriage-return (CR) and line-feed (LF) characters,
    		// from any string it is handed. this is also used by the 'hashstring' function (below) to help
    		// users always obtain the same EFFECTIVE uheprng seeding key.
    		random.cleanString = function (inStr) {
    			inStr = inStr.replace(/(^\s*)|(\s*$)/gi, ''); // remove any/all leading spaces
    			inStr = inStr.replace(/[\x00-\x1F]/gi, ''); // remove any/all control characters
    			inStr = inStr.replace(/\n /, '\n'); // remove any/all trailing spaces
    			return inStr; // return the cleaned up result
    		};

    		// this EXPORTED "hash string" function hashes the provided character string after first removing
    		// any leading or trailing spaces and ignoring any embedded carriage returns (CR) or Line Feeds (LF)
    		random.hashString = function (inStr) {
    			inStr = random.cleanString(inStr);
    			mash(inStr); // use the string to evolve the 'mash' state
    			for (i = 0; i < inStr.length; i++) { // scan through the characters in our string
    				k = inStr.charCodeAt(i); // get the character code at the location
    				for (j = 0; j < o; j++) { //	"mash" it into the UHEPRNG state
    					s[j] -= mash(k);
    					if (s[j] < 0) {
    						s[j] += 1;
    					}
    				}
    			}
    		};

    		// this EXPORTED function allows you to seed the random generator.
    		random.seed = function (seed) {
    			if (typeof seed === 'undefined' || seed === null) {
    				seed = Math.random();
    			}
    			if (typeof seed !== 'string') {
    				seed = stringify(seed, function (key, value) {
    					if (typeof value === 'function') {
    						return (value).toString();
    					}
    					return value;
    				});
    			}
    			random.initState();
    			random.hashString(seed);
    		};

    		// this handy exported function is used to add entropy to our uheprng at any time
    		random.addEntropy = function ( /* accept zero or more arguments */ ) {
    			var args = [];
    			for (i = 0; i < arguments.length; i++) {
    				args.push(arguments[i]);
    			}
    			hash((k++) + (new Date().getTime()) + args.join('') + Math.random());
    		};

    		// if we want to provide a deterministic startup context for our PRNG,
    		// but without directly setting the internal state variables, this allows
    		// us to initialize the mash hash and PRNG's internal state before providing
    		// some hashing input
    		random.initState = function () {
    			mash(); // pass a null arg to force mash hash to init
    			for (i = 0; i < o; i++) {
    				s[i] = mash(' '); // fill the array with initial mash hash values
    			}
    			c = 1; // init our multiply-with-carry carry
    			p = o; // init our phase
    		};

    		// we use this (optional) exported function to signal the JavaScript interpreter
    		// that we're finished using the "Mash" hash function so that it can free up the
    		// local "instance variables" is will have been maintaining.  It's not strictly
    		// necessary, of course, but it's good JavaScript citizenship.
    		random.done = function () {
    			mash = null;
    		};

    		// if we called "uheprng" with a seed value, then execute random.seed() before returning
    		if (typeof seed !== 'undefined') {
    			random.seed(seed);
    		}

    		// Returns a random integer between 0 (inclusive) and range (exclusive)
    		random.range = function (range) {
    			return random(range);
    		};

    		// Returns a random float between 0 (inclusive) and 1 (exclusive)
    		random.random = function () {
    			return random(Number.MAX_VALUE - 1) / Number.MAX_VALUE;
    		};

    		// Returns a random float between min (inclusive) and max (exclusive)
    		random.floatBetween = function (min, max) {
    			return random.random() * (max - min) + min;
    		};

    		// Returns a random integer between min (inclusive) and max (inclusive)
    		random.intBetween = function (min, max) {
    			return Math.floor(random.random() * (max - min + 1)) + min;
    		};

    		// when our main outer "uheprng" function is called, after setting up our
    		// initial variables and entropic state, we return an "instance pointer"
    		// to the internal anonymous function which can then be used to access
    		// the uheprng's various exported functions.  As with the ".done" function
    		// above, we should set the returned value to 'null' once we're finished
    		// using any of these functions.
    		return random;
    	}());
    };

    // Modification for use in node:
    uheprng.create = function (seed) {
    	return new uheprng(seed);
    };
    module.exports = uheprng;