Skip to content

Instantly share code, notes, and snippets.

@psema4
Last active July 30, 2023 09:35
Show Gist options
  • Save psema4/6c11e96a56a63e7c7e94ae3312a93fe7 to your computer and use it in GitHub Desktop.
Save psema4/6c11e96a56a63e7c7e94ae3312a93fe7 to your computer and use it in GitHub Desktop.
Simple Middle Square Weyl Sequence PRNG
/* Simple PRNG Based on https://en.wikipedia.org/wiki/Middle-square_method#Middle_Square_Weyl_Sequence_RNG
*
* Usage:
* node:
* var MSWS = require('msws.js');
*
* browser:
* include this script in your html document
*
* both:
* var prng = new MSWS();
*
* var seed = prng.getSeed();
* prng.setSeet(seed); // static sequences
* //prng.setSeed(new Date().getTime()); // or randomize the seed
*
* var min=0, max=1000, precision=3;
* console.log(prng.random()); // 0f <=> 1f
* console.log(prng.getInt(max, min); // 0 <=> 1000
* console.log(prng.getFloat(max, min); // 0f <=> 1000f
* console.log(prng.getFixed(precision, max, min); // 0.000 <=> 1000.000
*/
(function() {
var MSWS = (function() {
var MSWS = function(opts) {
this.x = 0;
this.w = 0;
this.s = opts && opts.seed || 0x45ad4ece;
this.maxPrecision = opts && opts.maxPrecision || 10;
};
MSWS.prototype.getSeed = function() {
return this.s;
}
MSWS.prototype.setSeed = function(seed) {
this.s = seed;
}
MSWS.prototype.msws = function(max, min) {
var clamped = !!max
, done = false
, i = 0
;
max = max || 1;
min = min || 0;
while (!done) {
i += 1;
this.x *= this.x;
this.x += (this.w += this.s);
this.x = (this.x>>16) | (this.x<<16);
this.x = (this.x < 0) ? this.x * -1 : this.x;
var outOfBounds = clamped && ( (this.x > max) || (min && this.x < min) );
if (!clamped) {
done = true;
} else if (!outOfBounds) {
done = true;
}
}
return this.x;
}
MSWS.prototype.getInt = function(max, min) {
return this.msws(max, min);
}
MSWS.prototype.getFloat = function(max, min) {
min = min || 0;
max = max || 1;
var whole = (max === 1) ? 0 : this.getInt(max-1, min)
, part = this.getInt(+'1'+'0'.repeat(this.maxPrecision))
, result = +whole + '.' + part
;
return result;
}
MSWS.prototype.getFixed = function(precision, max, min) {
precision = precision || 2;
min = min || 0;
max = max || 1;
precision = precision >= this.maxPrecision ? this.maxPrecision : precision;
return new Number(this.getFloat(max, min)).toFixed(precision);
}
MSWS.prototype.random = function() {
return this.getFloat(1, 0);
}
return MSWS;
})();
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
module.exports = MSWS
} else {
window.MSWS = MSWS
}
})();
/* See sample-es6.js for usage
Note: es6 module import / export not available in node; issues summarized at
https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c
export default class MSWS {
use commonjs instead
*/
module.exports = class MSWS {
constructor(opts) {
this.x = 0;
this.w = 0;
this.s = opts && opts.seed || 0;
this.maxPrecision = opts && opts.maxPrecision || 10;
}
getSeed() {
return this.s;
}
setSeed(seed) {
this.s = seed;
}
getInt(max = 1, min = 0) {
return this._msws(max, min);
}
getFloat(max = 1, min = 0) {
let whole = (max === 1) ? 0 : this.getInt(max - 1, min)
, part = this.getInt(+'1' + ('0'.repeat(this.maxPrecision)))
, result = +whole + '.' + part
;
return result;
}
getFixed(precision = 2, max = 1, min = 0) {
precision = precision >= this.maxPrecision ? this.maxPrecision : precision;
return new Number(this.getFloat(max, min)).toFixed(precision);
}
random(max = 1, min = 0) {
return this.getFloat(max, min);
}
_msws(max = 1, min = 0) {
let clamped = !!max
, done = false
, i = 0
;
while (!done) {
i += 1;
this.x *= this.x;
this.x += (this.w += this.s);
this.x = (this.x>>16) | (this.x<<16);
this.x = (this.x < 0) ? this.x * -1 : this.x;
let outOfBounds = clamped && ( (this.x > max) || (min && this.x < min) );
if (!clamped) {
done = true;
} else if (!outOfBounds) {
done = true;
}
}
return this.x;
}
// cannot be called by instance
static versionInfo() {
let version = 1
return `MSWS, a Middle Square Weyl Sequence prng.\nversion ${version.toFixed(2)}\n`;
}
}
/* Note: es6 module import / export not available in node; issues summarized at
https://medium.com/the-node-js-collection/an-update-on-es6-modules-in-node-js-42c958b890c
import MSWS from 'msws';
use commonjs instead
*/
let MSWS = require('./msws')
, prng = new MSWS({ seed: 3 })
;
console.log("%s", MSWS.versionInfo());
// integers
for (let i=0; i<10; i++) {
console.log("getInt(10): %d", prng.getInt(10));
}
// floats
console.log("\ngetFloat(): %s", prng.getFloat());
console.log("getFloat(100, 90): %s", prng.getFloat(100, 90));
// fixed-precision
console.log("\ngetFixed(): %s", prng.getFixed());
console.log("getFixed(4): %s", prng.getFixed(4));
console.log("getFixed(6): %s", prng.getFixed(6));
console.log("getFixed(8): %s", prng.getFixed(8));
console.log("getFixed(10): %s", prng.getFixed(10));
// random
console.log("\nrandom(): %s", prng.random());
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment