prng-lfsr
Version:
seedable, seeded, pseudo random number generator, prng, linear feedback shift register, fibonnaci, galois, lfsr
140 lines (104 loc) • 3.99 kB
JavaScript
var galois16 = require('../').galois16
, test = require('tape')
;
/* START common 16bit lfsr tests */
test('galois16 exists', function (assert) {
assert.ok(!!galois16);
assert.is('function', typeof galois16);
assert.end();
});
test('galois16 rejects bad seeds', function (assert) {
assert.is(galois16(), false, 'mandatory seed!');
assert.is(galois16('foo'), false);
assert.is(galois16(function () {}), false);
assert.is(galois16({}), false);
assert.is(galois16([]), false);
assert.is(galois16(65536), false);
assert.is(galois16(-1), false);
assert.is(galois16(0), false);
assert.end();
});
test('galois16 returns a function if seed ok', function (assert) {
assert.is(typeof galois16(1), 'function');
assert.is(typeof galois16(2), 'function');
assert.is(typeof galois16(65535), 'function');
assert.is(typeof galois16(0xACE1), 'function');
assert.end();
});
test('galois16 has expected periodicity', function (assert) {
var seed = 0xACE1
, g = galois16(seed)
, remainingIterations = 0xffff // 65535 iterations to return to start
, lastResult
;
while (remainingIterations--) {
if (seed === lastResult) { assert.ok(false, 'found seed value too early! remainingIterations: ' + remainingIterations) };
lastResult = g();
}
assert.is(lastResult, seed, '0xACE1 -------> 0xACE1 after maximum iterations');
assert.end();
});
test('galois16 output bit stream', function (assert) {
var seed = 0xACE1
, g = galois16(seed)
, remainingIterations = 0xffff // 65535 iterations to return to start. aka (2^n)-1
, lastResult
, bitString = ''
, maxZeroRun = /000000000000000/g // n - 1
, impossibleZeroRun = /0000000000000000/g // n
, maxOneRun = /1111111111111111/g // n
, impossibleOneRun = /11111111111111111/g // n + 1
, found
;
while (remainingIterations--) {
lastResult = g();
bitString += lastResult & 1; // right-most bit is output bit. NB. different output bit to fibonacci
}
assert.is(bitString.length, 0xffff, 'got right number of bits');
found = maxZeroRun.exec(bitString);
assert.is(found.length, 1, 'got right number of maximum runs of 0');
found = impossibleZeroRun.exec(bitString);
assert.is(found, null, 'got no runs of 0 exceeding n');
found = maxOneRun.exec(bitString);
assert.is(found.length, 1, 'got right number of maximum runs of 1');
found = impossibleOneRun.exec(bitString);
assert.is(found, null, 'got no runs of 1 exceeding n');
assert.end();
});
/* END common 16bit lfsr tests */
test('galois16 returns successful next values', function (assert) {
var g = galois16(0xACE1);
assert.is(g(), 0xE270, '0xACE1 -> 0xE270');
assert.is(g(), 0x7138, '0xE270 -> 0x7138');
assert.end();
});
test('galois/fibonacci output bit stream equivalance', function (assert) {
// TODO this shouldn't live here! move to common tests
var fibonacci16 = require('../').fibonacci16;
var seed = 0xACE1
, g = galois16(seed)
, f = fibonacci16(seed)
, gLastResult
, galoisBitString = ''
, fLastResult
, fibonacciBitString = ''
, fibonacciOffset = 14077
, remainingIterations = 0xffff // 65535 iterations to return to start. aka (2^n)-1
;
/* shows offset at 14077 ... is this right?
//console.log(fibonacciBitString.indexOf(galoisBitString.substr(0,256)));
if so then formalising a test that warms up fibonnacci, then we shall test equality
*/
while (fibonacciOffset--) {
f();
}
while (remainingIterations--) {
gLastResult = g();
fLastResult = f();
galoisBitString += gLastResult & 1; // right-most bit is output bit. NB. different output bit to fibonacci
fibonacciBitString += (fLastResult >> 15) & 1; // left-most bit is last output bit. NB. different output bit to galois
}
assert.is(galoisBitString, fibonacciBitString, 'galoisBitString === fibonacciBitString');
// wow, it works.
assert.end();
});