Skip to content

Commit

Permalink
💥 BREAKING CHANGE: Add fill method.
Browse files Browse the repository at this point in the history
Renamed `nextFloat` to `nextFloat64`. See #1.
  • Loading branch information
make-github-pseudonymous-again committed Dec 8, 2020
1 parent b1499a6 commit 8f6f776
Show file tree
Hide file tree
Showing 12 changed files with 107 additions and 14 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ See [docs](https://aureooms.github.io/js-pseudo-random/index.html).
```js
import {
splitmix64,
nextFloat,
nextFloat64,
nextUint64,
} from '@aureooms/js-pseudo-random';

const seed = [0, 0]; // Two 32-bit signed integers.
const prng = splitmix64(seed);
nextUint64(prng); // 64 random bits as two 32-bit signed integers (compatible with @aureooms/js-uint64).
nextFloat(prng); // A random float in the range [0, 1[.
nextFloat64(prng); // A random double in the range [0, 1[.
```

[![License](https://img.shields.io/github/license/aureooms/js-pseudo-random.svg)](https://raw.githubusercontent.com/aureooms/js-pseudo-random/main/LICENSE)
Expand Down
7 changes: 7 additions & 0 deletions src/_fill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const _fill = (next, prng, array, i = 0, j = array.length) => {
for (; i < j; ++i) {
array[i] = next(prng);
}
};

export default _fill;
65 changes: 65 additions & 0 deletions src/fill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import _fill from './_fill';
import nextUint8 from './nextUint8';
import nextUint16 from './nextUint16';
import nextInt32 from './nextInt32';
import nextFloat32 from './nextFloat32';
import nextFloat64 from './nextFloat64';
import nextBigInt64 from './nextBigInt64';
import nextBigUint64 from './nextBigUint64';

const fill = (prng, array, i, j) => {
switch (array.constructor) {
case ArrayBuffer:
return _fill(nextUint8, new Uint8Array(array), i, j);

case Int8Array:
case Uint8Array:
case Uint8ClampedArray:
return _fill(
nextUint8,
prng,
new Uint8Array(array.buffer, array.byteOffset, array.byteLength),
i,
j,
);

case Int16Array:
case Uint16Array:
return _fill(
nextUint16,
prng,
new Uint16Array(array.buffer, array.byteOffset, array.length),
i,
j,
);

case Int32Array:
case Uint32Array:
return _fill(
nextInt32,
prng,
new Int32Array(array.buffer, array.byteOffset, array.length),
i,
j,
);

case Float32Array:
return _fill(nextFloat32, prng, array, i, j);

case Float64Array:
return _fill(nextFloat64, prng, array, i, j);

case BigInt64Array:
return _fill(nextBigInt64, prng, array, i, j);

case BigUint64Array:
return _fill(nextBigUint64, prng, array, i, j);

default:
throw new Error(
`fill(prng, array, ...): array with constructor '${array.constructor.name}' not implemented`,
);
}
};

export default fill;
8 changes: 5 additions & 3 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import nextFloat from './nextFloat';
import fill from './fill';
import nextFloat64 from './nextFloat64';
import nextInt32 from './nextInt32';
import nextUint64 from './nextUint64';
import splitmix64 from './splitmix64';
import xoroshiro128plus from './xoroshiro128plus';

/* eslint import/no-anonymous-default-export: [2, {"allowObject": true}] */
export default {
nextFloat,
fill,
nextFloat64,
nextInt32,
nextUint64,
splitmix64,
xoroshiro128plus,
};

export {nextFloat, nextInt32, nextUint64, splitmix64, xoroshiro128plus};
export {fill, nextFloat64, nextInt32, nextUint64, splitmix64, xoroshiro128plus};
5 changes: 5 additions & 0 deletions src/nextBigInt64.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import nextBigUint64 from './nextBigUint64';

export default function nextBigInt64(prng) {
return nextBigUint64(prng) - BigInt(2 ** 63);
}
5 changes: 5 additions & 0 deletions src/nextBigUint64.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function nextBigUint64(prng) {
const a = prng.next().value;
const b = prng.next().value;
return BigInt(a) * BigInt(2 ** 32) + BigInt(b);
}
4 changes: 4 additions & 0 deletions src/nextFloat32.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export default function nextFloat32(prng) {
const x = prng.next().value;
return (x >>> 9) / 2 ** 23;
}
2 changes: 1 addition & 1 deletion src/nextFloat.js → src/nextFloat64.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default function nextFloat(prng) {
export default function nextFloat64(prng) {
const a = prng.next().value;
const b = prng.next().value;
return (a >>> 0) / 2 ** 32 + (b >>> 0) / 2 ** 64;
Expand Down
3 changes: 3 additions & 0 deletions src/nextUint16.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function nextUint16(prng) {
return (prng.next().value >>> 16) & 0xffff;
}
3 changes: 3 additions & 0 deletions src/nextUint8.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export default function nextUint8(prng) {
return (prng.next().value >>> 24) & 0xff;
}
4 changes: 2 additions & 2 deletions test/src/splitmix64.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import test from 'ava';
import {range, map} from '@aureooms/js-itertools';

import {get64} from '@aureooms/js-uint64';
import {splitmix64, nextUint64, nextFloat} from '../../src';
import {splitmix64, nextUint64, nextFloat64} from '../../src';

test('https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64 #1', (t) => {
/**
Expand All @@ -29,7 +29,7 @@ test('https://rosettacode.org/wiki/Pseudo-random_numbers/Splitmix64 #2', (t) =>
const prng = splitmix64(seed);
const histogram = new Array(5).fill(0);
for (const k of map(
() => Math.floor(nextFloat(prng) * 5) | 0,
() => Math.floor(nextFloat64(prng) * 5) | 0,
range(100000),
)) {
++histogram[k];
Expand Down
11 changes: 5 additions & 6 deletions test/src/xoroshiro128plus.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import test from 'ava';

import {get64} from '@aureooms/js-uint64';

import {splitmix64, xoroshiro128plus, nextInt32, nextUint64} from '../../src';
import {splitmix64, xoroshiro128plus, fill, nextUint64} from '../../src';

test('Example found at https://github.com/dgryski/go-xoroshiro/blob/ea5ca0291510c1f8b16321d610ae73e1006d499f/xoro_test.go#L28', (t) => {
const prng = xoroshiro128plus([0, 1, 0, 2], {a: 55, b: 14, c: 36});
Expand Down Expand Up @@ -53,12 +53,11 @@ test('Example found at https://github.com/dgryski/go-xoroshiro/blob/ea5ca0291510
});

test('Example found at https://github.com/dgryski/go-xoroshiro/blob/ea5ca0291510c1f8b16321d610ae73e1006d499f/xoro_test.go#L80', (t) => {
const seed = splitmix64([0x0ddc0ffe, 0xebadf00d]);
const seeder = splitmix64([0x0ddc0ffe, 0xebadf00d]);
const seed = new Int32Array(4);
fill(seeder, seed);

const prng = xoroshiro128plus(
[nextInt32(seed), nextInt32(seed), nextInt32(seed), nextInt32(seed)],
{a: 55, b: 14, c: 36},
);
const prng = xoroshiro128plus(seed, {a: 55, b: 14, c: 36});

t.deepEqual(nextUint64(prng), get64(0xa3f4ee8f, 0x1df50a08)); // 11814330020949985800
t.deepEqual(nextUint64(prng), get64(0xa3febba4, 0x5a9ce9c5)); // 11817088786836023749
Expand Down

0 comments on commit 8f6f776

Please sign in to comment.