Skip to content

Commit aee1214

Browse files
committed
Restore Math.random on teardown.
1 parent e44ae3c commit aee1214

2 files changed

Lines changed: 37 additions & 50 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"smash": "~0.0.12",
5555
"uglify-js": "2.4.0",
5656
"vows": "0.7.0",
57-
"seedrandom": "0.1.6"
57+
"seedrandom": "2.3.1"
5858
},
5959
"scripts": {
6060
"test": "node_modules/.bin/vows"

test/math/random-test.js

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,45 @@
11
var vows = require("vows"),
22
load = require("../load"),
33
assert = require("../assert"),
4-
seedrandom = require('seedrandom');
4+
seedrandom = require("seedrandom");
55

66
var suite = vows.describe("d3.random");
77

8-
/**
9-
* Testing a random number generator is a bit more complicated than testing
10-
* deterministic code, so we use different techniques.
11-
*
12-
* If the RNG is correct, each test in this suite will pass with probability
13-
* at least P. The tests have been designed so that P ≥ 98%. Specific values
14-
* of P are given above each case. We use the seedrandom module to get around
15-
* this non-deterministic aspect -- so it is safe to assume that if the tests
16-
* fail, then d3's RNG is broken.
17-
*
18-
* More on RNG testing here:
19-
* @see http://www.johndcook.com/Beautiful_Testing_ch10.pdf
20-
*/
21-
22-
// Overwrites Math.random to a seeded random function.
23-
// (by default Math.random is seeded with current time)
24-
Math.seedrandom('a random seed.');
8+
// Testing a random number generator is a bit more complicated than testing
9+
// deterministic code, so we use different techniques.
10+
//
11+
// If the RNG is correct, each test in this suite will pass with probability
12+
// at least P. The tests have been designed so that P ≥ 98%. Specific values
13+
// of P are given above each case. We use the seedrandom module to get around
14+
// this non-deterministic aspect -- so it is safe to assume that if the tests
15+
// fail, then d3's RNG is broken.
16+
//
17+
// See also: http://www.johndcook.com/Beautiful_Testing_ch10.pdf
2518

2619
suite.addBatch({
2720
"random": {
2821
topic: load("math/random").expression("d3.random"),
29-
"normal": {
30-
"topic": function(random) { return random.normal(-43289, 38.8); },
31-
32-
// P = 98%
33-
"has normal distribution" : KSTest(normalCDF(-43289, 38.8))
34-
},
35-
"logNormal": {
36-
// Use reasonable values for mean here because random.logNormal() grows
37-
// exponentially with the mean.
38-
"topic": function(random) { return random.logNormal(10, 2.5); },
39-
40-
// P = 98%
41-
"has log-normal distribution" : KSTest(logNormalCDF(10, 2.5))
42-
},
43-
"irwinHall": {
44-
"topic": function(random) { return random.irwinHall(10); },
45-
46-
// P = 98%
47-
"has Irwin-Hall distribution" : KSTest(irwinHallCDF(10))
22+
"(using seedrandom)": {
23+
topic: function(random) {
24+
_random = Math.random;
25+
Math.seedrandom("a random seed.");
26+
return random;
27+
},
28+
"normal": {
29+
"topic": function(random) { return random.normal(-43289, 38.8); },
30+
"has normal distribution": KSTest(normalCDF(-43289, 38.8))
31+
},
32+
"logNormal": {
33+
"topic": function(random) { return random.logNormal(10, 2.5); },
34+
"has log-normal distribution": KSTest(logNormalCDF(10, 2.5))
35+
},
36+
"irwinHall": {
37+
"topic": function(random) { return random.irwinHall(10); },
38+
"has Irwin-Hall distribution": KSTest(irwinHallCDF(10))
39+
},
40+
teardown: function() {
41+
Math.random = _random;
42+
}
4843
}
4944
}
5045
});
@@ -59,9 +54,7 @@ suite.addBatch({
5954
*
6055
* @param cdf function(x) { returns CDF of the distribution evaluated at x }
6156
* @param n number of sample points. Higher n = better evaluation, slower test.
62-
* @return function(rng) {
63-
* // asserts that rng produces values fitting the distribution
64-
* }
57+
* @return a function that asserts the rng produces values fitting the distribution
6558
*/
6659
function KSTest(cdf, n) {
6760
return function(rng) {
@@ -85,15 +78,15 @@ function KSTest(cdf, n) {
8578
}
8679
}
8780

81+
// Logistic approximation to normal CDF around N(mean, stddev).
8882
function normalCDF(mean, stddev) {
89-
// Logistic approximation to normal CDF around N(mean, stddev).
9083
return function(x) {
9184
return 1 / (1 + Math.exp(-0.07056 * Math.pow((x-mean)/stddev, 3) - 1.5976 * (x-mean)/stddev));
9285
}
9386
}
9487

88+
// See http://en.wikipedia.org/wiki/Log-normal_distribution#Similar_distributions
9589
function logNormalCDF(mean, stddev) {
96-
// @see http://en.wikipedia.org/wiki/Log-normal_distribution#Similar_distributions
9790
var exponent = Math.PI / (stddev * Math.sqrt(3));
9891
var numerator = Math.exp(mean);
9992
return function(x) {
@@ -111,15 +104,9 @@ function irwinHallCDF(n) {
111104
binoms.push(binom(n, k));
112105
}
113106

114-
// @see CDF at http://en.wikipedia.org/wiki/Irwin%E2%80%93Hall_distribution
107+
// See CDF at http://en.wikipedia.org/wiki/Irwin–Hall_distribution
115108
return function(x) {
116109
var t = 0;
117-
118-
// What d3 calls Irwin-Hill distribution is actually a Bates distribution:
119-
// the Irwin-Hall distribution divided by n. So we multiply the Bates
120-
// distribution's x-value by n to get the Irwin-Hall CDF at x.
121-
x *= n;
122-
123110
for (var k = 0; k < x; k++) {
124111
t += Math.pow(-1, k % 2) * binoms[k] * Math.pow(x - k, n);
125112
}

0 commit comments

Comments
 (0)