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