tychei.js 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // A Javascript implementaion of the "Tyche-i" prng algorithm by
  2. // Samuel Neves and Filipe Araujo.
  3. // See https://eden.dei.uc.pt/~sneves/pubs/2011-snfa2.pdf
  4. (function(global, module, define) {
  5. function XorGen(seed) {
  6. var me = this, strseed = '';
  7. // Set up generator function.
  8. me.next = function() {
  9. var b = me.b, c = me.c, d = me.d, a = me.a;
  10. b = (b << 25) ^ (b >>> 7) ^ c;
  11. c = (c - d) | 0;
  12. d = (d << 24) ^ (d >>> 8) ^ a;
  13. a = (a - b) | 0;
  14. me.b = b = (b << 20) ^ (b >>> 12) ^ c;
  15. me.c = c = (c - d) | 0;
  16. me.d = (d << 16) ^ (c >>> 16) ^ a;
  17. return me.a = (a - b) | 0;
  18. };
  19. /* The following is non-inverted tyche, which has better internal
  20. * bit diffusion, but which is about 25% slower than tyche-i in JS.
  21. me.next = function() {
  22. var a = me.a, b = me.b, c = me.c, d = me.d;
  23. a = (me.a + me.b | 0) >>> 0;
  24. d = me.d ^ a; d = d << 16 ^ d >>> 16;
  25. c = me.c + d | 0;
  26. b = me.b ^ c; b = b << 12 ^ d >>> 20;
  27. me.a = a = a + b | 0;
  28. d = d ^ a; me.d = d = d << 8 ^ d >>> 24;
  29. me.c = c = c + d | 0;
  30. b = b ^ c;
  31. return me.b = (b << 7 ^ b >>> 25);
  32. }
  33. */
  34. me.a = 0;
  35. me.b = 0;
  36. me.c = 2654435769 | 0;
  37. me.d = 1367130551;
  38. if (seed === Math.floor(seed)) {
  39. // Integer seed.
  40. me.a = (seed / 0x100000000) | 0;
  41. me.b = seed | 0;
  42. } else {
  43. // String seed.
  44. strseed += seed;
  45. }
  46. // Mix in string seed, then discard an initial batch of 64 values.
  47. for (var k = 0; k < strseed.length + 20; k++) {
  48. me.b ^= strseed.charCodeAt(k) | 0;
  49. me.next();
  50. }
  51. }
  52. function copy(f, t) {
  53. t.a = f.a;
  54. t.b = f.b;
  55. t.c = f.c;
  56. t.d = f.d;
  57. return t;
  58. };
  59. function impl(seed, opts) {
  60. var xg = new XorGen(seed),
  61. state = opts && opts.state,
  62. prng = function() { return (xg.next() >>> 0) / 0x100000000; };
  63. prng.double = function() {
  64. do {
  65. var top = xg.next() >>> 11,
  66. bot = (xg.next() >>> 0) / 0x100000000,
  67. result = (top + bot) / (1 << 21);
  68. } while (result === 0);
  69. return result;
  70. };
  71. prng.int32 = xg.next;
  72. prng.quick = prng;
  73. if (state) {
  74. if (typeof(state) == 'object') copy(state, xg);
  75. prng.state = function() { return copy(xg, {}); }
  76. }
  77. return prng;
  78. }
  79. if (module && module.exports) {
  80. module.exports = impl;
  81. } else if (define && define.amd) {
  82. define(function() { return impl; });
  83. } else {
  84. this.tychei = impl;
  85. }
  86. })(
  87. this,
  88. (typeof module) == 'object' && module, // present in node.js
  89. (typeof define) == 'function' && define // present with an AMD loader
  90. );