Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //random with seed & range
- (function(window) {
- //scope it so closure contains only relevant internal state
- window.performance = window.performance || {};
- performance.now = (function() { //use high res time
- return performance.now ||
- performance.mozNow ||
- performance.msNow ||
- performance.oNow ||
- performance.webkitNow ||
- function() { return new Date().getTime(); };//shim for old browsers
- })();
- var c=1;
- window.RND = function(s, min, max) {
- //uses next gen v8 js engine random (splitmix64 seed & Xoroshiro128+ rng)
- //which is better than (murmurhash3 & xorshift128+) currently used in browsers
- //this rng also supports custom seed , and min max range limit(both inclusive)
- //(this class depends on using Long.js 3rd party lib)
- //should be positive
- max = max || 1;
- min = min || 0;
- var state0_;
- var state1_;
- var seedInit;//readonly, used for changing min-max without the seed
- max += 1; //make max inclusive
- //if (max > 32767) //after that, ditribution might not be uniform(probably only in c lang rand())
- // max = 32767;
- setSeed(s);
- Xoroshiro128plus(state0_, state1_);//do 1st round before call, so result won't be only of seeding
- function setSeed(seed) {
- seedInit = initSeed(seed);
- splitmix64(seedInit);
- }
- function initSeed(seed) {
- //seed shouldn't be 0
- if (seed == null || seed <= 0)
- seed = genSeedFunc(Math.random());
- if(seed<30000)
- seed=(seed^(seed*seed))+seed;//more entropy, bigger number
- return seed;
- }
- function genSeedFunc(r){
- if (r == null || r <= 0)
- r=Math.random();
- return Math.floor((r*(c++))*(~performance.now()^Date.now()));
- }
- function splitmix64(seed) { //64bit
- //test input/output of splitmix64 & Xoroshiro128plus
- //https://ideone.com/PuauK5
- var x = new Long(seed, 0, false);
- //Long.fromString is a little slower (because of intParse,multiply,loop length)
- //round 1
- x = x.add(Long.fromString("0x9E3779B97F4A7C15", false, 16));
- z = x;
- z = z.xor(z.shiftRightUnsigned(30));
- z = z.multiply(Long.fromString("0xBF58476D1CE4E5B9", false, 16));
- z = z.xor(z.shiftRightUnsigned(27));
- z = z.multiply(Long.fromString("0x94D049BB133111EB", false, 16));
- z = z.xor(z.shiftRightUnsigned(31));
- state0_ = z;
- //round 2
- var z = x.add(Long.fromString("0x9E3779B97F4A7C15", false, 16));
- z = z.xor(z.shiftRightUnsigned(30));
- z = z.multiply(Long.fromString("0xBF58476D1CE4E5B9", false, 16));
- z = z.xor(z.shiftRightUnsigned(27));
- z = z.multiply(Long.fromString("0x94D049BB133111EB", false, 16));
- z = z.xor(z.shiftRightUnsigned(31));
- state1_ = z;
- //this function might not be accurate after round 3 (but usually only the first 2 are needed)
- }
- function rotL(x, k) {
- var v1 = x.shiftLeft(k);
- var v2 = x.shiftRightUnsigned(64 - k);
- return v1.or(v2);
- }
- function Xoroshiro128plus(s0, s1) { //128bit
- var result = s0.add(s1);
- s1 = s1.xor(s0);
- state0_ = rotL(s0, 55).xor(s1).xor(s1.shiftLeft(14));
- state1_ = rotL(s1, 36);
- return result;
- }
- function genRandInternal(){
- var sum = Xoroshiro128plus(state0_, state1_);
- //to double
- var random = toDouble(sum.toString());
- return random;
- }
- function toDouble(str)
- {
- if (str.startsWith("-"))//make positive
- str = str.substr(1);
- var result = "0." + str;
- var random = parseFloat(result);
- return random;
- }
- return function() {
- var random = genRandInternal();
- if ((max - 1 - min) <= 2) {
- //try 2 times to not pass min/max for better randomness
- if ((random > 1) || (random < 0)) {
- random = genRandInternal();
- if ((random > 1) || (random < 0)) {
- random = genRandInternal();
- }
- }
- }
- //set to range if overflow
- if (random > 1) random = 1;
- else if (random < 0) random = 0;
- //range check , random = 0-1 double , used as precentage of the range
- var r = (min + (random * (max - min))) % (max + 1);
- if (r > max-1) r = max-1;
- else if (r < min) r = min;
- return {
- value: r,
- seed_:seedInit,
- toBool: function() {
- //random bool
- return (random > 0.5);
- },
- toInt: function() {
- return Math.floor(r);
- },
- getSeed: function(){
- //for new RND instance with different min,max
- return genSeedFunc(random);
- }
- //,function NextBytes(arrSize){}
- }
- };
- //also can can do after -128 if you want a number between -128 , 128 (using min 0 and max 256)
- }
- })(window);
Advertisement
Add Comment
Please, Sign In to add comment