Skip to content

Commit

Permalink
feature: add XSH_RS, XSH_RR, and RXS_M_XS output functions (#116)
Browse files Browse the repository at this point in the history
  • Loading branch information
philihp authored Dec 22, 2023
1 parent 4adba95 commit 90f8ccf
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 16 deletions.
58 changes: 58 additions & 0 deletions src/__tests__/createPcg32.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { createPcg32, nextState, prevState, randomInt, randomList } from '..'
import { OutputFnType } from '../types'

describe('basic', () => {
it('pCG32_XSH_RR: Single integer', () => {
Expand All @@ -11,6 +12,36 @@ describe('basic', () => {
expect(randomUint32(pcg)[0]).toBe(0xa15c02b7)
})

it('pCG32_XSH_RS: Single integer', () => {
expect.assertions(2)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.XSH_RS }, 42, 54)
// Check for generator immutability and result reproducibility
const [n, _state] = randomUint32(pcg)
expect(n).toBe(1545299392)
expect(randomUint32(pcg)[0]).toBe(1545299392)
})

it('pCG32_XSL_RR: Single integer', () => {
expect.assertions(2)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.XSL_RR }, 42, 54)
// Check for generator immutability and result reproducibility
const [n, _state] = randomUint32(pcg)
expect(n).toBe(110043304)
expect(randomUint32(pcg)[0]).toBe(110043304)
})

it('pCG32_RXS_M_XS: Single integer', () => {
expect.assertions(2)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.RXS_M_XS }, 42, 54)
// Check for generator immutability and result reproducibility
const [n, _state] = randomUint32(pcg)
expect(n).toBe(3562606574)
expect(randomUint32(pcg)[0]).toBe(3562606574)
})

it('pCG32_XSH_RR: Multiple integers', () => {
expect.assertions(1)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
Expand All @@ -20,6 +51,33 @@ describe('basic', () => {
])
})

it('pCG32_XSH_RS: Multiple integers', () => {
expect.assertions(1)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.XSH_RS }, 42, 54)
expect(randomList(6, randomUint32, pcg).map(([value]) => value)).toStrictEqual([
1545299392, 2415717169, 3435843701, 3090997190, 1576856010, 3235194092,
])
})

it('pCG32_XSL_RR: Multiple integers', () => {
expect.assertions(1)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.XSL_RR }, 42, 54)
expect(randomList(6, randomUint32, pcg).map(([value]) => value)).toStrictEqual([
110043304, 3982559790, 957466950, 3645676572, 223035418, 2465086851,
])
})

it('pCG32_RXS_M_XS: Multiple integers', () => {
expect.assertions(1)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
const pcg = createPcg32({ outputFnType: OutputFnType.RXS_M_XS }, 42, 54)
expect(randomList(6, randomUint32, pcg).map(([value]) => value)).toStrictEqual([
3562606574, 3701842622, 2826130885, 1212371962, 849807893, 1843984456,
])
})

it('pCG32_XSH_RR: Jump-ahead, jump-back', () => {
expect.assertions(5)
const randomUint32 = randomInt(0, 2 ** 32 - 1)
Expand Down
4 changes: 2 additions & 2 deletions src/createPcg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ export const randomInt = curry((min: number, max: number, pcg: PCGState): [numbe
return [n.mod(bound).add(min).toNumber(), nextPcg]
})

export const randomList = curry((length, rng, pcg): [number, PCGState][] =>
scan(([, nextPcg]) => rng(nextPcg), rng(pcg), new Array(length - 1))
export const randomList = curry((length, rng, initPcg): [number, PCGState][] =>
scan(([, lastPcg]) => rng(lastPcg), rng(initPcg), new Array(length - 1))
)

export default curry(
Expand Down
16 changes: 8 additions & 8 deletions src/defaults.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import Long from 'long'
import { StreamScheme, OutputFnType } from './types'

// export const pcgDefaultIncrement8 = 77;
// export const pcgDefaultIncrement16 = 47989;
// export const pcgDefaultIncrement32 = 2891336453;
export const pcgDefaultIncrement64 = Long.fromString('1442695040888963407', true)
// export const pcgDefaultIncrement8 = 77
// export const pcgDefaultIncrement16 = 47989
// export const pcgDefaultIncrement32 = Long.fromString('2891336453', 10)
export const pcgDefaultIncrement64 = Long.fromString('1442695040888963407', 10)

// export const pcgDefaultMultiplier8 = 141;
// export const pcgDefaultMultiplier16 = 12829;
// export const pcgDefaultMultiplier32 = 747796405;
export const pcgDefaultMultiplier64 = Long.fromString('6364136223846793005', true)
// export const pcgDefaultMultiplier8 = 141
// export const pcgDefaultMultiplier16 = 12829
// export const pcgDefaultMultiplier32 = Long.fromString('747796405')
export const pcgDefaultMultiplier64 = Long.fromString('6364136223846793005', 10)

export const pcgDefaultOutputFnType: OutputFnType = OutputFnType.XSH_RR
export const pcgDefaultStreamScheme: StreamScheme = StreamScheme.SETSEQ
11 changes: 11 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,16 @@ export const createPcg32 = createPcg({
outputFns: {
[OutputFnType.XSH_RR]: (state: Long): number =>
ror32(state.shru(59).toInt(), state.shru(18).xor(state).shru(27).toInt()),
[OutputFnType.XSH_RS]: (state: Long): number => state.shru(22).xor(state).shru(state.shru(61).add(22)).toInt(),
[OutputFnType.XSL_RR]: (state: Long): number => ror32(state.shru(59).toInt(), state.shru(32).xor(state).toInt()),
// [OutputFnType.XSL_RR_RR]: (state: Long): number => {
// const high = state.shru(32)
// const newlow = ror32(state.shru(59).toInt(), high.xor(state).toInt())
// return new Long(ror32(new Long(newlow).and(32).toInt(), high.toInt())).shl(32).or(newlow).toInt()
// },
[OutputFnType.RXS_M_XS]: (state: Long): number => {
const word = state.shru(13).add(3).xor(state).mul(62169)
return word.shru(11).xor(word).toInt()
},
},
})
10 changes: 4 additions & 6 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import Long from 'long'

// TODO: Implement more output functions

export enum OutputFnType {
XSH_RR = 0,
// XSH_RS = 1
// XSL_RR = 2
// XSL_RR_RR = 3
// RXS_M_XS = 4
XSH_RS = 1,
XSL_RR = 2,
// XSL_RR_RR = 3 // currently unstable
RXS_M_XS = 4,
}

export type OutputFn = (state: Long) => number
Expand Down

0 comments on commit 90f8ccf

Please sign in to comment.