prngtest.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. // A simple smoke test and benchmark for the generators.
  2. var assert = require('assert');
  3. var xor128 = require('../lib/xor128');
  4. var xorwow = require('../lib/xorwow');
  5. var xs7 = require('../lib/xorshift7');
  6. var xor4096 = require('../lib/xor4096');
  7. var tychei = require('../lib/tychei');
  8. var alea = require('../lib/alea');
  9. var sr = require('../seedrandom');
  10. describe("XOR-Shift generator test", function() {
  11. var benchmarks = { native: { rand: Math.random, times: [] } };
  12. function test(label, alg, double1, float3, int4, hc, qc, ec, e2c) {
  13. var fn = alg(1);
  14. var fn2 = alg('hello.', { state: true });
  15. benchmarks[label] = {rand: fn.quick, times: []};
  16. it("should use " + label + " correctly", function() {
  17. if (double1 != null) assert.equal(fn.double(), double1);
  18. if (float3 != null) assert.equal(fn.quick(), float3);
  19. if (int4 != null) assert.equal(fn.int32(), int4);
  20. assert(fn() > 0);
  21. assert(fn() < 1);
  22. assert(fn2() > 0);
  23. // Internal state is visible only if requested.
  24. assert(!('state' in fn));
  25. assert('state' in fn2);
  26. var ss = fn2.state();
  27. var rs = fn2();
  28. assert(rs < 1);
  29. var j, h = 0, q = 0, e = 0, r, p, e2 = 0;
  30. for (j = 0; j < 1024; ++j) {
  31. r = fn();
  32. if (r < 0.5) h += 1;
  33. if (r < 0.25) q += 1;
  34. if (r < 0.125) e += 1;
  35. r2 = fn2();
  36. if (r2 < 0.125) e2 += 1;
  37. }
  38. if (hc != null) {
  39. assert.equal(h, hc);
  40. assert.equal(q, qc);
  41. assert.equal(e, ec);
  42. assert.equal(e2, e2c);
  43. h = q = e = p = 0;
  44. for (j = 0; j < 1024; ++j) {
  45. r = fn.double();
  46. if (r < 0.5) h += 1;
  47. if (r < 0.25) q += 1;
  48. if (r < 0.125) e += 1;
  49. if (fn.int32() >= 0) p += 1;
  50. }
  51. // Sanity-check double() and int32.
  52. assert(h >= 480 && h <= 543, h);
  53. assert(q >= 226 && q <= 286, q);
  54. assert(e >= 100 && e <= 156, e);
  55. assert(e2 >= 100 && e2 <= 156, e2);
  56. assert(p >= 482 && p <= 543, p);
  57. }
  58. var fn3 = alg(0, { state: ss });
  59. assert.equal(fn3(), rs);
  60. });
  61. }
  62. test("xor128", xor128,
  63. 0.7963797148975774, 0.22171171731315553, 317177041, 498, 236, 110, 115);
  64. test("xorwow", xorwow,
  65. 0.8178000247146859, 0.8407576507888734, 533150816, 519, 228, 121, 123);
  66. test("xorshift7", xs7,
  67. 0.21241471533241418, 0.9957620368804783, -1678071207, 510, 261, 143, 124);
  68. test("tychei", tychei,
  69. 0.42331440041340196, 0.9365617581643164, -884984569, 521, 242, 116, 126);
  70. test("seedrandom", sr,
  71. 0.1776348083296759, 0.2160690303426236, 1397712774, 526, 282, 131, 137);
  72. test("xor4096", xor4096,
  73. 0.1520436450538547, 0.4206166828516871, 1312695376, 496, 241, 113, 142);
  74. test("alea", alea,
  75. 0.5260470956849501, 0.47771977609954774, -1625913352, 494, 246, 125, 122);
  76. it("runs benchmarks", function() {
  77. var n = 4;
  78. var trials = 10;
  79. var top = 4;
  80. this.timeout(200 * n * trials);
  81. this.slow(30 * n * trials);
  82. var fn, k, start, end, j, t;
  83. for (k in benchmarks) {
  84. fn = benchmarks[k].rand;
  85. // warmup.
  86. for (j = 0; j < 1e5; ++j) fn();
  87. }
  88. for (t = 0; t < trials; ++t) {
  89. for (k in benchmarks) {
  90. fn = benchmarks[k].rand;
  91. start = +new Date;
  92. // benchmark.
  93. for (j = 0; j < n * 1e5; ++j) fn();
  94. end = +new Date;
  95. benchmarks[k].times.push(end - start);
  96. }
  97. }
  98. for (k in benchmarks) {
  99. benchmarks[k].times.sort();
  100. }
  101. function fastest(array) {
  102. var sum = 0;
  103. for (var j = 0; j < top; ++j) {
  104. sum += array[j];
  105. }
  106. return sum / top;
  107. }
  108. var nativetime = fastest(benchmarks.native.times);
  109. for (k in benchmarks) {
  110. var time = fastest(benchmarks[k].times);
  111. console.log(k+ ': ' + time / n + ' nanoseconds per call, ' +
  112. (time / nativetime).toFixed(1) + 'x native random.');
  113. }
  114. });
  115. });