-
Notifications
You must be signed in to change notification settings - Fork 2
/
main.js
88 lines (78 loc) · 2.26 KB
/
main.js
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
const addon = require('./build/Release/addon.node');
const crypto = require('crypto');
const BUFSIZE = 1 << 17;
class PRNG {
constructor(seed) {
this.internalSeed =
(seed instanceof Buffer)? seed:
(typeof seed === 'string')?
crypto.createHash('sha512').update(seed).digest().slice(0, 32):
crypto.randomBytes(32);
this.state = addon.init(this.internalSeed);
this.buffer = Buffer.alloc(BUFSIZE);
this.fillBuffer();
}
fillBuffer() {
addon.generate(this.state, this.buffer);
this.index = 0;
}
fill(buffer) {
if (buffer.length & (128-1) === 0) {
// The buffer is a multiple of 128:
// fast-path by bringing our own buffer.
addon.generate(this.state, buffer);
} else {
let copied = this.buffer.copy(buffer, 0, this.index);
this.index += copied;
while (copied < buffer.length) {
this.fillBuffer();
let n = this.buffer.copy(buffer, copied);
copied += n;
this.index += n;
}
}
}
uint32() {
let prevIndex = this.index;
this.index += 4;
if (this.index >= BUFSIZE) {
this.fillBuffer();
prevIndex = 0;
}
return this.buffer.readUInt32LE(prevIndex);
}
// Returns a random number between 0 included and 1.
double() {
var prevIndex = this.index;
this.index += 8;
if (this.index >= BUFSIZE) {
this.fillBuffer();
prevIndex = 0;
}
var r0 = this.buffer.readUInt32LE(prevIndex);
var r1 = this.buffer.readUInt32LE(prevIndex + 4);
return r0 / 0x100000000 +
(r1 & 0x1fffff) / 0x20000000000000;
}
}
// We target compatibility with the seedrandom package.
//
// seed: a String or Buffer.
function seedrandom(seed, options = {}, callback) {
// If requesting to "add entropy" to the pool,
// we just rely on the system's cryptographic pool.
if (options.entropy) { seed = null; }
const prng = new PRNG(seed);
const double = prng.double.bind(prng);
double.int32 = prng.uint32.bind(prng);
double.quick = function() {
return prng.uint32() / 0x100000000;
};
double.double = double;
double.fill = prng.fill.bind(prng);
if (callback) {
return callback(double, prng.internalSeed, this, options.state);
}
return double;
}
module.exports = seedrandom;