From aba003335c631aca1fd57d522d40b9d766c5eeed Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Sun, 22 Mar 2026 12:45:54 +0000 Subject: [PATCH 1/7] feat: xorshift128plus pseudorandom generator --- .../@stdlib/random/base/xorshift128/README.md | 287 ++++++++++ .../base/xorshift128/benchmark/benchmark.js | 357 ++++++++++++ .../random/base/xorshift128/examples/basic.js | 140 +++++ .../random/base/xorshift128/examples/index.js | 177 ++++++ .../random/base/xorshift128/lib/factory.js | 438 +++++++++++++++ .../random/base/xorshift128/lib/index.js | 54 ++ .../random/base/xorshift128/lib/main.js | 62 +++ .../random/base/xorshift128/lib/rand_int64.js | 71 +++ .../random/base/xorshift128/package.json | 105 ++++ .../random/base/xorshift128/test/test.js | 519 ++++++++++++++++++ 10 files changed, 2210 insertions(+) create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/README.md create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/package.json create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/test/test.js diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/README.md b/lib/node_modules/@stdlib/random/base/xorshift128/README.md new file mode 100644 index 000000000000..13ba08fb4399 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/README.md @@ -0,0 +1,287 @@ + + +# Xorshift128+ + +> A 128-bit xorshift pseudorandom number generator ([PRNG][xorshift]). + +
+ +## Usage + +```javascript +var xorshift128plus = require( '@stdlib/random/base/xorshift128' ); +``` + +#### xorshift128plus() + +Returns a pseudorandom 64-bit unsigned integer. + +```javascript +var r = xorshift128plus(); +// returns +``` + +#### xorshift128plus.normalized() + +Returns a pseudorandom number on the interval `[0,1)`. + +```javascript +var r = xorshift128plus.normalized(); +// returns +``` + +#### xorshift128plus.factory( [options] ) + +Returns a xorshift128+ pseudorandom number generator ([PRNG][xorshift]). + +```javascript +var rand = xorshift128plus.factory(); +``` + +The function accepts the following `options`: + +- **seed**: pseudorandom number generator seed. Must be a non-negative integer or BigInt. Default: a random seed. +- **state**: a state array (Array) containing pseudorandom number generator state. If provided, the function ignores the `seed` option. +- **copy**: `boolean` indicating whether to copy a provided pseudorandom number generator state. Setting this option to `false` allows sharing state between two or more pseudorandom number generators. Setting this option to `true` ensures that a returned generator has exclusive control over its internal state. Default: `true`. + +By default, a random seed is used to seed the returned generator. To seed the generator, provide either a non-negative integer + +```javascript +var rand = xorshift128plus.factory({ + 'seed': BigInt(1234) +}); + +var r = rand(); +// returns +``` + +or, for arbitrary length seeds, a BigInt value + +```javascript +var rand = xorshift128plus.factory({ + 'seed': BigInt( 1234 ) +}); + +var r = rand(); +// returns +``` + +To return a generator having a specific initial state, set the generator `state` option. + +```javascript +// Generate pseudorandom numbers, thus progressing the generator state: +var r; +var i; +for ( i = 0; i < 1000; i++ ) { + r = xorshift128plus(); +} + +// Create a new PRNG initialized to the current state of `xorshift128plus`: +var rand = xorshift128plus.factory({ + 'state': xorshift128plus.state +}); + +// Test that the generated pseudorandom numbers are the same: +var bool = ( rand() === xorshift128plus() ); +// returns true +``` + +#### xorshift128plus.NAME + +The generator name. + +```javascript +var str = xorshift128plus.NAME; +// returns 'xorshift128+' +``` + +#### xorshift128plus.seed + +The value used to seed `xorshift128plus()`. + +```javascript +// Generate pseudorandom values... +var r; +var i; +for ( i = 0; i < 100; i++ ) { + r = xorshift128plus(); +} + +// Generate the same pseudorandom values... +var rand = xorshift128plus.factory({ + 'seed': xorshift128plus.seed +}); +for ( i = 0; i < 100; i++ ) { + r = rand(); +} +``` + +#### xorshift128plus.state + +Writable property for getting and setting the generator state. + +```javascript +var r = xorshift128plus(); +// returns + +r = xorshift128plus(); +// returns + +// ... + +// Get the current state: +var state = xorshift128plus.state; +// returns + +r = xorshift128plus(); +// returns + +r = xorshift128plus(); +// returns + +// Reset the state: +xorshift128plus.state = state; + +// Replay the last two pseudorandom numbers: +r = xorshift128plus(); +// returns + +r = xorshift128plus(); +// returns + +// ... +``` + +#### xorshift128plus.toJSON() + +Serializes the pseudorandom number generator as a JSON object. + +```javascript +var o = xorshift128plus.toJSON(); +// returns { 'type': 'PRNG', 'name': '...', 'state': [...], 'params': [] } +``` + +
+ + + +
+ +## Notes + +- The generator has a period of approximately `2^128` (see [References](#references)). +- Xorshift128+ is a fast, simple pseudorandom number generator with good statistical properties for most applications. +- The generator produces 64-bit pseudorandom integers using BigInt arithmetic. +- The "randomness quality" of the generator's output is suitable for general-purpose use, Monte Carlo simulations, and parallel computations (with different seeds). +- For cryptographic applications, use a cryptographically secure pseudorandom number generator (CSPRNG). +- If PRNG state is "shared" (meaning a state array was provided during PRNG creation and **not** copied) and one sets the generator state to a state array having a different length, the PRNG does **not** update the existing shared state and, instead, points to the newly provided state array. In order to synchronize PRNG output according to the new shared state array, the state array for **each** relevant PRNG must be **explicitly** set. +- If PRNG state is "shared" and one sets the generator state to a state array of the same length, the PRNG state is updated (along with the state of all other PRNGs sharing the PRNG's state array). + +
+ + + +
+ +## Examples + + + +```javascript +var xorshift128plus = require( '@stdlib/random/base/xorshift128plus' ); + +// Generate pseudorandom numbers... +var i; +for ( i = 0; i < 100; i++ ) { + console.log( xorshift128plus() ); +} + +// Create a new pseudorandom number generator... +var seed = BigInt(1234); +var rand = xorshift128plus.factory({ + 'seed': seed +}); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} + +// Create another pseudorandom number generator using a previous seed... +rand = xorshift128plus.factory({ + 'seed': xorshift128plus.seed +}); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} +``` + +
+ + + +* * * + +
+ +## References + +- Vigna, S. (2014). "An experimental exploration of Marsaglia's xorshift generators, scrambled." _ACM Transactions on Mathematical Software (TOMS)_, 42(4), 30. doi:[10.1145/2714064.2714122][vigna:2014]. +- Vigna, S. (2018). "Further scramblings of Marsaglia's xorshift generators." _Journal of Computational and Applied Mathematics_, 341, 273–282. doi:[10.1016/j.cam.2018.03.024][vigna:2018]. + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js b/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js new file mode 100644 index 000000000000..7ec953220740 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js @@ -0,0 +1,357 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/* eslint-disable node/no-unpublished-require */ + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var isBigInt = require( '@stdlib/assert/is-bigint' ); +var BigInt = require( '@stdlib/bigint/ctor' ); +var pkg = require( './../package.json' ).name; +var xorshift128plus = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var rng; + var z; + var i; + + rng = xorshift128plus(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = rng(); + if ( !isBigInt( z ) ) { + b.fail( 'should return a BigInt' ); + } + } + b.toc(); + + if ( !isBigInt( z ) ) { + b.fail( 'should return a BigInt' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':normalized', function benchmark( b ) { + var rng; + var z; + var i; + + rng = xorshift128plus(); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = rng.normalized(); + if ( typeof z !== 'number' ) { + b.fail( 'should return a number' ); + } + } + b.toc(); + + if ( typeof z !== 'number' ) { + b.fail( 'should return a number' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':factory', function benchmark( b ) { + var z; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = xorshift128plus({ + 'seed': BigInt(12345) + }); + if ( typeof z !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + + if ( typeof z !== 'function' ) { + b.fail( 'should return a function' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':factory:seed', function benchmark( b ) { + var z; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = xorshift128plus({ + 'seed': BigInt( i ) + }); + if ( typeof z !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + + if ( typeof z !== 'function' ) { + b.fail( 'should return a function' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':state', function benchmark( b ) { + var state; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + state = rng.state; + if ( state.length !== 6 ) { + b.fail( 'invalid state length' ); + } + } + b.toc(); + + if ( state.length !== 6 ) { + b.fail( 'invalid state length' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':state:set', function benchmark( b ) { + var state; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + state = rng.state; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + rng.state = state; + } + b.toc(); + + if ( state.length !== 6 ) { + b.fail( 'invalid state length' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':seed', function benchmark( b ) { + var seed; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + seed = rng.seed; + if ( !isBigInt( seed ) ) { + b.fail( 'should return a BigInt' ); + } + } + b.toc(); + + if ( !isBigInt( seed ) ) { + b.fail( 'should return a BigInt' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':copy', function benchmark( b ) { + var rng2; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + rng2 = rng.copy(); + if ( typeof rng2 !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + + if ( typeof rng2 !== 'function' ) { + b.fail( 'should return a function' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':toJSON', function benchmark( b ) { + var json; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + json = rng.toJSON(); + if ( typeof json !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + + if ( typeof json !== 'object' ) { + b.fail( 'should return an object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':reproducible', function benchmark( b ) { + var rng1; + var rng2; + var v1; + var v2; + var i; + + rng1 = xorshift128plus({ + 'seed': BigInt(54321) + }); + rng2 = xorshift128plus({ + 'seed': BigInt(54321) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v1 = rng1(); + v2 = rng2(); + if ( v1 !== v2 ) { + b.fail( 'sequences should be identical' ); + } + } + b.toc(); + + if ( v1 !== v2 ) { + b.fail( 'sequences should be identical' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':batch:next', function benchmark( b ) { + var values; + var rng; + var i; + var j; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + values = []; + values.length = 100; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + for ( j = 0; j < 100; j++ ) { + values[ j ] = rng(); + } + } + b.toc(); + + if ( values.length !== 100 ) { + b.fail( 'invalid values array length' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':batch:normalized', function benchmark( b ) { + var values; + var rng; + var i; + var j; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + values = []; + values.length = 100; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + for ( j = 0; j < 100; j++ ) { + values[ j ] = rng.normalized(); + } + } + b.toc(); + + if ( values.length !== 100 ) { + b.fail( 'invalid values array length' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':mixed', function benchmark( b ) { + var rng; + var v1; + var v2; + var i; + + rng = xorshift128plus({ + 'seed': BigInt(12345) + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v1 = rng(); + v2 = rng.normalized(); + } + b.toc(); + + if ( !isBigInt( v1 ) ) { + b.fail( 'should return a BigInt' ); + } + if ( typeof v2 !== 'number' ) { + b.fail( 'should return a number' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js b/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js new file mode 100644 index 000000000000..fb360d6350d6 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js @@ -0,0 +1,140 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var BigInt = require( '@stdlib/bigint/ctor' ); +var xorshift128plus = require( './../lib/' ); +var i; + +// EXAMPLE 1: Create a generator with a seed +console.log( '\n=== Example 1: Basic Generator ===' ); + +var rng = xorshift128plus({ + 'seed': BigInt(12345) +}); + +console.log( 'Generated 64-bit integers:' ); +console.log( ' %s', rng() ); +console.log( ' %s', rng() ); +console.log( ' %s', rng() ); + +// EXAMPLE 2: Generate normalized values +console.log( '\n=== Example 2: Normalized Values ===' ); + +var normalizedRng = xorshift128plus({ + 'seed': BigInt(54321) +}); + +console.log( 'Normalized values in [0, 1):' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %d', normalizedRng.normalized() ); +} + +// EXAMPLE 3: Reproducibility with same seed +console.log( '\n=== Example 3: Reproducibility ===' ); + +var rng1 = xorshift128plus({ + 'seed': BigInt(99999) +}); +var rng2 = xorshift128plus({ + 'seed': BigInt(99999) +}); + +console.log( 'Both generators with same seed (99999n):' ); +for ( i = 0; i < 3; i++ ) { + console.log( ' rng1: %s, rng2: %s', rng1().toString(), rng2().toString() ); +} + +// EXAMPLE 4: Seeding with different values +console.log( '\n=== Example 4: Different Seeds ===' ); + +var rngA = xorshift128plus({ + 'seed': BigInt(111) +}); +var rngB = xorshift128plus({ + 'seed': BigInt(222) +}); + +console.log( 'Different seeds produce different sequences:' ); +console.log( ' seed 111n: %s', rngA().toString() ); +console.log( ' seed 222n: %s', rngB().toString() ); + +// EXAMPLE 5: Using without explicit seed (random) +console.log( '\n=== Example 5: Random Seed ===' ); + +var randomRng = xorshift128plus(); + +console.log( 'Generator with random seed:' ); +for ( i = 0; i < 3; i++ ) { + console.log( ' %s', randomRng().toString() ); +} + +// EXAMPLE 6: Accessing generator properties +console.log( '\n=== Example 6: Generator Properties ===' ); + +var propRng = xorshift128plus({ + 'seed': BigInt(777) +}); + +console.log( 'Generator properties:' ); +console.log( ' NAME: %s', propRng.NAME ); +console.log( ' seed (BigInt): %s', propRng.seed ); +console.log( ' state (array length): %d', propRng.state.length ); + +// EXAMPLE 7: State management +console.log( '\n=== Example 7: State Management ===' ); + +var stateRng = xorshift128plus({ + 'seed': BigInt(555) +}); + +console.log( 'Initial values:' ); +console.log( ' %s', stateRng() ); +console.log( ' %s', stateRng() ); + +var savedState = stateRng.state; +console.log( 'State saved' ); + +console.log( 'Continue generating:' ); +console.log( ' %s', stateRng() ); +console.log( ' %s', stateRng() ); + +stateRng.state = savedState; +console.log( 'State restored, same values:' ); +console.log( ' %s (should be same as value 3)', stateRng() ); +console.log( ' %s (should be same as value 4)', stateRng() ); + +// EXAMPLE 8: Copying a generator +console.log( '\n=== Example 8: Generator Copy ===' ); + +var original = xorshift128plus({ + 'seed': BigInt(333) +}); +var duplicate = original.copy(); + +console.log( 'Original: %s', original() ); +console.log( 'Copy: %s', duplicate() ); + +console.log( 'Both continue with same sequence (initially):' ); +console.log( 'Original: %s', original() ); +console.log( 'Copy: %s', duplicate() ); + +console.log( 'But now they are independent:' ); +console.log( 'Original: %s', original() ); +console.log( 'Copy: %s', duplicate() ); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js new file mode 100644 index 000000000000..d79af0a718b5 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js @@ -0,0 +1,177 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var BigInt = require( '@stdlib/bigint/ctor' ); +var xorshift128plus = require( './../lib' ); +var match; +var valA; +var valB; + +// Generate pseudorandom 64-bit integers... +console.log( '\n=== Pseudorandom 64-bit Integers ===' ); +console.log( 'seed: %s', BigInt(12345) ); + +var rng = xorshift128plus({ + 'seed': BigInt(12345) +}); + +var i; +for ( i = 0; i < 10; i++ ) { + console.log( rng().toString() ); +} + +// Generate normalized random numbers in [0, 1)... +console.log( '\n=== Normalized Random Numbers [0, 1) ===' ); + +rng = xorshift128plus({ + 'seed': BigInt(12345) +}); + +for ( i = 0; i < 10; i++ ) { + console.log( rng.normalized() ); +} + +// Create a new pseudorandom number generator with a custom seed... +console.log( '\n=== Custom Seed ===' ); + +var seed = BigInt(54321); +var rand = xorshift128plus({ + 'seed': seed +}); + +console.log( 'seed: %s', seed ); +for ( i = 0; i < 10; i++ ) { + console.log( rand().toString() ); +} + +// Create another pseudorandom number generator using a previous seed... +console.log( '\n=== Using Previous Seed ===' ); + +rand = xorshift128plus({ + 'seed': BigInt(99999) +}); +var previousSeed = rand.seed; + +// Generate some values +for ( i = 0; i < 5; i++ ) { + rand(); +} + +// Create a new generator with the previous seed +rand = xorshift128plus({ + 'seed': previousSeed +}); + +console.log( 'seed: %s', previousSeed ); +for ( i = 0; i < 10; i++ ) { + console.log( rand().toString() ); +} + +// Demonstrate state management... +console.log( '\n=== State Management ===' ); + +var rng1 = xorshift128plus({ + 'seed': BigInt(777) +}); +console.log( 'Generated values: ' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', rng1().toString() ); +} + +// Save state +var state = rng1.state; +console.log( 'State saved' ); + +// Generate more values +console.log( 'Generated more values:' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', rng1().toString() ); +} + +// Restore state +rng1.state = state; +console.log( 'State restored' ); + +// Generate the same values as before +console.log( 'Same values regenerated:' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', rng1().toString() ); +} + +// Demonstrate generator copying... +console.log( '\n=== Generator Copying ===' ); + +var original = xorshift128plus({ + 'seed': BigInt(555) +}); +console.log( 'Original generator:' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', original().toString() ); +} + +var copy = original.copy(); +console.log( 'Copied generator (should produce same sequence):' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', copy().toString() ); +} + +// Now they diverge +console.log( 'Original continues:' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', original().toString() ); +} + +console.log( 'Copy continues (different):' ); +for ( i = 0; i < 5; i++ ) { + console.log( ' %s', copy().toString() ); +} + +// Demonstrate reproducibility... +console.log( '\n=== Reproducibility ===' ); + +var rngA = xorshift128plus({ + 'seed': BigInt(888) +}); +var rngB = xorshift128plus({ + 'seed': BigInt(888) +}); + +console.log( 'Both generators with same seed produce identical sequences:' ); +for ( i = 0; i < 10; i++ ) { + valA = rngA(); + valB = rngB(); + match = ( valA === valB ) ? '✓' : '✗'; + console.log( ' %s %s === %s', match, valA.toString(), valB.toString() ); +} + +// Demonstrate JSON serialization... +console.log( '\n=== JSON Serialization ===' ); + +var jsonRng = xorshift128plus({ + 'seed': BigInt(333) +}); +var json = jsonRng.toJSON(); + +console.log( 'Serialized state:' ); +console.log( ' type: %s', json.type ); +console.log( ' name: %s', json.name ); +console.log( ' state length: %d', json.state.length ); +console.log( 'Full JSON object:' ); +console.log( json ); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js new file mode 100644 index 000000000000..32f4152a5ced --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js @@ -0,0 +1,438 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +/** +* Xorshift128+ pseudorandom number generator (PRNG). +* +* ## Algorithm +* +* The Xorshift128+ algorithm generates 64-bit pseudorandom numbers by +* maintaining two 64-bit state values and performing XOR and shift operations. +* +* ## Notes +* +* - Uses JavaScript BigInt for 64-bit arithmetic. +* - State consists of two 64-bit values: s0 and s1. +* - Period: approximately 2^128. +* +* @example +* var xorshift128plus = require( '@stdlib/random/base/xorshift128plus' ); +* +* var rng = xorshift128plus({ +* 'seed': BigInt(12345) +* }); +* +* var v = rng(); +* // returns +*/ + +'use strict'; + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var setReadOnlyAccessor = require( '@stdlib/utils/define-nonenumerable-read-only-accessor' ); +var setReadWriteAccessor = require( '@stdlib/utils/define-nonenumerable-read-write-accessor' ); +var hasOwnProp = require( '@stdlib/assert/has-own-property' ); +var isObject = require( '@stdlib/assert/is-plain-object' ); +var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; +var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ); +var isBigInt = require( '@stdlib/assert/is-bigint' ); +var BigInt = require( '@stdlib/bigint/ctor' ); +var Number = require( '@stdlib/number/ctor' ); +var randu = require( '@stdlib/random/base/randu' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var format = require( '@stdlib/string/format' ); + + +// VARIABLES // + +/* eslint-disable no-magic-numbers */ + +/** +* State array schema version. +* +* @private +* @type {bigint} +*/ +var STATE_ARRAY_VERSION = BigInt( 1 ); + +/** +* Number of state elements (2 × 64-bit values). +* +* @private +* @type {bigint} +*/ +var NUM_STATE_ELEMENTS = BigInt( 2 ); + +/** +* Total state array length:. +* [version | state_length | state[0] | state[1] | seed_length | seed] +* +* @private +* @type {number} +*/ +var STATE_ARRAY_SIZE = 6; + +/** +* State array indices. +* +* @private +* @type {number} +*/ +var VERSION_INDEX = 0; +var STATE_LENGTH_INDEX = 1; +var STATE_OFFSET = 2; +var SEED_LENGTH_INDEX = 4; +var SEED_OFFSET = 5; + +/** +* Maximum value for a 64-bit unsigned integer. +* +* @private +* @type {bigint} +*/ +var UINT64_MAX_BIGINT = BigInt( '0xffffffffffffffff' ); + +/** +* 2^64 as BigInt for normalization. +* +* @private +* @type {bigint} +*/ +var TWO_64 = BigInt( '0x10000000000000000' ); + +/** +* Normalization constant for converting uint64 to [0,1). +* +* @private +* @type {number} +*/ +var NORMALIZATION_CONSTANT = 1.0 / Number( TWO_64 ); + +/* eslint-enable no-magic-numbers */ + + +// FUNCTIONS // + +/** +* Initializes the internal PRNG state from a seed. +* +* @private +* @param {bigint} seed - seed value +* @returns {Array} state array with two 64-bit values +*/ +function initializeState( seed ) { + var MULTIPLIER_1 = BigInt( '0x9e3779b97f4a7c15' ); + var MULTIPLIER_2 = BigInt( '0xbf58476d1ce4e5b9' ); + var state = [ BigInt( 0 ), BigInt( 0 ) ]; + + state[ 0 ] = (seed ^ MULTIPLIER_1) & UINT64_MAX_BIGINT; + state[ 1 ] = (seed ^ MULTIPLIER_2) & UINT64_MAX_BIGINT; + + if ( state[ 0 ] === BigInt( 0 ) && state[ 1 ] === BigInt( 0 ) ) { + state[ 0 ] = BigInt( 1 ); + } + + return state; +} + +/** +* Verifies state array integrity. +* +* @private +* @param {Array} stateArray - state array +* @returns {(Error|null)} error or null +*/ +function verifyState( stateArray ) { + if ( !Array.isArray( stateArray ) ) { + return new TypeError( 'invalid state array. State must be an Array.' ); + } + + if ( stateArray.length !== STATE_ARRAY_SIZE ) { + return new RangeError(format('invalid state array. Expected length %u. Got %u.', STATE_ARRAY_SIZE, stateArray.length)); + } + + if ( stateArray[ VERSION_INDEX ] !== STATE_ARRAY_VERSION ) { + return new RangeError(format('invalid state array. Unsupported version %u.', stateArray[ VERSION_INDEX ])); + } + + if ( stateArray[ STATE_LENGTH_INDEX ] !== NUM_STATE_ELEMENTS ) { + return new RangeError(format('invalid state array. Expected state length %u. Got %u.', NUM_STATE_ELEMENTS, stateArray[ STATE_LENGTH_INDEX ])); + } + + if ( typeof stateArray[ STATE_OFFSET ] !== 'bigint' ) { + return new TypeError( 'invalid state array. State[0] must be a BigInt.' ); + } + + if ( typeof stateArray[ STATE_OFFSET + 1 ] !== 'bigint' ) { + return new TypeError( 'invalid state array. State[1] must be a BigInt.' ); + } + + return null; +} + + +// MAIN // + +/** +* Returns an Xorshift128+ pseudorandom number generator. +* +* @param {Object} [options] - configuration object +* @param {(number|bigint)} [options.seed] - seed value +* @param {Array} [options.state] - generator state +* @param {boolean} [options.copy=true] - copy state +* @throws {TypeError} options must be an object +* @throws {TypeError} invalid option value +* @throws {RangeError} invalid state array +* @returns {Function} PRNG function +*/ +function factory( options ) { + var STATE; + var state; + var seed; + var opts; + var err; + var tmp; + var i; + + opts = {}; + if ( arguments.length ) { + if ( !isObject( options ) ) { + throw new TypeError(format('invalid argument. Options must be an object. Received: %s', typeof options)); + } + + if ( hasOwnProp( options, 'copy' ) ) { + opts.copy = options.copy; + if ( !isBoolean( options.copy ) ) { + throw new TypeError(format('invalid option. `copy` must be a boolean. Received: %s', typeof options.copy)); + } + } + + if ( hasOwnProp( options, 'state' ) ) { + STATE = options.state; + opts.state = true; + + if ( !Array.isArray( STATE ) ) { + throw new TypeError('invalid option. `state` must be an Array.'); + } + + err = verifyState( STATE ); + if ( err ) { + throw err; + } + + if ( opts.copy !== false ) { + tmp = []; + tmp.length = STATE_ARRAY_SIZE; + for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { + tmp[ i ] = STATE[ i ]; + } + STATE = tmp; + } + } + + if ( !opts.state ) { + if ( hasOwnProp( options, 'seed' ) ) { + seed = options.seed; + opts.seed = true; + + if ( typeof seed === 'number' ) { + if ( !isNonNegativeInteger( seed ) ) { + throw new TypeError('invalid option. `seed` must be a non-negative integer or BigInt.'); + } + seed = BigInt( seed ); + } else if ( isBigInt( seed ) ) { + if ( seed < BigInt( 0 ) ) { + throw new RangeError('invalid option. `seed` must be a non-negative BigInt.'); + } + } else { + throw new TypeError('invalid option. `seed` must be a non-negative integer or BigInt.'); + } + + if ( seed === BigInt( 0 ) ) { + seed = BigInt( 1 ); + } + } else { + seed = BigInt( floor( randu() * 0x100000000 ) ) * BigInt( '0x100000000' ); + seed |= BigInt( floor( randu() * 0x100000000 ) ); + if ( seed === BigInt( 0 ) ) { + seed = BigInt( 1 ); + } + } + } + } else { + seed = BigInt( floor( randu() * 0x100000000 ) ) * BigInt( '0x100000000' ); + seed |= BigInt( floor( randu() * 0x100000000 ) ); + if ( seed === BigInt( 0 ) ) { + seed = BigInt( 1 ); + } + } + + if ( STATE === void 0 ) { + state = initializeState( seed ); + STATE = []; + STATE.length = STATE_ARRAY_SIZE; + STATE[ VERSION_INDEX ] = STATE_ARRAY_VERSION; + STATE[ STATE_LENGTH_INDEX ] = NUM_STATE_ELEMENTS; + STATE[ STATE_OFFSET ] = state[ 0 ]; + STATE[ STATE_OFFSET + 1 ] = state[ 1 ]; + STATE[ SEED_LENGTH_INDEX ] = BigInt( 1 ); + STATE[ SEED_OFFSET ] = seed; + } + + /** + * Generates a pseudorandom 64-bit unsigned integer. + * + * @private + * @returns {bigint} pseudorandom 64-bit integer + */ + function next() { + var s1 = STATE[ STATE_OFFSET ]; + var s0 = STATE[ STATE_OFFSET + 1 ]; + + STATE[ STATE_OFFSET ] = s0; + + s1 ^= (s1 << BigInt( 23 )); + s1 ^= (s1 >> BigInt( 18 )); + s1 ^= s0; + s0 ^= (s0 >> BigInt( 5 )); + + STATE[ STATE_OFFSET + 1 ] = (s1 ^ s0) & UINT64_MAX_BIGINT; + + return ((s1 ^ s0) + s0) & UINT64_MAX_BIGINT; + } + + /** + * Generates a pseudorandom number on [0, 1). + * + * @private + * @returns {number} pseudorandom number in [0, 1) + */ + function norm() { + return Number( next() ) * NORMALIZATION_CONSTANT; + } + + /** + * Returns the current state. + * + * @private + * @returns {Array} state array + */ + function getState() { + var out = []; + var i; + out.length = STATE_ARRAY_SIZE; + for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { + out[ i ] = STATE[ i ]; + } + return out; + } + + /** + * Sets the state. + * + * @private + * @param {Array} s - new state + * @throws {TypeError} invalid state type + * @throws {RangeError} invalid state + */ + function setState( s ) { + var e; + var i; + if ( !Array.isArray( s ) ) { + throw new TypeError('invalid argument. `state` must be an Array.'); + } + + e = verifyState( s ); + if ( e ) { + throw e; + } + + if ( opts.copy === false ) { + if ( opts.state && s.length === STATE.length ) { + for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { + STATE[ i ] = s[ i ]; + } + } else { + STATE = s; + opts.state = true; + } + } else { + if ( s.length !== STATE.length ) { + STATE = []; + STATE.length = STATE_ARRAY_SIZE; + } + for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { + STATE[ i ] = s[ i ]; + } + } + } + + /** + * Returns a copy of the PRNG. + * + * @private + * @returns {Function} copy + */ + function copy() { + return factory({ + 'state': getState(), + 'copy': true + }); + } + + /** + * Serializes the state. + * + * @private + * @returns {Object} JSON object + */ + function toJSON() { + return { + 'type': 'PRNG', + 'name': 'xorshift128+', + 'state': Array.from( STATE ), + 'params': [] + }; + } + + /** + * Returns the seed. + * + * @private + * @returns {bigint} seed + */ + function getSeed() { + return STATE[ SEED_OFFSET ]; + } + + setReadOnly( next, 'NAME', 'xorshift128+' ); + setReadOnly( next, 'normalized', norm ); + setReadOnly( next, 'copy', copy ); + setReadOnly( next, 'toJSON', toJSON ); + setReadOnlyAccessor( next, 'seed', getSeed ); + setReadWriteAccessor( next, 'state', getState, setState ); + + return next; +} + + +// EXPORTS // + +module.exports = factory; diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js new file mode 100644 index 000000000000..c86ce9dd3ebd --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js @@ -0,0 +1,54 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Xorshift128+ pseudorandom number generator. +* +* @module @stdlib/random/base/xorshift128 +* +* @example +* var xorshift128 = require( '@stdlib/random/base/xorshift128' ); +* +* // Create a PRNG with a seed +* var rng = xorshift128( { seed: 12345n } ); +* // returns +* +* var v = rng(); +* // returns +* +* @example +* var xorshift128 = require( '@stdlib/random/base/xorshift128' ); +* +* // Without arguments, creates with random seed +* var rng = xorshift128(); +* // returns +* +* var v = rng(); +* // returns +*/ + +// MODULES // + +var factory = require( './factory.js' ); + + +// EXPORTS // + +module.exports = factory; diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js new file mode 100644 index 000000000000..49ca6703919e --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js @@ -0,0 +1,62 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Default Xorshift128+ PRNG instance. +* +* Note: This file is provided for backward compatibility with stdlib patterns. +* Most users should use the factory directly via index.js. +*/ + +// MODULES // + +var factory = require( './factory.js' ); +var randi32 = require( './rand_int64.js' ); + + +// MAIN // + +/** +* Default Xorshift128+ PRNG instance. +* +* This is a pre-created PRNG instance with a random seed. +* It can be used directly for generating random numbers. +* +* @name xorshift128plus +* @type {Function} +* @returns {bigint} pseudorandom 64-bit unsigned integer +* +* @example +* var xorshift128plus = require( '@stdlib/random/base/xorshift128/lib/main.js' ); +* +* var v = xorshift128plus(); +* // returns +* +* var v = xorshift128plus.normalized(); +* // returns +*/ +var xorshift128plus = factory({ + 'seed': randi32() +}); + + +// EXPORTS // + +module.exports = xorshift128plus; diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js new file mode 100644 index 000000000000..3ab43f901970 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js @@ -0,0 +1,71 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Generates random 32-bit integers for seed generation. +* +* This module generates random 32-bit unsigned integer seed values +* using Math.random(). These are used to seed the Xorshift128+ PRNG +* when no explicit seed is provided. +* +* Two 32-bit values are combined to create a 64-bit seed: +* seed = (high << 32) | low +* +* This provides better entropy than using a single 32-bit value. +*/ + +// MODULES // + +var randu = require( '@stdlib/random/base/randu' ); +var floor = require( '@stdlib/math/base/special/floor' ); +var BigInt = require( '@stdlib/bigint/ctor' ); + +/** +* Generates a random 32-bit unsigned integer. +* +* @private +* @returns {bigint} random 32-bit value as BigInt +* +* @example +* var seed = randi32(); +* // throws +*/ +function randi32() { + var seed; + var high; + var low; + + // Generate two 32-bit values and combine them into a 64-bit value + high = floor( randu() * 0x100000000 ); + low = floor( randu() * 0x100000000 ); + seed = (BigInt( high ) << BigInt(32)) | BigInt( low ); + + // Ensure non-zero seed + if ( seed === BigInt(0) ) { + seed = BigInt(1); + } + + return seed; +} + + +// EXPORTS // + +module.exports = randi32; diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/package.json b/lib/node_modules/@stdlib/random/base/xorshift128/package.json new file mode 100644 index 000000000000..192b5f9bd494 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/package.json @@ -0,0 +1,105 @@ +{ + "name": "@stdlib/random/base/xorshift128plus", + "version": "0.1.0", + "description": "A 128-bit xorshift pseudorandom number generator (PRNG) with a period of approximately 2^128.", + "license": "Apache-2.0", + "author": { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + }, + "contributors": [ + { + "name": "The Stdlib Authors", + "url": "https://github.com/stdlib-js/stdlib/graphs/contributors" + } + ], + "main": "./lib/index.js", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "include": "./include", + "lib": "./lib", + "src": "./src", + "test": "./test" + }, + "types": "./docs/types/index.d.ts", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git", + "directory": "lib/node_modules/@stdlib/random/base/xorshift128plus" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=12.0.0", + "npm": ">2.7.0" + }, + "env": { + "node": true, + "es2020": true + }, + "parserOptions": { + "ecmaVersion": 2020, + "sourceType": "script" + }, + "rules": { + "no-magic-numbers": [ + "error", + { + "ignore": [ + -1, + 0, + 1, + 2 + ], + "ignoreArrayIndexes": true + } + ] + }, + "os": [ + "aix", + "darwin", + "freebsd", + "linux", + "macos", + "openbsd", + "sunos", + "win32", + "windows" + ], + "keywords": [ + "stdlib", + "stdmath", + "mathematics", + "math", + "statistics", + "stats", + "prng", + "pseudorandom", + "random", + "rand", + "randint", + "randu", + "uniform", + "generator", + "xorshift", + "xorshift128+", + "xorshift128plus", + "xor", + "shift", + "mersenne", + "twister", + "seed", + "seedable", + "bigint", + "64-bit", + "period", + "equidistribution" + ] +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js new file mode 100644 index 000000000000..a192ab8f5fc7 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js @@ -0,0 +1,519 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var isBigInt = require( '@stdlib/assert/is-bigint' ); +var BigInt = require( '@stdlib/bigint/ctor' ); +var xorshift128plus = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof xorshift128plus, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'calling the function without arguments returns a PRNG function', function test( t ) { + var rng = xorshift128plus(); + t.strictEqual( typeof rng, 'function', 'returns a function' ); + t.end(); +}); + +tape( 'calling with empty options object returns a PRNG function', function test( t ) { + var rng = xorshift128plus( {} ); + t.strictEqual( typeof rng, 'function', 'returns a function' ); + t.end(); +}); + +tape( 'calling with a number seed returns a PRNG function', function test( t ) { + var rng = xorshift128plus({ + 'seed': 12345 + }); + t.strictEqual( typeof rng, 'function', 'returns a function' ); + t.end(); +}); + +tape( 'calling with a BigInt seed returns a PRNG function', function test( t ) { + var rng = xorshift128plus({ + 'seed': BigInt( 12345 ) + }); + t.strictEqual( typeof rng, 'function', 'returns a function' ); + t.end(); +}); + +tape( 'seeded generators with same seed produce identical sequences', function test( t ) { + var rng1 = xorshift128plus({ + 'seed': BigInt( 54321 ) + }); + var rng2 = xorshift128plus({ + 'seed': BigInt( 54321 ) + }); + var i; + + for ( i = 0; i < 100; i++ ) { + t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); + } + t.end(); +}); + +tape( 'different seeds produce different sequences', function test( t ) { + var different = 0; + var rng1 = xorshift128plus({ + 'seed': BigInt( 111 ) + }); + var rng2 = xorshift128plus({ + 'seed': BigInt( 222 ) + }); + var i; + + for ( i = 0; i < 100; i++ ) { + if ( rng1().toString() !== rng2().toString() ) { + different += 1; + } + } + t.strictEqual( different > 95, true, 'most values are different' ); + t.end(); +}); + +tape( 'zero seed is converted to 1n', function test( t ) { + var rng1 = xorshift128plus({ + 'seed': BigInt( 0 ) + }); + var rng2 = xorshift128plus({ + 'seed': BigInt( 1 ) + }); + var i; + + for ( i = 0; i < 50; i++ ) { + t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); + } + t.end(); +}); + +tape( 'accepts number seed and converts to BigInt', function test( t ) { + var rng1 = xorshift128plus({ + 'seed': 12345 + }); + var rng2 = xorshift128plus({ + 'seed': BigInt( 12345 ) + }); + var i; + + for ( i = 0; i < 50; i++ ) { + t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); + } + t.end(); +}); + +tape( 'the PRNG returns BigInt values', function test( t ) { + var rng = xorshift128plus({ + 'seed': BigInt( 42 ) + }); + var v; + var i; + + for ( i = 0; i < 100; i++ ) { + v = rng(); + t.strictEqual( isBigInt( v ), true, 'iteration '+i+': returns BigInt' ); + } + t.end(); +}); + +tape( 'the PRNG returns values in [0, 2^64)', function test( t ) { + var rng = xorshift128plus({ + 'seed': BigInt( 42 ) + }); + var max = BigInt( '0xffffffffffffffff' ); + var v; + var i; + + for ( i = 0; i < 100; i++ ) { + v = rng(); + t.strictEqual( v >= BigInt( 0 ) && v <= max, true, 'iteration '+i+': value in valid range' ); + } + t.end(); +}); + +tape( 'the normalized method returns numbers in [0, 1)', function test( t ) { + var rng = xorshift128plus({ + 'seed': BigInt( 42 ) + }); + var v; + var i; + + for ( i = 0; i < 1000; i++ ) { + v = rng.normalized(); + t.strictEqual( typeof v, 'number', 'iteration '+i+': returns number' ); + t.strictEqual( v >= 0.0 && v < 1.0, true, 'iteration '+i+': in [0, 1)' ); + } + t.end(); +}); + +tape( 'normalized sequences are deterministic', function test( t ) { + var rng1 = xorshift128plus({ + 'seed': BigInt( 99999 ) + }); + var rng2 = xorshift128plus({ + 'seed': BigInt( 99999 ) + }); + var i; + + for ( i = 0; i < 100; i++ ) { + t.strictEqual( rng1.normalized(), rng2.normalized(), 'iteration '+i+': same normalized output' ); + } + t.end(); +}); + +tape( 'the PRNG has a seed property', function test( t ) { + var seed; + var rng = xorshift128plus({ + 'seed': BigInt( 12345 ) + }); + seed = rng.seed; + + t.strictEqual( isBigInt( seed ), true, 'seed is BigInt' ); + t.strictEqual( seed, BigInt( 12345 ), 'seed value is correct' ); + t.end(); +}); + +tape( 'the PRNG has a state property', function test( t ) { + var state; + var rng = xorshift128plus({ + 'seed': BigInt( 12345 ) + }); + state = rng.state; + + t.strictEqual( Array.isArray( state ), true, 'state is Array' ); + t.strictEqual( state.length, 6, 'state has correct length' ); + t.strictEqual( state[ 0 ], BigInt( 1 ), 'version is 1n' ); + t.strictEqual( state[ 1 ], BigInt( 2 ), 'state length is 2n' ); + t.strictEqual( isBigInt( state[ 2 ] ), true, 'state[0] is BigInt' ); + t.strictEqual( isBigInt( state[ 3 ] ), true, 'state[1] is BigInt' ); + t.strictEqual( state[ 4 ], BigInt( 1 ), 'seed length is 1n' ); + t.strictEqual( state[ 5 ], BigInt( 12345 ), 'seed is stored' ); + t.end(); +}); + +tape( 'calling .copy() returns an independent PRNG with same state', function test( t ) { + var rng1 = xorshift128plus({ + 'seed': BigInt( 54321 ) + }); + var rng2; + var v1; + var v2; + var i; + + // Generate some values to advance state + for ( i = 0; i < 50; i++ ) { + rng1(); + } + + // Copy the PRNG + rng2 = rng1.copy(); + + // Both should generate identical sequences from this point + for ( i = 0; i < 100; i++ ) { + v1 = rng1(); + v2 = rng2(); + t.strictEqual( v1.toString(), v2.toString(), 'iteration '+i+': identical output' ); + } + t.end(); +}); + +tape( 'setting state via .state property restores sequence', function test( t ) { + var state; + var rng = xorshift128plus({ + 'seed': BigInt( 54321 ) + }); + var arr; + var i; + + // Generate some values + for ( i = 0; i < 100; i++ ) { + rng(); + } + + // Capture state + state = rng.state; + + // Generate more values + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( rng() ); + } + + // Restore state + rng.state = state; + + // Verify sequence is replayed + for ( i = 0; i < 100; i++ ) { + t.strictEqual( rng().toString(), arr[ i ].toString(), 'iteration '+i+': restored sequence' ); + } + t.end(); +}); + +tape( 'copy option=true makes independent copy', function test( t ) { + var state = [ + BigInt( 1 ), + BigInt( 2 ), + BigInt( 12345 ), + BigInt( 67890 ), + BigInt( 1 ), + BigInt( 12345 ) + ]; + var rng1 = xorshift128plus({ + 'state': state, + 'copy': true + }); + var rng2 = xorshift128plus({ + 'state': state, + 'copy': true + }); + var v1; + var v2; + + state[ 2 ] = BigInt( 99999 ); // Modify original state array + + v1 = rng1(); + v2 = rng2(); + + t.strictEqual( v1.toString(), v2.toString(), 'copies are independent of original' ); + t.end(); +}); + +tape( 'the PRNG has a toJSON method', function test( t ) { + var json; + var rng = xorshift128plus({ + 'seed': BigInt( 12345 ) + }); + json = rng.toJSON(); + + t.strictEqual( typeof json, 'object', 'returns object' ); + t.strictEqual( json.type, 'PRNG', 'type is PRNG' ); + t.strictEqual( json.name, 'xorshift128+', 'name is correct' ); + t.strictEqual( Array.isArray( json.state ), true, 'state is array' ); + t.strictEqual( json.state.length, 6, 'state array has correct length' ); + t.end(); +}); + +tape( 'the PRNG has a NAME property', function test( t ) { + var rng = xorshift128plus(); + t.strictEqual( rng.NAME, 'xorshift128+', 'NAME is correct' ); + t.end(); +}); + +tape( 'throws error if options is not an object', function test( t ) { + var values; + var i; + + values = [ + 'string', + 123, + true, + null, + undefined, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift128plus( value ); + }; + } +}); + +tape( 'throws error if seed is not a number or BigInt', function test( t ) { + var values; + var i; + + values = [ + 'string', + true, + null, + undefined, + {}, + [] + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift128plus({ + 'seed': value + }); + }; + } +}); + +tape( 'throws error if copy option is not a boolean', function test( t ) { + var values = [ 'string', 123, null, undefined, {}, [] ]; + var i; + + for ( i = 0; i < values.length; i++ ) { + t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift128plus({ + 'copy': value + }); + }; + } +}); + +tape( 'throws error if state is not an Array', function test( t ) { + var values = [ 'string', 123, true, null, undefined, {}, function noop() {} ]; + var i; + + for ( i = 0; i < values.length; i++ ) { + t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift128plus({ + 'state': value + }); + }; + } +}); + +tape( 'throws error if state has incorrect length', function test( t ) { + var values = [ + [], + [ BigInt( 1 ) ], + [ BigInt( 1 ), BigInt( 2 ) ] + ]; + var i; + + for ( i = 0; i < values.length; i++ ) { + t.throws(badValue( values[ i ] ), RangeError, 'throws RangeError for length '+values[ i ].length); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift128plus({ + 'state': value + }); + }; + } +}); + +tape( 'throws error if state has incorrect version', function test( t ) { + var state = [ + BigInt( 0 ), + BigInt( 2 ), + BigInt( 12345 ), + BigInt( 67890 ), + BigInt( 1 ), + BigInt( 12345 ) + ]; + + t.throws(function testFn() { + xorshift128plus({ + 'state': state + }); + }, RangeError, 'throws RangeError for invalid version'); + t.end(); +}); + +tape( 'throws error if state has incorrect state length', function test( t ) { + var state = [ + BigInt( 1 ), + BigInt( 1 ), + BigInt( 12345 ), + BigInt( 67890 ), + BigInt( 1 ), + BigInt( 12345 ) + ]; + + t.throws(function testFn() { + xorshift128plus({ + 'state': state + }); + }, RangeError, 'throws RangeError for invalid state length'); + t.end(); +}); + +tape( 'the PRNG has good period (state doesn\'t cycle quickly)', function test( t ) { + var firstVal; + var found; + var rng; + var i; + + rng = xorshift128plus({ + 'seed': BigInt( 42 ) + }); + firstVal = rng(); + found = false; + + // Generate 10000 values and check we don't see the initial state repeated + for ( i = 1; i < 10000; i++ ) { + if ( rng().toString() === firstVal.toString() ) { + found = true; + break; + } + } + + t.strictEqual( found, false, 'no premature cycling detected in 10000 iterations' ); + t.end(); +}); + +tape( 'normalized output is reasonably uniform', function test( t ) { + var ratio; + var high = 0; + var rng = xorshift128plus({ + 'seed': BigInt( 42 ) + }); + var low = 0; + var v; + var i; + + for ( i = 0; i < 10000; i++ ) { + v = rng.normalized(); + if ( v < 0.5 ) { + low += 1; + } else { + high += 1; + } + } + + ratio = low / high; + t.strictEqual( ratio > 0.9 && ratio < 1.1, true, 'distribution is approximately uniform' ); + t.end(); +}); From fc0ce90b25047a08c2fdec26b531ab0087bc16ca Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Mon, 23 Mar 2026 07:24:47 +0000 Subject: [PATCH 2/7] fix: correct README usage --- .../@stdlib/random/base/xorshift128/README.md | 144 ++++++++---------- 1 file changed, 61 insertions(+), 83 deletions(-) diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/README.md b/lib/node_modules/@stdlib/random/base/xorshift128/README.md index 13ba08fb4399..42d86347f322 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/README.md +++ b/lib/node_modules/@stdlib/random/base/xorshift128/README.md @@ -27,33 +27,37 @@ limitations under the License. ## Usage ```javascript -var xorshift128plus = require( '@stdlib/random/base/xorshift128' ); +var factory = require( '@stdlib/random/base/xorshift128' ); ``` -#### xorshift128plus() +#### factory() -Returns a pseudorandom 64-bit unsigned integer. +Returns a xorshift128+ pseudorandom number generator. ```javascript -var r = xorshift128plus(); +var rng = factory(); + +var r = rng(); // returns ``` -#### xorshift128plus.normalized() +#### factory.normalized() Returns a pseudorandom number on the interval `[0,1)`. ```javascript -var r = xorshift128plus.normalized(); +var rng = factory(); + +var r = rng.normalized(); // returns ``` -#### xorshift128plus.factory( [options] ) +#### factory( [options] ) Returns a xorshift128+ pseudorandom number generator ([PRNG][xorshift]). ```javascript -var rand = xorshift128plus.factory(); +var rng = factory(); ``` The function accepts the following `options`: @@ -62,121 +66,108 @@ The function accepts the following `options`: - **state**: a state array (Array) containing pseudorandom number generator state. If provided, the function ignores the `seed` option. - **copy**: `boolean` indicating whether to copy a provided pseudorandom number generator state. Setting this option to `false` allows sharing state between two or more pseudorandom number generators. Setting this option to `true` ensures that a returned generator has exclusive control over its internal state. Default: `true`. -By default, a random seed is used to seed the returned generator. To seed the generator, provide either a non-negative integer +By default, a random seed is used to seed the returned generator. To seed the generator, provide either a non-negative integer: ```javascript -var rand = xorshift128plus.factory({ - 'seed': BigInt(1234) +var BigInt = require( '@stdlib/bigint/ctor' ); + +var rng = factory({ + 'seed': BigInt( 1234 ) }); -var r = rand(); +var r = rng(); // returns ``` -or, for arbitrary length seeds, a BigInt value +or, for additional control, a BigInt value: ```javascript -var rand = xorshift128plus.factory({ +var BigInt = require( '@stdlib/bigint/ctor' ); + +var rng = factory({ 'seed': BigInt( 1234 ) }); -var r = rand(); +var r = rng(); // returns ``` -To return a generator having a specific initial state, set the generator `state` option. +To return a generator having a specific initial state, set the generator `state` option: ```javascript -// Generate pseudorandom numbers, thus progressing the generator state: +var rng1 = factory(); + var r; var i; for ( i = 0; i < 1000; i++ ) { - r = xorshift128plus(); + r = rng1(); } -// Create a new PRNG initialized to the current state of `xorshift128plus`: -var rand = xorshift128plus.factory({ - 'state': xorshift128plus.state +var state = rng1.state; + +var rng2 = factory({ + 'state': state }); -// Test that the generated pseudorandom numbers are the same: -var bool = ( rand() === xorshift128plus() ); +var bool = ( rng2() === rng1() ); // returns true ``` -#### xorshift128plus.NAME +#### factory.NAME The generator name. ```javascript -var str = xorshift128plus.NAME; +var str = factory.NAME; // returns 'xorshift128+' ``` -#### xorshift128plus.seed +#### rng.seed -The value used to seed `xorshift128plus()`. +The value used to seed the generator. ```javascript -// Generate pseudorandom values... -var r; -var i; -for ( i = 0; i < 100; i++ ) { - r = xorshift128plus(); -} +var BigInt = require( '@stdlib/bigint/ctor' ); -// Generate the same pseudorandom values... -var rand = xorshift128plus.factory({ - 'seed': xorshift128plus.seed +var rng = factory({ + 'seed': BigInt( 1234 ) }); -for ( i = 0; i < 100; i++ ) { - r = rand(); -} + +var seed = rng.seed; +// returns ``` -#### xorshift128plus.state +#### rng.state Writable property for getting and setting the generator state. ```javascript -var r = xorshift128plus(); -// returns +var rng = factory(); -r = xorshift128plus(); +var r = rng(); // returns -// ... - -// Get the current state: -var state = xorshift128plus.state; +var state = rng.state; // returns -r = xorshift128plus(); -// returns - -r = xorshift128plus(); +r = rng(); // returns -// Reset the state: -xorshift128plus.state = state; +rng.state = state; -// Replay the last two pseudorandom numbers: -r = xorshift128plus(); +r = rng(); // returns - -r = xorshift128plus(); -// returns - -// ... ``` -#### xorshift128plus.toJSON() +#### rng.toJSON() Serializes the pseudorandom number generator as a JSON object. ```javascript -var o = xorshift128plus.toJSON(); -// returns { 'type': 'PRNG', 'name': '...', 'state': [...], 'params': [] } +var rng = factory(); + +var o = rng.toJSON(); +// returns { 'type': 'PRNG', 'name': 'xorshift128+', 'state': [...], 'params': [] } ``` @@ -206,29 +197,16 @@ var o = xorshift128plus.toJSON(); ```javascript -var xorshift128plus = require( '@stdlib/random/base/xorshift128plus' ); +var factory = require( '@stdlib/random/base/xorshift128' ); +var BigInt = require( '@stdlib/bigint/ctor' ); -// Generate pseudorandom numbers... -var i; -for ( i = 0; i < 100; i++ ) { - console.log( xorshift128plus() ); -} - -// Create a new pseudorandom number generator... -var seed = BigInt(1234); -var rand = xorshift128plus.factory({ - 'seed': seed +var rng = factory({ + 'seed': BigInt( 1234 ) }); -for ( i = 0; i < 100; i++ ) { - console.log( rand() ); -} -// Create another pseudorandom number generator using a previous seed... -rand = xorshift128plus.factory({ - 'seed': xorshift128plus.seed -}); -for ( i = 0; i < 100; i++ ) { - console.log( rand() ); +var i; +for ( i = 0; i < 10; i++ ) { + console.log( rng() ); } ``` From fff3a2578431cdf9c13193b28c5b21791e8de1c7 Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Mon, 23 Mar 2026 08:02:19 +0000 Subject: [PATCH 3/7] fix: lint error --- .../@stdlib/random/base/xorshift128/README.md | 6 ++-- .../random/base/xorshift128/package.json | 29 ++----------------- 2 files changed, 7 insertions(+), 28 deletions(-) diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/README.md b/lib/node_modules/@stdlib/random/base/xorshift128/README.md index 42d86347f322..d025d2ec2297 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/README.md +++ b/lib/node_modules/@stdlib/random/base/xorshift128/README.md @@ -52,7 +52,7 @@ var r = rng.normalized(); // returns ``` -#### factory( [options] ) +#### factory( \[options] ) Returns a xorshift128+ pseudorandom number generator ([PRNG][xorshift]). @@ -118,7 +118,9 @@ var bool = ( rng2() === rng1() ); The generator name. ```javascript -var str = factory.NAME; +var rng = factory(); + +var str = rng.NAME; // returns 'xorshift128+' ``` diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/package.json b/lib/node_modules/@stdlib/random/base/xorshift128/package.json index 192b5f9bd494..a163ae58b0cb 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/package.json +++ b/lib/node_modules/@stdlib/random/base/xorshift128/package.json @@ -23,13 +23,12 @@ "src": "./src", "test": "./test" }, - "types": "./docs/types/index.d.ts", + "types": "./docs/types", "scripts": {}, "homepage": "https://github.com/stdlib-js/stdlib", "repository": { "type": "git", - "url": "git://github.com/stdlib-js/stdlib.git", - "directory": "lib/node_modules/@stdlib/random/base/xorshift128plus" + "url": "git://github.com/stdlib-js/stdlib.git" }, "bugs": { "url": "https://github.com/stdlib-js/stdlib/issues" @@ -40,28 +39,6 @@ "node": ">=12.0.0", "npm": ">2.7.0" }, - "env": { - "node": true, - "es2020": true - }, - "parserOptions": { - "ecmaVersion": 2020, - "sourceType": "script" - }, - "rules": { - "no-magic-numbers": [ - "error", - { - "ignore": [ - -1, - 0, - 1, - 2 - ], - "ignoreArrayIndexes": true - } - ] - }, "os": [ "aix", "darwin", @@ -89,7 +66,7 @@ "uniform", "generator", "xorshift", - "xorshift128+", + "xorshift128", "xorshift128plus", "xor", "shift", From d933a60823b674ad935d580c0e151297eba76c82 Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Tue, 24 Mar 2026 14:00:04 +0000 Subject: [PATCH 4/7] fix : resolve lint and doctests issue for xorshift128 --- .../random/base/xorshift128/docs/repl.txt | 171 ++++++++++++++++++ .../base/xorshift128/docs/types/index.d.ts | 170 +++++++++++++++++ .../base/xorshift128/docs/types/test.ts | 141 +++++++++++++++ 3 files changed, 482 insertions(+) create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt b/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt new file mode 100644 index 000000000000..537960eebb78 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt @@ -0,0 +1,171 @@ + +{{alias}}() + Returns a xorshift128+ pseudorandom number generator. + + This pseudorandom number generator (PRNG) is a 128-bit xorshift PRNG + with a period of approximately 2^128. + + The generator produces 64-bit pseudorandom integers using BigInt + arithmetic. + + The generator is suitable for general-purpose use and Monte Carlo + simulations. For cryptographic applications, use a cryptographically + secure pseudorandom number generator (CSPRNG). + + Returns + ------- + rng: Function + Pseudorandom number generator (PRNG). + + Examples + -------- + > var rng = {{alias}}(); + > var v = rng(); + + +{{alias}}( options ) + Returns a xorshift128+ pseudorandom number generator with specified options. + + Parameters + ---------- + options: Object (optional) + Options. + + options.seed: integer|bigint (optional) + Pseudorandom number generator seed. The seed may be either a + non-negative integer or BigInt. + + options.state: Array (optional) + Pseudorandom number generator state. If provided, the `seed` option + is ignored. + + options.copy: boolean (optional) + Boolean indicating whether to copy a provided pseudorandom number + generator state. Setting this option to `false` allows sharing state + between two or more pseudorandom number generators. Setting this option + to `true` ensures that a returned generator has exclusive control over + its internal state. Default: true. + + Returns + ------- + rng: Function + Pseudorandom number generator (PRNG). + + Examples + -------- + // Basic usage: + > var rng = {{alias}}(); + > var v = rng(); + > v = rng(); + + // Provide a seed: + > var BigInt = require( '@stdlib/bigint/ctor' ); + > rng = {{alias}}( { 'seed': BigInt( 1234 ) } ); + > v = rng(); + + +rng() + Returns a pseudorandom 64-bit unsigned integer. + + Returns + ------- + r: bigint + Pseudorandom number. + + Examples + -------- + > var rng = {{alias}}(); + > var v = rng(); + + +rng.normalized() + Returns a pseudorandom number on the interval `[0,1)`. + + Returns + ------- + r: number + Pseudorandom number. + + Examples + -------- + > var rng = {{alias}}(); + > var v = rng.normalized(); + + +rng.copy() + Returns a copy of the pseudorandom number generator. + + Returns + ------- + copy: Function + Copy of the pseudorandom number generator. + + Examples + -------- + > var rng = {{alias}}(); + > var copy = rng.copy(); + > var v1 = rng(); + > var v2 = copy(); + + +rng.NAME + Generator name. + + Examples + -------- + > var rng = {{alias}}(); + > var str = rng.NAME + 'xorshift128+' + + +rng.seed + Pseudorandom number generator seed. + + Examples + -------- + > var rng = {{alias}}( { 'seed': BigInt( 1234 ) } ); + > var seed = rng.seed; + + +rng.state + Generator state. + + Examples + -------- + > var rng = {{alias}}(); + > var v = rng(); + > v = rng(); + > v = rng(); + + // Get the current state: + > var state = rng.state + > + + > v = rng(); + > v = rng(); + + // Set the state: + > rng.state = state; + + // Replay the last two pseudorandom numbers: + > v = rng(); + > v = rng(); + + +rng.toJSON() + Serializes the pseudorandom number generator as a JSON object. + + Returns + ------- + out: Object + JSON representation. + + Examples + -------- + > var rng = {{alias}}(); + > var o = rng.toJSON() + { 'type': 'PRNG', 'name': 'xorshift128+', 'state': [...], 'params': [] } + + See Also + -------- + \ No newline at end of file diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts new file mode 100644 index 000000000000..2163821d080f --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts @@ -0,0 +1,170 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +/** +* Interface defining `factory` options. +*/ +interface Options { + /** + * Pseudorandom number generator seed. + */ + seed?: number | bigint; + + /** + * Pseudorandom number generator state. + */ + state?: Array; + + /** + * Specifies whether to copy a provided pseudorandom number generator state. + */ + copy?: boolean; +} + +/** +* Interface for PRNG properties and methods. +*/ +interface PRNG { + /** + * Generator name. + */ + readonly NAME: string; + + /** + * PRNG seed. + */ + readonly seed: bigint; + + /** + * PRNG state. + */ + state: Array; + + /** + * Serializes the pseudorandom number generator as a JSON object. + * + * @returns JSON representation + */ + toJSON(): { + type: string; + name: string; + state: Array; + params: Array; + }; +} + +/** +* Interface for generating pseudorandom 64-bit unsigned integers. +*/ +interface NullaryFunction extends PRNG { + /** + * Returns a pseudorandom 64-bit unsigned integer. + * + * @returns pseudorandom number + */ + (): bigint; + + /** + * Returns a pseudorandom number on the interval `[0,1)`. + * + * @returns pseudorandom number + */ + normalized(): number; + + /** + * Returns a copy of the PRNG. + * + * @returns copy of the PRNG + */ + copy(): NullaryFunction; +} + +/** +* Interface for the xorshift128+ PRNG factory. +*/ +interface Factory { + /** + * Returns a xorshift128+ pseudorandom number generator. + * + * @param options - function options + * @param options.seed - pseudorandom number generator seed + * @param options.state - pseudorandom number generator state + * @param options.copy - boolean indicating whether to copy a provided pseudorandom number generator state (default: true) + * @throws must provide valid options + * @returns pseudorandom number generator + * + * @example + * var rng = factory(); + * var v = rng(); + * // returns + * + * @example + * var rng = factory({ + * 'seed': BigInt(12345) + * }); + * var v = rng(); + * // returns + */ + ( options?: Options ): NullaryFunction; +} + +/** +* Returns a xorshift128+ pseudorandom number generator. +* +* ## Notes +* +* - This pseudorandom number generator (PRNG) is a 128-bit xorshift PRNG with a period of approximately 2^128. +* - The generator produces 64-bit pseudorandom integers using BigInt arithmetic. +* - The generator is suitable for general-purpose use and Monte Carlo simulations. +* - For cryptographic applications, use a cryptographically secure pseudorandom number generator (CSPRNG). +* +* @param options - function options +* @param options.seed - pseudorandom number generator seed +* @param options.state - pseudorandom number generator state +* @param options.copy - boolean indicating whether to copy a provided pseudorandom number generator state (default: true) +* @throws must provide valid options +* @returns pseudorandom number generator +* +* @example +* var rng = factory(); +* var v = rng(); +* // returns +* +* @example +* var rng = factory(); +* var v = rng.normalized(); +* // returns +* +* @example +* var rng = factory({ +* 'seed': BigInt(12345) +* }); +* var v = rng(); +* // returns +*/ +declare var factory: Factory; + + +// EXPORTS // + +export = factory; + \ No newline at end of file diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts new file mode 100644 index 000000000000..071363df524a --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts @@ -0,0 +1,141 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import factory = require( './index' ); +import BigInt = require( '@stdlib/bigint/ctor' ); + +// TESTS // + +// The function returns a generator... +{ + factory(); // $ExpectType NullaryFunction +} + +// The compiler throws an error if the function is provided any arguments... +{ + factory( true ); // $ExpectError + factory( 2, 3 ); // $ExpectError +} + +// The returned generator returns a bigint... +{ + const rng = factory(); + rng(); // $ExpectType bigint +} + +// The compiler throws an error if the generator is provided any arguments... +{ + const rng = factory(); + rng( true ); // $ExpectError + rng( 123 ); // $ExpectError + rng( 'abc' ); // $ExpectError +} + +// Attached to returned generator is a `normalized` method which returns a number... +{ + const rng = factory(); + rng.normalized(); // $ExpectType number +} + +// The compiler throws an error if the `normalized` method is provided any arguments... +{ + const rng = factory(); + rng.normalized( true ); // $ExpectError + rng.normalized( 123 ); // $ExpectError + rng.normalized( 'abc' ); // $ExpectError +} + +// Attached to returned generator is a `copy` method which returns a generator... +{ + const rng = factory(); + rng.copy(); // $ExpectType NullaryFunction +} + +// The compiler throws an error if the `copy` method is provided any arguments... +{ + const rng = factory(); + rng.copy( true ); // $ExpectError + rng.copy( 123 ); // $ExpectError +} + +// Attached to returned generator is a `toJSON` method which returns a object... +{ + const rng = factory(); + rng.toJSON(); // $ExpectType object +} + +// The compiler throws an error if the `toJSON` method is provided any arguments... +{ + const rng = factory(); + rng.toJSON( true ); // $ExpectError + rng.toJSON( 123 ); // $ExpectError +} + +// The compiler throws an error if the `factory` function is provided an options argument which is not an object... +{ + factory( null ); // $ExpectError + factory( 'abc' ); // $ExpectError + factory( 123 ); // $ExpectError +} + +// The compiler throws an error if the `factory` function is provided a `seed` option which is not a valid seed... +{ + factory( { 'seed': true } ); // $ExpectError + factory( { 'seed': 'abc' } ); // $ExpectError + factory( { 'seed': null } ); // $ExpectError + factory( { 'seed': [] } ); // $ExpectError + factory( { 'seed': {} } ); // $ExpectError + factory( { 'seed': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` function is provided a `state` option which is not a valid state... +{ + factory( { 'state': 123 } ); // $ExpectError + factory( { 'state': 'abc' } ); // $ExpectError + factory( { 'state': null } ); // $ExpectError + factory( { 'state': {} } ); // $ExpectError + factory( { 'state': true } ); // $ExpectError + factory( { 'state': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` function is provided a `copy` option which is not a boolean... +{ + factory( { 'copy': 123 } ); // $ExpectError + factory( { 'copy': 'abc' } ); // $ExpectError + factory( { 'copy': null } ); // $ExpectError + factory( { 'copy': [] } ); // $ExpectError + factory( { 'copy': {} } ); // $ExpectError + factory( { 'copy': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` function is provided more than one argument... +{ + factory( {}, 2 ); // $ExpectError +} + +// Valid usage... +{ + const rng = factory( { 'seed': BigInt( 1234 ) } ); + const v1 = rng(); + const v2 = rng.normalized(); + const state = rng.state; + rng.state = state; + const copy = rng.copy(); + const json = rng.toJSON(); +} + \ No newline at end of file From bfaa1d8f56afb382be62234f22c6bb5fcc271e5c Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Tue, 24 Mar 2026 16:44:43 +0000 Subject: [PATCH 5/7] fix: lint error in ts file --- .../base/xorshift128/docs/types/index.d.ts | 52 +++++++++---------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts index 2163821d080f..c98ed35c88cc 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts @@ -15,11 +15,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + // TypeScript Version: 4.1 - + /// - + /** * Interface defining `factory` options. */ @@ -28,18 +28,18 @@ interface Options { * Pseudorandom number generator seed. */ seed?: number | bigint; - + /** * Pseudorandom number generator state. */ state?: Array; - + /** * Specifies whether to copy a provided pseudorandom number generator state. */ copy?: boolean; } - + /** * Interface for PRNG properties and methods. */ @@ -48,30 +48,30 @@ interface PRNG { * Generator name. */ readonly NAME: string; - + /** * PRNG seed. */ readonly seed: bigint; - + /** * PRNG state. */ state: Array; - + /** * Serializes the pseudorandom number generator as a JSON object. * * @returns JSON representation */ toJSON(): { - type: string; - name: string; - state: Array; - params: Array; - }; + type: string; + name: string; + state: Array; + params: Array; + }; } - + /** * Interface for generating pseudorandom 64-bit unsigned integers. */ @@ -82,14 +82,14 @@ interface NullaryFunction extends PRNG { * @returns pseudorandom number */ (): bigint; - + /** * Returns a pseudorandom number on the interval `[0,1)`. * * @returns pseudorandom number */ normalized(): number; - + /** * Returns a copy of the PRNG. * @@ -97,12 +97,11 @@ interface NullaryFunction extends PRNG { */ copy(): NullaryFunction; } - + /** * Interface for the xorshift128+ PRNG factory. */ -interface Factory { - /** +/** * Returns a xorshift128+ pseudorandom number generator. * * @param options - function options @@ -124,9 +123,8 @@ interface Factory { * var v = rng(); * // returns */ - ( options?: Options ): NullaryFunction; -} - +type Factory = ( options?: Options ) => NullaryFunction; + /** * Returns a xorshift128+ pseudorandom number generator. * @@ -162,9 +160,9 @@ interface Factory { * // returns */ declare var factory: Factory; - - + + // EXPORTS // - + export = factory; - \ No newline at end of file + From 6a561d94bbcccde0acf52f8b4078997de4270101 Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Wed, 22 Apr 2026 06:08:21 +0000 Subject: [PATCH 6/7] docs: improve xorshift128-prng --- .../@stdlib/random/base/xorshift128/README.md | 76 +-- .../base/xorshift128/benchmark/benchmark.js | 267 ++++---- .../random/base/xorshift128/docs/repl.txt | 41 +- .../base/xorshift128/docs/types/index.d.ts | 34 +- .../base/xorshift128/docs/types/test.ts | 274 +++++--- .../random/base/xorshift128/examples/basic.js | 140 ----- .../random/base/xorshift128/examples/index.js | 161 +---- .../random/base/xorshift128/lib/factory.js | 387 +++++++----- .../random/base/xorshift128/lib/index.js | 38 +- .../random/base/xorshift128/lib/main.js | 33 +- .../lib/{rand_int64.js => rand_int32.js} | 42 +- .../random/base/xorshift128/package.json | 3 +- .../base/xorshift128/test/test.factory.js | 423 +++++++++++++ .../random/base/xorshift128/test/test.js | 592 ++++++++---------- 14 files changed, 1377 insertions(+), 1134 deletions(-) delete mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js rename lib/node_modules/@stdlib/random/base/xorshift128/lib/{rand_int64.js => rand_int32.js} (56%) create mode 100644 lib/node_modules/@stdlib/random/base/xorshift128/test/test.factory.js diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/README.md b/lib/node_modules/@stdlib/random/base/xorshift128/README.md index d025d2ec2297..0f2475d609ac 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/README.md +++ b/lib/node_modules/@stdlib/random/base/xorshift128/README.md @@ -20,7 +20,7 @@ limitations under the License. # Xorshift128+ -> A 128-bit xorshift pseudorandom number generator ([PRNG][xorshift]). +> A 128-bit xorshift+ pseudorandom number generator ([PRNG][xorshift]).
@@ -38,7 +38,7 @@ Returns a xorshift128+ pseudorandom number generator. var rng = factory(); var r = rng(); -// returns +// returns ``` #### factory.normalized() @@ -62,34 +62,19 @@ var rng = factory(); The function accepts the following `options`: -- **seed**: pseudorandom number generator seed. Must be a non-negative integer or BigInt. Default: a random seed. -- **state**: a state array (Array) containing pseudorandom number generator state. If provided, the function ignores the `seed` option. +- **seed**: pseudorandom number generator seed. Must be a non-negative integer. Default: a random seed. +- **state**: a state array (Uint32Array) containing pseudorandom number generator state. If provided, the function ignores the `seed` option. - **copy**: `boolean` indicating whether to copy a provided pseudorandom number generator state. Setting this option to `false` allows sharing state between two or more pseudorandom number generators. Setting this option to `true` ensures that a returned generator has exclusive control over its internal state. Default: `true`. -By default, a random seed is used to seed the returned generator. To seed the generator, provide either a non-negative integer: - -```javascript -var BigInt = require( '@stdlib/bigint/ctor' ); - -var rng = factory({ - 'seed': BigInt( 1234 ) -}); - -var r = rng(); -// returns -``` - -or, for additional control, a BigInt value: +By default, a random seed is used to seed the returned generator. To seed the generator, provide a non-negative integer: ```javascript -var BigInt = require( '@stdlib/bigint/ctor' ); - var rng = factory({ - 'seed': BigInt( 1234 ) + 'seed': 1234 }); var r = rng(); -// returns +// returns ``` To return a generator having a specific initial state, set the generator `state` option: @@ -129,14 +114,12 @@ var str = rng.NAME; The value used to seed the generator. ```javascript -var BigInt = require( '@stdlib/bigint/ctor' ); - var rng = factory({ - 'seed': BigInt( 1234 ) + 'seed': 1234 }); var seed = rng.seed; -// returns +// returns ``` #### rng.state @@ -147,18 +130,39 @@ Writable property for getting and setting the generator state. var rng = factory(); var r = rng(); -// returns +// returns var state = rng.state; -// returns +// returns r = rng(); -// returns +// returns rng.state = state; r = rng(); -// returns +// returns +``` + +#### rng.copy() + +Returns a copy of the pseudorandom number generator. + +```javascript +var rng = factory({ + 'seed': 1234 +}); + +var rng2 = rng.copy(); + +var v1 = rng(); +// returns + +var v2 = rng2(); +// returns + +var bool = ( v1 === v2 ); +// returns true ``` #### rng.toJSON() @@ -182,8 +186,9 @@ var o = rng.toJSON(); - The generator has a period of approximately `2^128` (see [References](#references)). - Xorshift128+ is a fast, simple pseudorandom number generator with good statistical properties for most applications. -- The generator produces 64-bit pseudorandom integers using BigInt arithmetic. -- The "randomness quality" of the generator's output is suitable for general-purpose use, Monte Carlo simulations, and parallel computations (with different seeds). +- The generator produces 32-bit pseudorandom integers using bitwise operations on 32-bit pairs. +- Entropy mixing: the output is computed by XORing the upper and lower 32 bits of the 64-bit result to preserve entropy from the full state. +- The "randomness quality" of the generator's output is suitable for general-purpose use, Monte Carlo simulations, parallel computations (with different seeds), and statistical sampling. - For cryptographic applications, use a cryptographically secure pseudorandom number generator (CSPRNG). - If PRNG state is "shared" (meaning a state array was provided during PRNG creation and **not** copied) and one sets the generator state to a state array having a different length, the PRNG does **not** update the existing shared state and, instead, points to the newly provided state array. In order to synchronize PRNG output according to the new shared state array, the state array for **each** relevant PRNG must be **explicitly** set. - If PRNG state is "shared" and one sets the generator state to a state array of the same length, the PRNG state is updated (along with the state of all other PRNGs sharing the PRNG's state array). @@ -200,10 +205,9 @@ var o = rng.toJSON(); ```javascript var factory = require( '@stdlib/random/base/xorshift128' ); -var BigInt = require( '@stdlib/bigint/ctor' ); var rng = factory({ - 'seed': BigInt( 1234 ) + 'seed': 1234 }); var i; @@ -238,7 +242,7 @@ for ( i = 0; i < 10; i++ ) { ## See Also - [`@stdlib/random/base/mt19937`][@stdlib/random/base/mt19937]: A 32-bit Mersenne Twister pseudorandom number generator. -- [`@stdlib/random/base/randi`][@stdlib/random/base/randi]: pseudorandom numbers having integer values. +- [`@stdlib/random/base/minstd`][@stdlib/random/base/minstd]: A linear congruential pseudorandom number generator (MINSTD).
@@ -258,7 +262,7 @@ for ( i = 0; i < 10; i++ ) { [@stdlib/random/base/mt19937]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/random/base/mt19937 -[@stdlib/random/base/randi]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/random/base/randi +[@stdlib/random/base/minstd]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/random/base/minstd diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js b/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js index 7ec953220740..6b6bc27862b9 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/benchmark/benchmark.js @@ -18,203 +18,188 @@ 'use strict'; -/* eslint-disable node/no-unpublished-require */ - // MODULES // var bench = require( '@stdlib/bench' ); -var isBigInt = require( '@stdlib/assert/is-bigint' ); -var BigInt = require( '@stdlib/bigint/ctor' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var pkg = require( './../package.json' ).name; var xorshift128plus = require( './../lib' ); // MAIN // -bench( pkg, function benchmark( b ) { +bench( pkg+':factory', function benchmark( b ) { var rng; - var z; var i; - rng = xorshift128plus(); - b.tic(); for ( i = 0; i < b.iterations; i++ ) { - z = rng(); - if ( !isBigInt( z ) ) { - b.fail( 'should return a BigInt' ); + rng = xorshift128plus(); + if ( typeof rng !== 'function' ) { + b.fail( 'should return a function' ); } } b.toc(); - if ( !isBigInt( z ) ) { - b.fail( 'should return a BigInt' ); + if ( isnan( rng() ) ) { + b.fail( 'should not return NaN' ); } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':normalized', function benchmark( b ) { +bench( pkg+':factory:seed=', function benchmark( b ) { + var opts; var rng; - var z; var i; - rng = xorshift128plus(); + opts = { + 'seed': 1 + }; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - z = rng.normalized(); - if ( typeof z !== 'number' ) { - b.fail( 'should return a number' ); + opts.seed = i + 1; + rng = xorshift128plus( opts ); + if ( typeof rng !== 'function' ) { + b.fail( 'should return a function' ); } } b.toc(); - if ( typeof z !== 'number' ) { - b.fail( 'should return a number' ); + if ( isnan( rng() ) ) { + b.fail( 'should not return NaN' ); } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':factory', function benchmark( b ) { - var z; +bench( pkg+':factory:state=', function benchmark( b ) { + var state; + var opts; + var rng; var i; + opts = {}; + state = new Uint32Array( 4 ); + for ( i = 0; i < state.length; i++ ) { + state[ i ] = 123 + i; + } + opts.state = state; + b.tic(); for ( i = 0; i < b.iterations; i++ ) { - z = xorshift128plus({ - 'seed': BigInt(12345) - }); - if ( typeof z !== 'function' ) { + opts.state[ 0 ] = i + 1; + rng = xorshift128plus( opts ); + if ( typeof rng !== 'function' ) { b.fail( 'should return a function' ); } } b.toc(); - if ( typeof z !== 'function' ) { - b.fail( 'should return a function' ); + if ( isnan( rng() ) ) { + b.fail( 'should not return NaN' ); } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':factory:seed', function benchmark( b ) { - var z; +bench( pkg+':generation', function benchmark( b ) { + var rng; var i; + rng = xorshift128plus({ + 'seed': 12345 + }); + b.tic(); for ( i = 0; i < b.iterations; i++ ) { - z = xorshift128plus({ - 'seed': BigInt( i ) - }); - if ( typeof z !== 'function' ) { - b.fail( 'should return a function' ); - } + rng(); } b.toc(); - - if ( typeof z !== 'function' ) { - b.fail( 'should return a function' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':state', function benchmark( b ) { - var state; +bench( pkg+':generation:normalized', function benchmark( b ) { var rng; var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 54321 }); b.tic(); for ( i = 0; i < b.iterations; i++ ) { - state = rng.state; - if ( state.length !== 6 ) { - b.fail( 'invalid state length' ); - } + rng.normalized(); } b.toc(); - - if ( state.length !== 6 ) { - b.fail( 'invalid state length' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':state:set', function benchmark( b ) { +bench( pkg+':state:get', function benchmark( b ) { var state; var rng; var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 11111 }); - state = rng.state; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - rng.state = state; + state = rng.state; + if ( typeof state !== 'object' ) { + b.fail( 'should return object' ); + } } b.toc(); - - if ( state.length !== 6 ) { - b.fail( 'invalid state length' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':seed', function benchmark( b ) { - var seed; +bench( pkg+':state:set', function benchmark( b ) { + var state; var rng; var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 22222 }); + state = new Uint32Array( 4 ); + state[ 0 ] = 1000; + state[ 1 ] = 2000; + state[ 2 ] = 3000; + state[ 3 ] = 4000; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - seed = rng.seed; - if ( !isBigInt( seed ) ) { - b.fail( 'should return a BigInt' ); - } + rng.state = state; } b.toc(); - - if ( !isBigInt( seed ) ) { - b.fail( 'should return a BigInt' ); - } b.pass( 'benchmark finished' ); b.end(); }); bench( pkg+':copy', function benchmark( b ) { - var rng2; + var copy; var rng; var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 33333 }); b.tic(); for ( i = 0; i < b.iterations; i++ ) { - rng2 = rng.copy(); - if ( typeof rng2 !== 'function' ) { + copy = rng.copy(); + if ( typeof copy !== 'function' ) { b.fail( 'should return a function' ); } } b.toc(); - - if ( typeof rng2 !== 'function' ) { - b.fail( 'should return a function' ); - } b.pass( 'benchmark finished' ); b.end(); }); @@ -225,133 +210,135 @@ bench( pkg+':toJSON', function benchmark( b ) { var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 44444 }); b.tic(); for ( i = 0; i < b.iterations; i++ ) { json = rng.toJSON(); if ( typeof json !== 'object' ) { - b.fail( 'should return an object' ); + b.fail( 'should return object' ); } } b.toc(); - - if ( typeof json !== 'object' ) { - b.fail( 'should return an object' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':reproducible', function benchmark( b ) { - var rng1; - var rng2; - var v1; - var v2; +bench( pkg+':generation:sequential', function benchmark( b ) { + var rng; var i; + var j; - rng1 = xorshift128plus({ - 'seed': BigInt(54321) - }); - rng2 = xorshift128plus({ - 'seed': BigInt(54321) + rng = xorshift128plus({ + 'seed': 55555 }); b.tic(); for ( i = 0; i < b.iterations; i++ ) { - v1 = rng1(); - v2 = rng2(); - if ( v1 !== v2 ) { - b.fail( 'sequences should be identical' ); + for ( j = 0; j < 100; j++ ) { + rng(); } } b.toc(); - - if ( v1 !== v2 ) { - b.fail( 'sequences should be identical' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':batch:next', function benchmark( b ) { - var values; - var rng; +bench( pkg+':multiple:instances', function benchmark( b ) { + var rngs; var i; var j; - rng = xorshift128plus({ - 'seed': BigInt(12345) - }); - values = []; - values.length = 100; + rngs = []; + for ( i = 0; i < 100; i++ ) { + rngs.push( xorshift128plus({ + 'seed': i + 1 + }) ); + } b.tic(); for ( i = 0; i < b.iterations; i++ ) { - for ( j = 0; j < 100; j++ ) { - values[ j ] = rng(); + for ( j = 0; j < rngs.length; j++ ) { + rngs[ j ](); } } b.toc(); - - if ( values.length !== 100 ) { - b.fail( 'invalid values array length' ); - } b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':batch:normalized', function benchmark( b ) { - var values; +bench( pkg+':mixed:operations', function benchmark( b ) { + var state; var rng; var i; - var j; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 66666 }); - values = []; - values.length = 100; b.tic(); for ( i = 0; i < b.iterations; i++ ) { - for ( j = 0; j < 100; j++ ) { - values[ j ] = rng.normalized(); + // Generate regular value + rng(); + + // Generate normalized value + rng.normalized(); + + // Access state + state = rng.state; + if ( typeof state !== 'object') { + b.fail( 'should return object' ); } } b.toc(); + b.pass( 'benchmark finished' ); + b.end(); +}); - if ( values.length !== 100 ) { - b.fail( 'invalid values array length' ); +bench( pkg+':state:cycle', function benchmark( b ) { + var state; + var rng1; + var rng2; + var i; + + rng1 = xorshift128plus({ + 'seed': 77777 + }); + rng2 = xorshift128plus({ + 'seed': 88888 + }); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + // Save state from rng1 + state = rng1.state; + + // Restore state to rng2 + rng2.state = state; + + // Generate from restored PRNG + rng2(); } + b.toc(); b.pass( 'benchmark finished' ); b.end(); }); -bench( pkg+':mixed', function benchmark( b ) { +bench( pkg+':entropy:mixing', function benchmark( b ) { var rng; - var v1; - var v2; var i; rng = xorshift128plus({ - 'seed': BigInt(12345) + 'seed': 99999 }); b.tic(); for ( i = 0; i < b.iterations; i++ ) { - v1 = rng(); - v2 = rng.normalized(); + // Core generation with entropy mixing (XOR of upper/lower 32 bits) + rng(); } b.toc(); - - if ( !isBigInt( v1 ) ) { - b.fail( 'should return a BigInt' ); - } - if ( typeof v2 !== 'number' ) { - b.fail( 'should return a number' ); - } b.pass( 'benchmark finished' ); b.end(); }); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt b/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt index 537960eebb78..ef6cc19777c3 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/repl.txt @@ -5,12 +5,13 @@ This pseudorandom number generator (PRNG) is a 128-bit xorshift PRNG with a period of approximately 2^128. - The generator produces 64-bit pseudorandom integers using BigInt - arithmetic. + The generator produces 32-bit pseudorandom unsigned integers using + bitwise operations on 32-bit pairs. Entropy is preserved via XOR mixing + of the upper and lower 32 bits of the 64-bit internal result. - The generator is suitable for general-purpose use and Monte Carlo - simulations. For cryptographic applications, use a cryptographically - secure pseudorandom number generator (CSPRNG). + The generator is suitable for general-purpose use, Monte Carlo + simulations, and statistical sampling. For cryptographic applications, + use a cryptographically secure pseudorandom number generator (CSPRNG). Returns ------- @@ -31,13 +32,13 @@ options: Object (optional) Options. - options.seed: integer|bigint (optional) - Pseudorandom number generator seed. The seed may be either a - non-negative integer or BigInt. + options.seed: integer (optional) + Pseudorandom number generator seed. The seed must be a non-negative + integer. - options.state: Array (optional) + options.state: Uint32Array (optional) Pseudorandom number generator state. If provided, the `seed` option - is ignored. + is ignored. The state array must have length 4. options.copy: boolean (optional) Boolean indicating whether to copy a provided pseudorandom number @@ -59,18 +60,17 @@ > v = rng(); // Provide a seed: - > var BigInt = require( '@stdlib/bigint/ctor' ); - > rng = {{alias}}( { 'seed': BigInt( 1234 ) } ); + > rng = {{alias}}( { 'seed': 1234 } ); > v = rng(); rng() - Returns a pseudorandom 64-bit unsigned integer. + Returns a pseudorandom 32-bit unsigned integer. Returns ------- - r: bigint - Pseudorandom number. + r: number + Pseudorandom number (32-bit unsigned integer). Examples -------- @@ -84,7 +84,7 @@ rng.normalized() Returns ------- r: number - Pseudorandom number. + Pseudorandom number on [0,1). Examples -------- @@ -123,8 +123,9 @@ rng.seed Examples -------- - > var rng = {{alias}}( { 'seed': BigInt( 1234 ) } ); + > var rng = {{alias}}( { 'seed': 1234 } ); > var seed = rng.seed; + 1234 rng.state @@ -139,7 +140,7 @@ rng.state // Get the current state: > var state = rng.state - > + > v = rng(); > v = rng(); @@ -165,7 +166,3 @@ rng.toJSON() > var rng = {{alias}}(); > var o = rng.toJSON() { 'type': 'PRNG', 'name': 'xorshift128+', 'state': [...], 'params': [] } - - See Also - -------- - \ No newline at end of file diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts index c98ed35c88cc..63570a6b83fb 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/index.d.ts @@ -27,12 +27,12 @@ interface Options { /** * Pseudorandom number generator seed. */ - seed?: number | bigint; + seed?: number; /** * Pseudorandom number generator state. */ - state?: Array; + state?: Uint32Array; /** * Specifies whether to copy a provided pseudorandom number generator state. @@ -52,12 +52,12 @@ interface PRNG { /** * PRNG seed. */ - readonly seed: bigint; + readonly seed: number; /** * PRNG state. */ - state: Array; + state: Uint32Array; /** * Serializes the pseudorandom number generator as a JSON object. @@ -67,21 +67,21 @@ interface PRNG { toJSON(): { type: string; name: string; - state: Array; + state: Uint32Array; params: Array; }; } /** -* Interface for generating pseudorandom 64-bit unsigned integers. +* Interface for generating pseudorandom 32-bit unsigned integers. */ interface NullaryFunction extends PRNG { /** - * Returns a pseudorandom 64-bit unsigned integer. + * Returns a pseudorandom 32-bit unsigned integer. * * @returns pseudorandom number */ - (): bigint; + (): number; /** * Returns a pseudorandom number on the interval `[0,1)`. @@ -114,14 +114,14 @@ interface NullaryFunction extends PRNG { * @example * var rng = factory(); * var v = rng(); - * // returns + * // returns * * @example * var rng = factory({ - * 'seed': BigInt(12345) + * 'seed': 12345 * }); * var v = rng(); - * // returns + * // returns */ type Factory = ( options?: Options ) => NullaryFunction; @@ -131,8 +131,9 @@ type Factory = ( options?: Options ) => NullaryFunction; * ## Notes * * - This pseudorandom number generator (PRNG) is a 128-bit xorshift PRNG with a period of approximately 2^128. -* - The generator produces 64-bit pseudorandom integers using BigInt arithmetic. -* - The generator is suitable for general-purpose use and Monte Carlo simulations. +* - The generator produces 32-bit pseudorandom unsigned integers using bitwise operations on 32-bit pairs. +* - Entropy is preserved via XOR mixing of upper and lower 32 bits of the 64-bit internal result. +* - The generator is suitable for general-purpose use, Monte Carlo simulations, and statistical sampling. * - For cryptographic applications, use a cryptographically secure pseudorandom number generator (CSPRNG). * * @param options - function options @@ -145,7 +146,7 @@ type Factory = ( options?: Options ) => NullaryFunction; * @example * var rng = factory(); * var v = rng(); -* // returns +* // returns * * @example * var rng = factory(); @@ -154,10 +155,10 @@ type Factory = ( options?: Options ) => NullaryFunction; * * @example * var rng = factory({ -* 'seed': BigInt(12345) +* 'seed': 12345 * }); * var v = rng(); -* // returns +* // returns */ declare var factory: Factory; @@ -165,4 +166,3 @@ declare var factory: Factory; // EXPORTS // export = factory; - diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts index 071363df524a..4185acc26c08 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts +++ b/lib/node_modules/@stdlib/random/base/xorshift128/docs/types/test.ts @@ -15,127 +15,223 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - + import factory = require( './index' ); -import BigInt = require( '@stdlib/bigint/ctor' ); - -// TESTS // - -// The function returns a generator... + +/** +* TESTS +*/ + +// The factory function returns a function... { - factory(); // $ExpectType NullaryFunction + const rng = factory(); + rng(); // $ExpectType number + rng.normalized(); // $ExpectType number + rng.copy(); // $ExpectType () => number } - -// The compiler throws an error if the function is provided any arguments... + +// The factory function accepts a seed option... { - factory( true ); // $ExpectError - factory( 2, 3 ); // $ExpectError + const rng = factory( { + 'seed': 1234 + }); + rng(); // $ExpectType number } - -// The returned generator returns a bigint... + +// The factory function accepts a state option... { - const rng = factory(); - rng(); // $ExpectType bigint + const state = new Uint32Array( 4 ); + const rng = factory( { + 'state': state + }); + rng(); // $ExpectType number } - -// The compiler throws an error if the generator is provided any arguments... + +// The factory function accepts both seed and state options... { - const rng = factory(); - rng( true ); // $ExpectError - rng( 123 ); // $ExpectError - rng( 'abc' ); // $ExpectError + const state = new Uint32Array( 4 ); + const rng = factory( { + 'seed': 1234, + 'state': state + }); + rng(); // $ExpectType number } - -// Attached to returned generator is a `normalized` method which returns a number... + +// The factory function accepts a copy option... { - const rng = factory(); - rng.normalized(); // $ExpectType number + const rng = factory( { + 'copy': true + }); + rng(); // $ExpectType number } - -// The compiler throws an error if the `normalized` method is provided any arguments... + +// The factory function returns an object with NAME property... { const rng = factory(); - rng.normalized( true ); // $ExpectError - rng.normalized( 123 ); // $ExpectError - rng.normalized( 'abc' ); // $ExpectError + rng.NAME; // $ExpectType string } - -// Attached to returned generator is a `copy` method which returns a generator... + +// The factory function returns an object with seed property... { const rng = factory(); - rng.copy(); // $ExpectType NullaryFunction + rng.seed; // $ExpectType number } - -// The compiler throws an error if the `copy` method is provided any arguments... + +// The factory function returns an object with state property (getter)... { const rng = factory(); - rng.copy( true ); // $ExpectError - rng.copy( 123 ); // $ExpectError + rng.state; // $ExpectType Uint32Array } - -// Attached to returned generator is a `toJSON` method which returns a object... + +// The factory function returns an object with state property (setter)... { const rng = factory(); - rng.toJSON(); // $ExpectType object + const state = new Uint32Array( 4 ); + rng.state = state; } - -// The compiler throws an error if the `toJSON` method is provided any arguments... + +// The factory function returns an object with toJSON method... { const rng = factory(); - rng.toJSON( true ); // $ExpectError - rng.toJSON( 123 ); // $ExpectError -} - -// The compiler throws an error if the `factory` function is provided an options argument which is not an object... -{ - factory( null ); // $ExpectError - factory( 'abc' ); // $ExpectError - factory( 123 ); // $ExpectError + rng.toJSON(); // $ExpectType { type: string; name: string; state: Uint32Array; params: unknown[]; } } - -// The compiler throws an error if the `factory` function is provided a `seed` option which is not a valid seed... + +// The factory function returns an object with copy method... { - factory( { 'seed': true } ); // $ExpectError - factory( { 'seed': 'abc' } ); // $ExpectError - factory( { 'seed': null } ); // $ExpectError - factory( { 'seed': [] } ); // $ExpectError - factory( { 'seed': {} } ); // $ExpectError - factory( { 'seed': ( x: number ): number => x } ); // $ExpectError -} - -// The compiler throws an error if the `factory` function is provided a `state` option which is not a valid state... -{ - factory( { 'state': 123 } ); // $ExpectError - factory( { 'state': 'abc' } ); // $ExpectError - factory( { 'state': null } ); // $ExpectError - factory( { 'state': {} } ); // $ExpectError - factory( { 'state': true } ); // $ExpectError - factory( { 'state': ( x: number ): number => x } ); // $ExpectError + const rng = factory(); + rng.copy(); // $ExpectType () => number } - -// The compiler throws an error if the `factory` function is provided a `copy` option which is not a boolean... + +// The factory function returns an object with normalized method... { - factory( { 'copy': 123 } ); // $ExpectError - factory( { 'copy': 'abc' } ); // $ExpectError - factory( { 'copy': null } ); // $ExpectError - factory( { 'copy': [] } ); // $ExpectError - factory( { 'copy': {} } ); // $ExpectError - factory( { 'copy': ( x: number ): number => x } ); // $ExpectError + const rng = factory(); + rng.normalized(); // $ExpectType number } - -// The compiler throws an error if the `factory` function is provided more than one argument... + +// Test that factory can be called with options parameter... { - factory( {}, 2 ); // $ExpectError + const rng = factory( { + 'seed': 12345, + 'copy': false + }); + rng(); // $ExpectType number + rng.normalized(); // $ExpectType number + rng.copy(); // $ExpectType () => number +} + +// Test that state array must be Uint32Array... +{ + const rng1 = factory(); + const state = rng1.state; + const rng2 = factory( { + 'state': state + }); + rng2(); // $ExpectType number +} + +// Test that seed must be a number... +{ + const rng = factory( { + 'seed': 999 + }); + rng(); // $ExpectType number +} + +// Test getting and setting state... +{ + const rng1 = factory( { + 'seed': 42 + }); + + // Generate some values + rng1(); + rng1(); + + // Get state + const state = rng1.state; + state; // $ExpectType Uint32Array + + // Create new PRNG with saved state + const rng2 = factory( { + 'state': state + }); + + // Should continue from same state + rng2(); // $ExpectType number +} + +// Test copy functionality... +{ + const rng1 = factory( { + 'seed': 100 + }); + + const rng2 = rng1.copy(); + + const v1 = rng1(); + const v2 = rng2(); + + v1; // $ExpectType number + v2; // $ExpectType number +} + +// Test normalized output... +{ + const rng = factory( { + 'seed': 555 + }); + + const normalized = rng.normalized(); + normalized; // $ExpectType number + + // Should be in [0, 1) + if ( normalized >= 0 && normalized < 1 ) { + // valid + } +} + +// Test toJSON serialization... +{ + const rng = factory( { + 'seed': 777 + }); + + const json = rng.toJSON(); + json.type; // $ExpectType string + json.name; // $ExpectType string + json.state; // $ExpectType Uint32Array + json.params; // $ExpectType unknown[] } - -// Valid usage... + +// Test NAME constant... { - const rng = factory( { 'seed': BigInt( 1234 ) } ); + const rng = factory(); + if ( rng.NAME === 'xorshift128+' ) { + // Expected + } +} + +// Test seed property... +{ + const rng = factory( { + 'seed': 1234 + }); + + const seed = rng.seed; + seed; // $ExpectType number +} + +// Test consecutive generation... +{ + const rng = factory( { + 'seed': 2000 + }); + const v1 = rng(); - const v2 = rng.normalized(); - const state = rng.state; - rng.state = state; - const copy = rng.copy(); - const json = rng.toJSON(); + const v2 = rng(); + const v3 = rng(); + + v1; // $ExpectType number + v2; // $ExpectType number + v3; // $ExpectType number } - \ No newline at end of file diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js b/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js deleted file mode 100644 index fb360d6350d6..000000000000 --- a/lib/node_modules/@stdlib/random/base/xorshift128/examples/basic.js +++ /dev/null @@ -1,140 +0,0 @@ -/** -* @license Apache-2.0 -* -* Copyright (c) 2026 The Stdlib Authors. -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -'use strict'; - -var BigInt = require( '@stdlib/bigint/ctor' ); -var xorshift128plus = require( './../lib/' ); -var i; - -// EXAMPLE 1: Create a generator with a seed -console.log( '\n=== Example 1: Basic Generator ===' ); - -var rng = xorshift128plus({ - 'seed': BigInt(12345) -}); - -console.log( 'Generated 64-bit integers:' ); -console.log( ' %s', rng() ); -console.log( ' %s', rng() ); -console.log( ' %s', rng() ); - -// EXAMPLE 2: Generate normalized values -console.log( '\n=== Example 2: Normalized Values ===' ); - -var normalizedRng = xorshift128plus({ - 'seed': BigInt(54321) -}); - -console.log( 'Normalized values in [0, 1):' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %d', normalizedRng.normalized() ); -} - -// EXAMPLE 3: Reproducibility with same seed -console.log( '\n=== Example 3: Reproducibility ===' ); - -var rng1 = xorshift128plus({ - 'seed': BigInt(99999) -}); -var rng2 = xorshift128plus({ - 'seed': BigInt(99999) -}); - -console.log( 'Both generators with same seed (99999n):' ); -for ( i = 0; i < 3; i++ ) { - console.log( ' rng1: %s, rng2: %s', rng1().toString(), rng2().toString() ); -} - -// EXAMPLE 4: Seeding with different values -console.log( '\n=== Example 4: Different Seeds ===' ); - -var rngA = xorshift128plus({ - 'seed': BigInt(111) -}); -var rngB = xorshift128plus({ - 'seed': BigInt(222) -}); - -console.log( 'Different seeds produce different sequences:' ); -console.log( ' seed 111n: %s', rngA().toString() ); -console.log( ' seed 222n: %s', rngB().toString() ); - -// EXAMPLE 5: Using without explicit seed (random) -console.log( '\n=== Example 5: Random Seed ===' ); - -var randomRng = xorshift128plus(); - -console.log( 'Generator with random seed:' ); -for ( i = 0; i < 3; i++ ) { - console.log( ' %s', randomRng().toString() ); -} - -// EXAMPLE 6: Accessing generator properties -console.log( '\n=== Example 6: Generator Properties ===' ); - -var propRng = xorshift128plus({ - 'seed': BigInt(777) -}); - -console.log( 'Generator properties:' ); -console.log( ' NAME: %s', propRng.NAME ); -console.log( ' seed (BigInt): %s', propRng.seed ); -console.log( ' state (array length): %d', propRng.state.length ); - -// EXAMPLE 7: State management -console.log( '\n=== Example 7: State Management ===' ); - -var stateRng = xorshift128plus({ - 'seed': BigInt(555) -}); - -console.log( 'Initial values:' ); -console.log( ' %s', stateRng() ); -console.log( ' %s', stateRng() ); - -var savedState = stateRng.state; -console.log( 'State saved' ); - -console.log( 'Continue generating:' ); -console.log( ' %s', stateRng() ); -console.log( ' %s', stateRng() ); - -stateRng.state = savedState; -console.log( 'State restored, same values:' ); -console.log( ' %s (should be same as value 3)', stateRng() ); -console.log( ' %s (should be same as value 4)', stateRng() ); - -// EXAMPLE 8: Copying a generator -console.log( '\n=== Example 8: Generator Copy ===' ); - -var original = xorshift128plus({ - 'seed': BigInt(333) -}); -var duplicate = original.copy(); - -console.log( 'Original: %s', original() ); -console.log( 'Copy: %s', duplicate() ); - -console.log( 'Both continue with same sequence (initially):' ); -console.log( 'Original: %s', original() ); -console.log( 'Copy: %s', duplicate() ); - -console.log( 'But now they are independent:' ); -console.log( 'Original: %s', original() ); -console.log( 'Copy: %s', duplicate() ); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js index d79af0a718b5..e379d3ff7250 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2026 The Stdlib Authors. +* Copyright (c) 2018 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,160 +18,35 @@ 'use strict'; -var BigInt = require( '@stdlib/bigint/ctor' ); var xorshift128plus = require( './../lib' ); -var match; -var valA; -var valB; - -// Generate pseudorandom 64-bit integers... -console.log( '\n=== Pseudorandom 64-bit Integers ===' ); -console.log( 'seed: %s', BigInt(12345) ); - -var rng = xorshift128plus({ - 'seed': BigInt(12345) -}); +var rng = xorshift128plus(); +console.log( '\nDefault Generator:' ); var i; for ( i = 0; i < 10; i++ ) { - console.log( rng().toString() ); -} - -// Generate normalized random numbers in [0, 1)... -console.log( '\n=== Normalized Random Numbers [0, 1) ===' ); - -rng = xorshift128plus({ - 'seed': BigInt(12345) -}); - -for ( i = 0; i < 10; i++ ) { - console.log( rng.normalized() ); + console.log( rng() ); } -// Create a new pseudorandom number generator with a custom seed... -console.log( '\n=== Custom Seed ===' ); - -var seed = BigInt(54321); -var rand = xorshift128plus({ - 'seed': seed +// Create a new pseudorandom number generator... +var rand1 = xorshift128plus({ + 'seed': 1234 }); - -console.log( 'seed: %s', seed ); -for ( i = 0; i < 10; i++ ) { - console.log( rand().toString() ); -} - -// Create another pseudorandom number generator using a previous seed... -console.log( '\n=== Using Previous Seed ===' ); - -rand = xorshift128plus({ - 'seed': BigInt(99999) +var rand2 = xorshift128plus({ + 'seed': 1234 }); -var previousSeed = rand.seed; - -// Generate some values +console.log( '\nSame seed (reproducible):' ); for ( i = 0; i < 5; i++ ) { - rand(); -} - -// Create a new generator with the previous seed -rand = xorshift128plus({ - 'seed': previousSeed -}); - -console.log( 'seed: %s', previousSeed ); -for ( i = 0; i < 10; i++ ) { - console.log( rand().toString() ); + console.log( rand1(), rand2() ); } -// Demonstrate state management... -console.log( '\n=== State Management ===' ); - -var rng1 = xorshift128plus({ - 'seed': BigInt(777) +// Create another pseudorandom number generator using a previous seed... +var rand3 = xorshift128plus({ + 'seed': 111 }); -console.log( 'Generated values: ' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', rng1().toString() ); -} - -// Save state -var state = rng1.state; -console.log( 'State saved' ); - -// Generate more values -console.log( 'Generated more values:' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', rng1().toString() ); -} - -// Restore state -rng1.state = state; -console.log( 'State restored' ); - -// Generate the same values as before -console.log( 'Same values regenerated:' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', rng1().toString() ); -} - -// Demonstrate generator copying... -console.log( '\n=== Generator Copying ===' ); - -var original = xorshift128plus({ - 'seed': BigInt(555) +var rand4 = xorshift128plus({ + 'seed': 999 }); -console.log( 'Original generator:' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', original().toString() ); -} - -var copy = original.copy(); -console.log( 'Copied generator (should produce same sequence):' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', copy().toString() ); -} - -// Now they diverge -console.log( 'Original continues:' ); +console.log( '\nDifferent seeds (independent);' ); for ( i = 0; i < 5; i++ ) { - console.log( ' %s', original().toString() ); + console.log( rand3(), rand4() ); } - -console.log( 'Copy continues (different):' ); -for ( i = 0; i < 5; i++ ) { - console.log( ' %s', copy().toString() ); -} - -// Demonstrate reproducibility... -console.log( '\n=== Reproducibility ===' ); - -var rngA = xorshift128plus({ - 'seed': BigInt(888) -}); -var rngB = xorshift128plus({ - 'seed': BigInt(888) -}); - -console.log( 'Both generators with same seed produce identical sequences:' ); -for ( i = 0; i < 10; i++ ) { - valA = rngA(); - valB = rngB(); - match = ( valA === valB ) ? '✓' : '✗'; - console.log( ' %s %s === %s', match, valA.toString(), valB.toString() ); -} - -// Demonstrate JSON serialization... -console.log( '\n=== JSON Serialization ===' ); - -var jsonRng = xorshift128plus({ - 'seed': BigInt(333) -}); -var json = jsonRng.toJSON(); - -console.log( 'Serialized state:' ); -console.log( ' type: %s', json.type ); -console.log( ' name: %s', json.name ); -console.log( ' state length: %d', json.state.length ); -console.log( 'Full JSON object:' ); -console.log( json ); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js index 32f4152a5ced..80ccbf9a340e 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/factory.js @@ -21,24 +21,26 @@ * * ## Algorithm * -* The Xorshift128+ algorithm generates 64-bit pseudorandom numbers by -* maintaining two 64-bit state values and performing XOR and shift operations. +* The Xorshift128+ algorithm generates 32-bit pseudorandom numbers using +* 64-bit state values (stored as 32-bit pairs). Entropy from both halves +* of the 64-bit output is mixed via XOR to preserve quality. * * ## Notes * -* - Uses JavaScript BigInt for 64-bit arithmetic. -* - State consists of two 64-bit values: s0 and s1. +* - Uses Uint32Array for state storage (@stdlib compatible). +* - Returns 32-bit unsigned integers via entropy mixing. +* - Entropy mixing: XOR(upper_32bits, lower_32bits). * - Period: approximately 2^128. * * @example -* var xorshift128plus = require( '@stdlib/random/base/xorshift128plus' ); +* var factory = require( '@stdlib/random/base/xorshift128plus' ); * -* var rng = xorshift128plus({ -* 'seed': BigInt(12345) +* var rng = factory({ +* 'seed': 12345 * }); * * var v = rng(); -* // returns +* // returns */ 'use strict'; @@ -52,12 +54,10 @@ var hasOwnProp = require( '@stdlib/assert/has-own-property' ); var isObject = require( '@stdlib/assert/is-plain-object' ); var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isNonNegativeInteger = require( '@stdlib/assert/is-nonnegative-integer' ); -var isBigInt = require( '@stdlib/assert/is-bigint' ); -var BigInt = require( '@stdlib/bigint/ctor' ); -var Number = require( '@stdlib/number/ctor' ); -var randu = require( '@stdlib/random/base/randu' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var floor = require( '@stdlib/math/base/special/floor' ); var format = require( '@stdlib/string/format' ); +var randu = require( '@stdlib/random/base/randu' ); // VARIABLES // @@ -65,126 +65,153 @@ var format = require( '@stdlib/string/format' ); /* eslint-disable no-magic-numbers */ /** -* State array schema version. +* State array length (4 × 32-bit values = 2 × 64-bit values). * * @private -* @type {bigint} +* @type {number} */ -var STATE_ARRAY_VERSION = BigInt( 1 ); +var STATE_ARRAY_SIZE = 4; /** -* Number of state elements (2 × 64-bit values). +* State array indices for first 64-bit value (s0). * * @private -* @type {bigint} +* @type {number} */ -var NUM_STATE_ELEMENTS = BigInt( 2 ); +var S0_HI_INDEX = 0; +var S0_LO_INDEX = 1; /** -* Total state array length:. -* [version | state_length | state[0] | state[1] | seed_length | seed] +* State array indices for second 64-bit value (s1). * * @private * @type {number} */ -var STATE_ARRAY_SIZE = 6; +var S1_HI_INDEX = 2; +var S1_LO_INDEX = 3; /** -* State array indices. +* Normalization constant for converting to [0,1). * * @private * @type {number} */ -var VERSION_INDEX = 0; -var STATE_LENGTH_INDEX = 1; -var STATE_OFFSET = 2; -var SEED_LENGTH_INDEX = 4; -var SEED_OFFSET = 5; +var NORMALIZATION_CONSTANT = 1.0 / 0x100000000; -/** -* Maximum value for a 64-bit unsigned integer. -* -* @private -* @type {bigint} -*/ -var UINT64_MAX_BIGINT = BigInt( '0xffffffffffffffff' ); +/* eslint-enable no-magic-numbers */ + + +// FUNCTIONS // /** -* 2^64 as BigInt for normalization. +* Performs left shift on 64-bit value stored as two 32-bit parts. * * @private -* @type {bigint} +* @param {number} hi - high 32 bits +* @param {number} lo - low 32 bits +* @param {number} shift - shift amount (0-63) +* @returns {Array} [hi_shifted, lo_shifted] */ -var TWO_64 = BigInt( '0x10000000000000000' ); +function shift64Left( hi, lo, shift ) { + var newHi; + var newLo; + + if ( shift === 0 ) { + return [ hi, lo ]; + } + if ( shift >= 64 ) { + return [ 0, 0 ]; + } + if ( shift >= 32 ) { + return [ (lo << (shift - 32)) >>> 0, 0 ]; + } + /* eslint-disable no-bitwise */ + newHi = ((hi << shift) | (lo >>> (32 - shift))) >>> 0; + newLo = (lo << shift) >>> 0; + + /* eslint-enable no-bitwise */ + return [ newHi, newLo ]; +} /** -* Normalization constant for converting uint64 to [0,1). +* Performs right shift on 64-bit value stored as two 32-bit parts. * * @private -* @type {number} +* @param {number} hi - high 32 bits +* @param {number} lo - low 32 bits +* @param {number} shift - shift amount (0-63) +* @returns {Array} [hi_shifted, lo_shifted] */ -var NORMALIZATION_CONSTANT = 1.0 / Number( TWO_64 ); - -/* eslint-enable no-magic-numbers */ +function shift64Right( hi, lo, shift ) { + var newHi; + var newLo; + if ( shift === 0 ) { + return [ hi, lo ]; + } + if ( shift >= 64 ) { + return [ 0, 0 ]; + } + if ( shift >= 32 ) { + return [ 0, (hi >>> (shift - 32)) >>> 0 ]; + } + /* eslint-disable no-bitwise */ + newHi = (hi >>> shift) >>> 0; + newLo = (((lo >>> shift) | (hi << (32 - shift))) >>> 0); -// FUNCTIONS // + /* eslint-enable no-bitwise */ + return [ newHi, newLo ]; +} /** -* Initializes the internal PRNG state from a seed. +* Adds two 64-bit values with carry handling. * * @private -* @param {bigint} seed - seed value -* @returns {Array} state array with two 64-bit values +* @param {number} hi1 - first value high 32 bits +* @param {number} lo1 - first value low 32 bits +* @param {number} hi2 - second value high 32 bits +* @param {number} lo2 - second value low 32 bits +* @returns {Array} [hi_result, lo_result] */ -function initializeState( seed ) { - var MULTIPLIER_1 = BigInt( '0x9e3779b97f4a7c15' ); - var MULTIPLIER_2 = BigInt( '0xbf58476d1ce4e5b9' ); - var state = [ BigInt( 0 ), BigInt( 0 ) ]; - - state[ 0 ] = (seed ^ MULTIPLIER_1) & UINT64_MAX_BIGINT; - state[ 1 ] = (seed ^ MULTIPLIER_2) & UINT64_MAX_BIGINT; - - if ( state[ 0 ] === BigInt( 0 ) && state[ 1 ] === BigInt( 0 ) ) { - state[ 0 ] = BigInt( 1 ); - } - - return state; +function add64( hi1, lo1, hi2, lo2 ) { + var carry; + var lo; + var hi; + lo = (lo1 + lo2) >>> 0; + carry = (lo < lo1) ? 1 : 0; + hi = (hi1 + hi2 + carry) >>> 0; + return [ hi, lo ]; } /** -* Verifies state array integrity. +* Initializes state from seed. * * @private -* @param {Array} stateArray - state array -* @returns {(Error|null)} error or null +* @param {Uint32Array} state - state array to initialize +* @param {number} seed - seed value +* @returns {Uint32Array} initialized state */ -function verifyState( stateArray ) { - if ( !Array.isArray( stateArray ) ) { - return new TypeError( 'invalid state array. State must be an Array.' ); - } +function initState( state, seed ) { + /* eslint-disable no-magic-numbers */ - if ( stateArray.length !== STATE_ARRAY_SIZE ) { - return new RangeError(format('invalid state array. Expected length %u. Got %u.', STATE_ARRAY_SIZE, stateArray.length)); - } + // Use seed to initialize s0 and s1 + // Based on SplitMix64 constants for good distribution + var s0 = seed >>> 0; + var s1 = ((seed + 0x9e3779b97f4a7c15) >>> 0) ^ s0; - if ( stateArray[ VERSION_INDEX ] !== STATE_ARRAY_VERSION ) { - return new RangeError(format('invalid state array. Unsupported version %u.', stateArray[ VERSION_INDEX ])); - } + // Create initial 64-bit values - if ( stateArray[ STATE_LENGTH_INDEX ] !== NUM_STATE_ELEMENTS ) { - return new RangeError(format('invalid state array. Expected state length %u. Got %u.', NUM_STATE_ELEMENTS, stateArray[ STATE_LENGTH_INDEX ])); - } + // s0_initial = seed * 2^32 + s0 - if ( typeof stateArray[ STATE_OFFSET ] !== 'bigint' ) { - return new TypeError( 'invalid state array. State[0] must be a BigInt.' ); - } + // s1_initial = seed * 2^32 + s1 + state[ S0_HI_INDEX ] = (s0 * 1103515245) >>> 0; + state[ S0_LO_INDEX ] = (s1 * 1103515245) >>> 0; + state[ S1_HI_INDEX ] = (s0 + 12345) >>> 0; + state[ S1_LO_INDEX ] = (s1 + 12345) >>> 0; - if ( typeof stateArray[ STATE_OFFSET + 1 ] !== 'bigint' ) { - return new TypeError( 'invalid state array. State[1] must be a BigInt.' ); - } + /* eslint-enable no-magic-numbers */ - return null; + return state; } @@ -194,20 +221,26 @@ function verifyState( stateArray ) { * Returns an Xorshift128+ pseudorandom number generator. * * @param {Object} [options] - configuration object -* @param {(number|bigint)} [options.seed] - seed value -* @param {Array} [options.state] - generator state +* @param {number} [options.seed] - seed value +* @param {Uint32Array} [options.state] - generator state * @param {boolean} [options.copy=true] - copy state * @throws {TypeError} options must be an object * @throws {TypeError} invalid option value * @throws {RangeError} invalid state array * @returns {Function} PRNG function +* +* @example +* var rng = factory({ +* 'seed': 1234 +* }); +* +* var v = rng(); +* // throws 96092074 */ function factory( options ) { var STATE; - var state; - var seed; var opts; - var err; + var seed; var tmp; var i; @@ -228,18 +261,16 @@ function factory( options ) { STATE = options.state; opts.state = true; - if ( !Array.isArray( STATE ) ) { - throw new TypeError('invalid option. `state` must be an Array.'); + if ( !(STATE instanceof Uint32Array) ) { + throw new TypeError('invalid option. `state` must be a Uint32Array.'); } - err = verifyState( STATE ); - if ( err ) { - throw err; + if ( STATE.length !== STATE_ARRAY_SIZE ) { + throw new RangeError(format('invalid option. `state` must have length %u. Received: %u.', STATE_ARRAY_SIZE, STATE.length)); } if ( opts.copy !== false ) { - tmp = []; - tmp.length = STATE_ARRAY_SIZE; + tmp = new Uint32Array( STATE_ARRAY_SIZE ); for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { tmp[ i ] = STATE[ i ]; } @@ -252,92 +283,107 @@ function factory( options ) { seed = options.seed; opts.seed = true; - if ( typeof seed === 'number' ) { - if ( !isNonNegativeInteger( seed ) ) { - throw new TypeError('invalid option. `seed` must be a non-negative integer or BigInt.'); - } - seed = BigInt( seed ); - } else if ( isBigInt( seed ) ) { - if ( seed < BigInt( 0 ) ) { - throw new RangeError('invalid option. `seed` must be a non-negative BigInt.'); - } - } else { - throw new TypeError('invalid option. `seed` must be a non-negative integer or BigInt.'); - } - - if ( seed === BigInt( 0 ) ) { - seed = BigInt( 1 ); + if ( !isNonNegativeInteger( seed ) ) { + throw new TypeError('invalid option. `seed` must be a non-negative integer.'); } } else { - seed = BigInt( floor( randu() * 0x100000000 ) ) * BigInt( '0x100000000' ); - seed |= BigInt( floor( randu() * 0x100000000 ) ); - if ( seed === BigInt( 0 ) ) { - seed = BigInt( 1 ); - } + /* eslint-disable no-magic-numbers */ + seed = floor( randu() * 0x100000000 ); + + /* eslint-enable no-magic-numbers */ } } } else { - seed = BigInt( floor( randu() * 0x100000000 ) ) * BigInt( '0x100000000' ); - seed |= BigInt( floor( randu() * 0x100000000 ) ); - if ( seed === BigInt( 0 ) ) { - seed = BigInt( 1 ); - } + /* eslint-disable no-magic-numbers */ + seed = floor( randu() * 0x100000000 ); + + /* eslint-enable no-magic-numbers */ } if ( STATE === void 0 ) { - state = initializeState( seed ); - STATE = []; - STATE.length = STATE_ARRAY_SIZE; - STATE[ VERSION_INDEX ] = STATE_ARRAY_VERSION; - STATE[ STATE_LENGTH_INDEX ] = NUM_STATE_ELEMENTS; - STATE[ STATE_OFFSET ] = state[ 0 ]; - STATE[ STATE_OFFSET + 1 ] = state[ 1 ]; - STATE[ SEED_LENGTH_INDEX ] = BigInt( 1 ); - STATE[ SEED_OFFSET ] = seed; + STATE = new Uint32Array( STATE_ARRAY_SIZE ); + STATE = initState( STATE, seed ); } /** - * Generates a pseudorandom 64-bit unsigned integer. + * Generates next pseudorandom 32-bit unsigned integer. + * + * Entropy mixing approach: + * 1. Compute 64-bit output using 32-bit state pairs + * 2. Mix upper and lower 32 bits via XOR + * 3. Return 32-bit mixed result * * @private - * @returns {bigint} pseudorandom 64-bit integer + * @returns {number} pseudorandom 32-bit unsigned integer */ function next() { - var s1 = STATE[ STATE_OFFSET ]; - var s0 = STATE[ STATE_OFFSET + 1 ]; - - STATE[ STATE_OFFSET ] = s0; - - s1 ^= (s1 << BigInt( 23 )); - s1 ^= (s1 >> BigInt( 18 )); - s1 ^= s0; - s0 ^= (s0 >> BigInt( 5 )); - - STATE[ STATE_OFFSET + 1 ] = (s1 ^ s0) & UINT64_MAX_BIGINT; - - return ((s1 ^ s0) + s0) & UINT64_MAX_BIGINT; + var result; + var sumHi; + var sumLo; + var s0Hi; + var s0Lo; + var s1Hi; + var s1Lo; + var t; + + // Load state + s0Hi = STATE[ S0_HI_INDEX ]; + s0Lo = STATE[ S0_LO_INDEX ]; + s1Hi = STATE[ S1_HI_INDEX ]; + s1Lo = STATE[ S1_LO_INDEX ]; + + // s1 ^= s1 << 23 + t = shift64Left( s1Hi, s1Lo, 23 ); + s1Hi ^= t[ 0 ]; + s1Lo ^= t[ 1 ]; + + // s1 ^= s1 >> 17 + t = shift64Right( s1Hi, s1Lo, 17 ); + s1Hi ^= t[ 0 ]; + s1Lo ^= t[ 1 ]; + + // s1 ^= s0 + s1Hi ^= s0Hi; + s1Lo ^= s0Lo; + + // s1 ^= s0 >> 26 + t = shift64Right( s0Hi, s0Lo, 26 ); + s1Hi ^= t[ 0 ]; + s1Lo ^= t[ 1 ]; + + // Update state + STATE[ S0_HI_INDEX ] = s1Hi; + STATE[ S0_LO_INDEX ] = s1Lo; + STATE[ S1_HI_INDEX ] = s0Hi; + STATE[ S1_LO_INDEX ] = s0Lo; + + // Result = s1 + s0 + result = add64( s1Hi, s1Lo, s0Hi, s0Lo ); + sumHi = result[ 0 ]; + sumLo = result[ 1 ]; + + // Entropy mixing + return (sumHi ^ sumLo) >>> 0; } - /** - * Generates a pseudorandom number on [0, 1). + * Generates pseudorandom number on [0, 1). * * @private - * @returns {number} pseudorandom number in [0, 1) + * @returns {number} pseudorandom number */ function norm() { - return Number( next() ) * NORMALIZATION_CONSTANT; + return next() * NORMALIZATION_CONSTANT; } /** - * Returns the current state. + * Returns current state. * * @private - * @returns {Array} state array + * @returns {Uint32Array} state */ function getState() { - var out = []; + var out = new Uint32Array( STATE_ARRAY_SIZE ); var i; - out.length = STATE_ARRAY_SIZE; for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { out[ i ] = STATE[ i ]; } @@ -345,27 +391,26 @@ function factory( options ) { } /** - * Sets the state. + * Sets state. * * @private - * @param {Array} s - new state - * @throws {TypeError} invalid state type - * @throws {RangeError} invalid state + * @param {Uint32Array} s - new state + * @throws {TypeError} state must be Uint32Array + * @throws {RangeError} state must have correct length */ function setState( s ) { - var e; var i; - if ( !Array.isArray( s ) ) { - throw new TypeError('invalid argument. `state` must be an Array.'); + + if ( !(s instanceof Uint32Array) ) { + throw new TypeError('invalid argument. `state` must be a Uint32Array.'); } - e = verifyState( s ); - if ( e ) { - throw e; + if ( s.length !== STATE_ARRAY_SIZE ) { + throw new RangeError(format('invalid argument. `state` must have length %u. Received: %u.', STATE_ARRAY_SIZE, s.length)); } if ( opts.copy === false ) { - if ( opts.state && s.length === STATE.length ) { + if ( opts.state ) { for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { STATE[ i ] = s[ i ]; } @@ -374,10 +419,6 @@ function factory( options ) { opts.state = true; } } else { - if ( s.length !== STATE.length ) { - STATE = []; - STATE.length = STATE_ARRAY_SIZE; - } for ( i = 0; i < STATE_ARRAY_SIZE; i++ ) { STATE[ i ] = s[ i ]; } @@ -385,7 +426,7 @@ function factory( options ) { } /** - * Returns a copy of the PRNG. + * Returns copy of PRNG. * * @private * @returns {Function} copy @@ -398,28 +439,28 @@ function factory( options ) { } /** - * Serializes the state. + * Serializes state as JSON. * * @private - * @returns {Object} JSON object + * @returns {Object} JSON representation */ function toJSON() { return { 'type': 'PRNG', 'name': 'xorshift128+', - 'state': Array.from( STATE ), + 'state': getState(), 'params': [] }; } /** - * Returns the seed. + * Returns seed. * * @private - * @returns {bigint} seed + * @returns {number} seed */ function getSeed() { - return STATE[ SEED_OFFSET ]; + return STATE[ S0_HI_INDEX ]; } setReadOnly( next, 'NAME', 'xorshift128+' ); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js index c86ce9dd3ebd..ca61fbd7e40d 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/index.js @@ -19,29 +19,43 @@ 'use strict'; /** -* Xorshift128+ pseudorandom number generator. +* Xorshift128+ pseudorandom number generator (PRNG). * -* @module @stdlib/random/base/xorshift128 +* ## Algorithm +* +* The Xorshift128+ algorithm generates 32-bit pseudorandom numbers using +* 64-bit state values (stored as 32-bit pairs). Entropy from both halves +* of the 64-bit output is mixed via XOR to preserve quality. +* +* ## Notes +* +* - Uses Uint32Array for state storage (@stdlib compatible). +* - Returns 32-bit unsigned integers via entropy mixing. +* - Entropy mixing: XOR(upper_32bits, lower_32bits). +* - Period: approximately 2^128. * * @example -* var xorshift128 = require( '@stdlib/random/base/xorshift128' ); +* var xorshift128plus = require( '@stdlib/random/base/xorshift128' ); * -* // Create a PRNG with a seed -* var rng = xorshift128( { seed: 12345n } ); -* // returns +* // Create PRNG with fixed seed for reproducibility +* var rng = xorshift128plus({ +* 'seed': 1234 +* }); * * var v = rng(); -* // returns +* // returns * * @example -* var xorshift128 = require( '@stdlib/random/base/xorshift128' ); +* var xorshift128plus = require( '@stdlib/random/base/xorshift128' ); * -* // Without arguments, creates with random seed -* var rng = xorshift128(); -* // returns +* // Create PRNG with random seed +* var rng = xorshift128plus(); * * var v = rng(); -* // returns +* // returns +* +* var n = rng.normalized(); +* // returns */ // MODULES // diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js index 49ca6703919e..1aea8abfa640 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/main.js @@ -19,16 +19,26 @@ 'use strict'; /** -* Default Xorshift128+ PRNG instance. +* Xorshift128+ pseudorandom number generator (default instance). +* +* @module @stdlib/random/base/xorshift128 +* @type {Function} +* @returns {number} pseudorandom 32-bit unsigned integer +* +* @example +* var rng = require( '@stdlib/random/base/xorshift128' ); +* +* var v = rng(); +* // returns * -* Note: This file is provided for backward compatibility with stdlib patterns. -* Most users should use the factory directly via index.js. +* var n = rng.normalized(); +* // throws */ // MODULES // var factory = require( './factory.js' ); -var randi32 = require( './rand_int64.js' ); +var randi32 = require( './rand_int32.js' ); // MAIN // @@ -36,21 +46,8 @@ var randi32 = require( './rand_int64.js' ); /** * Default Xorshift128+ PRNG instance. * -* This is a pre-created PRNG instance with a random seed. -* It can be used directly for generating random numbers. -* -* @name xorshift128plus * @type {Function} -* @returns {bigint} pseudorandom 64-bit unsigned integer -* -* @example -* var xorshift128plus = require( '@stdlib/random/base/xorshift128/lib/main.js' ); -* -* var v = xorshift128plus(); -* // returns -* -* var v = xorshift128plus.normalized(); -* // returns +* @returns {number} pseudorandom 32-bit unsigned integer */ var xorshift128plus = factory({ 'seed': randi32() diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js b/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int32.js similarity index 56% rename from lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js rename to lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int32.js index 3ab43f901970..4f15feaa6d52 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int64.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/lib/rand_int32.js @@ -19,50 +19,50 @@ 'use strict'; /** -* Generates random 32-bit integers for seed generation. +* Generates random 32-bit unsigned integer seeds. * -* This module generates random 32-bit unsigned integer seed values -* using Math.random(). These are used to seed the Xorshift128+ PRNG -* when no explicit seed is provided. +* This module generates random 32-bit unsigned integer seed values. +* These are used to seed the Xorshift128+ PRNG when no explicit seed +* is provided by the user. * -* Two 32-bit values are combined to create a 64-bit seed: -* seed = (high << 32) | low +* @private +* @returns {number} random 32-bit unsigned integer * -* This provides better entropy than using a single 32-bit value. +* @example +* var seed = randi32(); +* // returns */ // MODULES // var randu = require( '@stdlib/random/base/randu' ); var floor = require( '@stdlib/math/base/special/floor' ); -var BigInt = require( '@stdlib/bigint/ctor' ); + + +// MAIN // /** -* Generates a random 32-bit unsigned integer. +* Generates a random 32-bit unsigned integer seed. * * @private -* @returns {bigint} random 32-bit value as BigInt +* @returns {number} random 32-bit unsigned integer * * @example * var seed = randi32(); -* // throws +* // returns */ function randi32() { - var seed; - var high; - var low; + /* eslint-disable no-magic-numbers */ + var seed = floor( randu() * 0x100000000 ); - // Generate two 32-bit values and combine them into a 64-bit value - high = floor( randu() * 0x100000000 ); - low = floor( randu() * 0x100000000 ); - seed = (BigInt( high ) << BigInt(32)) | BigInt( low ); + /* eslint-enable no-magic-numbers */ // Ensure non-zero seed - if ( seed === BigInt(0) ) { - seed = BigInt(1); + if ( seed === 0 ) { + seed = 1; } - return seed; + return seed >>> 0; // Ensure unsigned 32-bit } diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/package.json b/lib/node_modules/@stdlib/random/base/xorshift128/package.json index a163ae58b0cb..4ac13ed3347e 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/package.json +++ b/lib/node_modules/@stdlib/random/base/xorshift128/package.json @@ -1,5 +1,5 @@ { - "name": "@stdlib/random/base/xorshift128plus", + "name": "@stdlib/random/base/xorshift128", "version": "0.1.0", "description": "A 128-bit xorshift pseudorandom number generator (PRNG) with a period of approximately 2^128.", "license": "Apache-2.0", @@ -74,7 +74,6 @@ "twister", "seed", "seedable", - "bigint", "64-bit", "period", "equidistribution" diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.factory.js b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.factory.js new file mode 100644 index 000000000000..ac9d3bba527e --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.factory.js @@ -0,0 +1,423 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var isUint32Array = require( '@stdlib/assert/is-uint32array' ); +var Float64Array = require( '@stdlib/array/float64' ); +var Uint32Array = require( '@stdlib/array/uint32' ); +var factory = require( './../lib/factory.js' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.ok( isFunction( factory ), 'main export is a function' ); + t.end(); +}); + +tape( 'factory returns a function', function test( t ) { + var rng = factory(); + t.ok( isFunction( rng ), 'returns a function' ); + t.end(); +}); + +tape( 'factory accepts seed option', function test( t ) { + var rng; + + rng = factory({ + 'seed': 1234 + }); + t.ok( isFunction( rng ), 'returns function with seed option' ); + + rng = factory({ + 'seed': 0 + }); + t.ok( isFunction( rng ), 'returns function with seed 0' ); + + rng = factory({ + 'seed': 0xffffffff + }); + t.ok( isFunction( rng ), 'returns function with max seed' ); + + t.end(); +}); + +tape( 'factory accepts state option', function test( t ) { + var state; + var rng1 = factory({ + 'seed': 1234 + }); + var rng2; + state = rng1.state; + + rng2 = factory({ + 'state': state + }); + t.ok( isFunction( rng2 ), 'returns function with state option' ); + t.end(); +}); + +tape( 'factory accepts copy option', function test( t ) { + var state; + var rng1 = factory({ + 'seed': 5678 + }); + var rng2; + var rng3; + state = rng1.state; + + rng2 = factory({ + 'state': state, + 'copy': true + }); + t.ok( isFunction( rng2 ), 'returns function with copy=true' ); + + rng3 = factory({ + 'state': state, + 'copy': false + }); + t.ok( isFunction( rng3 ), 'returns function with copy=false' ); + + t.end(); +}); + +tape( 'factory with copy=false does not copy state', function test( t ) { + var state = new Uint32Array( 4 ); + var rng = factory({ + 'state': state, + 'copy': false + }); + + // When copy=false, modifications to original state should eventually affect RNG + state[ 0 ] = 9999; + + t.ok( isFunction( rng ), 'returns function with copy=false' ); + t.end(); +}); + +tape( 'factory with copy=true copies state', function test( t ) { + var original = new Uint32Array( 4 ); + var state1; + var state2; + var rng = factory({ + 'state': original, + 'copy': true + }); + state1 = rng.state; + state2 = rng.state; + + t.strictEqual( state1[ 0 ], state2[ 0 ], 'state not affected by modifying original' ); + t.end(); +}); + +tape( 'factory returns PRNG with correct NAME', function test( t ) { + var rng = factory({ + 'seed': 1234 + }); + t.strictEqual( rng.NAME, 'xorshift128+', 'NAME is "xorshift128+"' ); + t.end(); +}); + +tape( 'factory returns PRNG with normalized method', function test( t ) { + var rng = factory({ + 'seed': 2345 + }); + t.ok( isFunction( rng.normalized ), 'has normalized method' ); + t.end(); +}); + +tape( 'factory returns PRNG with copy method', function test( t ) { + var rng = factory({ + 'seed': 3456 + }); + t.ok( isFunction( rng.copy ), 'has copy method' ); + t.end(); +}); + +tape( 'factory returns PRNG with toJSON method', function test( t ) { + var rng = factory({ + 'seed': 4567 + }); + t.ok( isFunction( rng.toJSON ), 'has toJSON method' ); + t.end(); +}); + +tape( 'factory returns PRNG with seed getter', function test( t ) { + var rng = factory({ + 'seed': 5678 + }); + t.ok( typeof rng.seed === 'number', 'seed is accessible' ); + t.end(); +}); + +tape( 'factory returns PRNG with state getter/setter', function test( t ) { + var state; + var rng = factory({ + 'seed': 6789 + }); + + t.ok( isUint32Array( rng.state ), 'state getter works' ); + + state = new Uint32Array( 4 ); + state[ 0 ] = 1000; + state[ 1 ] = 2000; + state[ 2 ] = 3000; + state[ 3 ] = 4000; + + rng.state = state; + t.ok( isUint32Array( rng.state ), 'state setter works' ); + t.end(); +}); + +tape( 'factory throws TypeError when options is not an object', function test( t ) { + var values; + var i; + + values = [ 'invalid', 123, [] ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws on invalid options '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory( value ); + }; + } +}); + +tape( 'factory throws TypeError when seed is invalid', function test( t ) { + var values; + var i; + + values = [ -1, 3.14, 'invalid', {} ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badSeed( values[i] ), TypeError, 'throws on invalid seed '+values[i] ); + } + t.end(); + + function badSeed( value ) { + return function badSeed() { + factory({ + 'seed': value + }); + }; + } +}); + +tape( 'factory throws TypeError when state is not Uint32Array', function test( t ) { + var values; + var i; + + values = [ [], new Float64Array( 4 ), {} ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badState( values[i] ), TypeError, 'throws on invalid state '+values[i] ); + } + t.end(); + + function badState( value ) { + return function badState() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'factory throws RangeError when state has wrong length', function test( t ) { + var values; + var i; + + values = [ + new Uint32Array( 0 ), + new Uint32Array( 2 ), + new Uint32Array( 8 ) + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badRange( values[i] ), RangeError, 'throws on wrong state length' ); + } + t.end(); + + function badRange( value ) { + return function badRange() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'factory throws TypeError when copy is not boolean', function test( t ) { + var values; + var i; + + values = [ 'true', 1, null ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badCopy( values[i] ), TypeError, 'throws on invalid copy '+values[i] ); + } + t.end(); + + function badCopy( value ) { + return function badCopy() { + factory({ + 'seed': 1234, + 'copy': value + }); + }; + } +}); + +tape( 'factory without options uses random seed', function test( t ) { + var rng1 = factory(); + var rng2 = factory(); + var v1 = rng1(); + var v2 = rng2(); + + // Very unlikely to be equal if truly random + t.notEqual( v1, v2, 'different random seeds produce different outputs' ); + t.end(); +}); + +tape( 'factory with same seed produces deterministic sequence', function test( t ) { + var rng1 = factory({ + 'seed': 12345 + }); + var rng2 = factory({ + 'seed': 12345 + }); + var i; + + for ( i = 0; i < 100; i++ ) { + t.strictEqual( rng1(), rng2(), 'same seed at iteration ' + i ); + } + t.end(); +}); + +tape( 'factory with state produces deterministic continuation', function test( t ) { + var state; + var rng1 = factory({ + 'seed': 54321 + }); + var rng2; + var i; + + // Generate and skip values + for ( i = 0; i < 50; i++ ) { + rng1(); + } + + // Save state + state = rng1.state; + + // Create second PRNG with same state + rng2 = factory({ + 'state': state + }); + + // Verify same continuation + for ( i = 0; i < 100; i++ ) { + t.strictEqual( rng1(), rng2(), 'same state continuation at iteration ' + i ); + } + t.end(); +}); + +tape( 'factory creates independent PRNGs', function test( t ) { + var rng1 = factory({ + 'seed': 1111 + }); + var rng3 = factory({ + 'seed': 2222 + }); + var v1 = rng1(); + var v3 = rng3(); + + t.notEqual( v1, v3, 'different seeds produce different output' ); + t.end(); +}); + +tape( 'factory output is 32-bit unsigned integer', function test( t ) { + var rng = factory({ + 'seed': 99999 + }); + var v; + var i; + + for ( i = 0; i < 100; i++ ) { + v = rng(); + t.ok( v >= 0, 'output >= 0' ); + t.ok( v <= 0xffffffff, 'output <= 2^32-1' ); + t.ok( Number.isInteger( v ), 'output is integer' ); + } + t.end(); +}); + +tape( 'factory normalized output is in [0,1)', function test( t ) { + var rng = factory({ + 'seed': 88888 + }); + var v; + var i; + + for ( i = 0; i < 100; i++ ) { + v = rng.normalized(); + t.ok( v >= 0, 'normalized output >= 0' ); + t.ok( v < 1, 'normalized output < 1' ); + } + t.end(); +}); + +tape( 'factory state length is always 4', function test( t ) { + var rng1 = factory(); + var rng2 = factory({ + 'seed': 1234 + }); + var rng3 = factory({ + 'state': new Uint32Array( 4 ) + }); + + t.strictEqual( rng1.state.length, 4, 'random seed state length is 4' ); + t.strictEqual( rng2.state.length, 4, 'seeded PRNG state length is 4' ); + t.strictEqual( rng3.state.length, 4, 'state-initialized PRNG state length is 4' ); + t.end(); +}); + +tape( 'factory state is Uint32Array', function test( t ) { + var rng1 = factory(); + var rng2 = factory({ + 'seed': 1234 + }); + var rng3 = factory({ + 'state': new Uint32Array( 4 ) + }); + + t.ok( isUint32Array( rng1.state ), 'random seed state is Uint32Array' ); + t.ok( isUint32Array( rng2.state ), 'seeded PRNG state is Uint32Array' ); + t.ok( isUint32Array( rng3.state ), 'state-initialized PRNG state is Uint32Array' ); + t.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js index a192ab8f5fc7..799bd87d9601 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js @@ -21,8 +21,9 @@ // MODULES // var tape = require( 'tape' ); -var isBigInt = require( '@stdlib/assert/is-bigint' ); -var BigInt = require( '@stdlib/bigint/ctor' ); +var isFunction = require( '@stdlib/assert/is-function' ); +var isUint32Array = require( '@stdlib/assert/is-uint32array' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var xorshift128plus = require( './../lib' ); @@ -30,490 +31,439 @@ var xorshift128plus = require( './../lib' ); tape( 'main export is a function', function test( t ) { t.ok( true, __filename ); - t.strictEqual( typeof xorshift128plus, 'function', 'main export is a function' ); + t.ok( isFunction( xorshift128plus ), 'main export is a function' ); t.end(); }); -tape( 'calling the function without arguments returns a PRNG function', function test( t ) { +tape( 'when called with no arguments, returns a pseudorandom number generator function', function test( t ) { var rng = xorshift128plus(); - t.strictEqual( typeof rng, 'function', 'returns a function' ); + t.ok( isFunction( rng ), 'returns a function' ); t.end(); }); -tape( 'calling with empty options object returns a PRNG function', function test( t ) { - var rng = xorshift128plus( {} ); - t.strictEqual( typeof rng, 'function', 'returns a function' ); - t.end(); -}); - -tape( 'calling with a number seed returns a PRNG function', function test( t ) { - var rng = xorshift128plus({ - 'seed': 12345 - }); - t.strictEqual( typeof rng, 'function', 'returns a function' ); - t.end(); -}); - -tape( 'calling with a BigInt seed returns a PRNG function', function test( t ) { - var rng = xorshift128plus({ - 'seed': BigInt( 12345 ) - }); - t.strictEqual( typeof rng, 'function', 'returns a function' ); - t.end(); -}); - -tape( 'seeded generators with same seed produce identical sequences', function test( t ) { - var rng1 = xorshift128plus({ - 'seed': BigInt( 54321 ) - }); - var rng2 = xorshift128plus({ - 'seed': BigInt( 54321 ) - }); +tape( 'when called with a seed option, returns a PRNG with deterministic output', function test( t ) { + var rng1; + var rng2; + var v1; + var v2; var i; - for ( i = 0; i < 100; i++ ) { - t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); - } - t.end(); -}); - -tape( 'different seeds produce different sequences', function test( t ) { - var different = 0; - var rng1 = xorshift128plus({ - 'seed': BigInt( 111 ) + rng1 = xorshift128plus({ + 'seed': 1234 }); - var rng2 = xorshift128plus({ - 'seed': BigInt( 222 ) + rng2 = xorshift128plus({ + 'seed': 1234 }); - var i; for ( i = 0; i < 100; i++ ) { - if ( rng1().toString() !== rng2().toString() ) { - different += 1; - } + v1 = rng1(); + v2 = rng2(); + t.strictEqual( v1, v2, 'same seed produces same output at iteration ' + i ); } - t.strictEqual( different > 95, true, 'most values are different' ); t.end(); }); -tape( 'zero seed is converted to 1n', function test( t ) { +tape( 'when called with different seeds, produces different outputs', function test( t ) { var rng1 = xorshift128plus({ - 'seed': BigInt( 0 ) + 'seed': 111 }); var rng2 = xorshift128plus({ - 'seed': BigInt( 1 ) + 'seed': 222 }); - var i; + var v1 = rng1(); + var v2 = rng2(); - for ( i = 0; i < 50; i++ ) { - t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); - } + t.notEqual( v1, v2, 'different seeds produce different outputs' ); t.end(); }); -tape( 'accepts number seed and converts to BigInt', function test( t ) { - var rng1 = xorshift128plus({ +tape( 'generated output is a 32-bit unsigned integer', function test( t ) { + var rng = xorshift128plus({ 'seed': 12345 }); - var rng2 = xorshift128plus({ - 'seed': BigInt( 12345 ) - }); + var v; var i; - for ( i = 0; i < 50; i++ ) { - t.strictEqual( rng1().toString(), rng2().toString(), 'iteration '+i+': same output' ); + for ( i = 0; i < 100; i++ ) { + v = rng(); + t.ok( v >= 0 && v <= 0xffffffff, 'output in range [0, 2^32)' ); + t.ok( Number.isInteger( v ), 'output is integer' ); } t.end(); }); -tape( 'the PRNG returns BigInt values', function test( t ) { +tape( 'generated output is unsigned 32-bit', function test( t ) { var rng = xorshift128plus({ - 'seed': BigInt( 42 ) + 'seed': 9999 }); var v; - var i; - for ( i = 0; i < 100; i++ ) { - v = rng(); - t.strictEqual( isBigInt( v ), true, 'iteration '+i+': returns BigInt' ); - } + v = rng(); + t.ok( v >= 0, 'output >= 0' ); + t.ok( v < 0x100000000, 'output < 2^32' ); t.end(); }); -tape( 'the PRNG returns values in [0, 2^64)', function test( t ) { +tape( 'PRNG has a normalized method', function test( t ) { var rng = xorshift128plus({ - 'seed': BigInt( 42 ) + 'seed': 5555 }); - var max = BigInt( '0xffffffffffffffff' ); - var v; - var i; - - for ( i = 0; i < 100; i++ ) { - v = rng(); - t.strictEqual( v >= BigInt( 0 ) && v <= max, true, 'iteration '+i+': value in valid range' ); - } + t.ok( isFunction( rng.normalized ), 'has normalized method' ); t.end(); }); -tape( 'the normalized method returns numbers in [0, 1)', function test( t ) { +tape( 'normalized method returns value in [0,1)', function test( t ) { var rng = xorshift128plus({ - 'seed': BigInt( 42 ) + 'seed': 5555 }); var v; var i; for ( i = 0; i < 1000; i++ ) { v = rng.normalized(); - t.strictEqual( typeof v, 'number', 'iteration '+i+': returns number' ); - t.strictEqual( v >= 0.0 && v < 1.0, true, 'iteration '+i+': in [0, 1)' ); - } - t.end(); -}); - -tape( 'normalized sequences are deterministic', function test( t ) { - var rng1 = xorshift128plus({ - 'seed': BigInt( 99999 ) - }); - var rng2 = xorshift128plus({ - 'seed': BigInt( 99999 ) - }); - var i; - - for ( i = 0; i < 100; i++ ) { - t.strictEqual( rng1.normalized(), rng2.normalized(), 'iteration '+i+': same normalized output' ); + t.ok( v >= 0 && v < 1, 'normalized value in [0,1)' ); } t.end(); }); -tape( 'the PRNG has a seed property', function test( t ) { - var seed; +tape( 'PRNG has a seed property', function test( t ) { var rng = xorshift128plus({ - 'seed': BigInt( 12345 ) + 'seed': 3333 }); - seed = rng.seed; - - t.strictEqual( isBigInt( seed ), true, 'seed is BigInt' ); - t.strictEqual( seed, BigInt( 12345 ), 'seed value is correct' ); + t.ok( typeof rng.seed === 'number', 'seed property is a number' ); t.end(); }); -tape( 'the PRNG has a state property', function test( t ) { +tape( 'PRNG has a state property (getter)', function test( t ) { var state; var rng = xorshift128plus({ - 'seed': BigInt( 12345 ) + 'seed': 4444 }); state = rng.state; - t.strictEqual( Array.isArray( state ), true, 'state is Array' ); - t.strictEqual( state.length, 6, 'state has correct length' ); - t.strictEqual( state[ 0 ], BigInt( 1 ), 'version is 1n' ); - t.strictEqual( state[ 1 ], BigInt( 2 ), 'state length is 2n' ); - t.strictEqual( isBigInt( state[ 2 ] ), true, 'state[0] is BigInt' ); - t.strictEqual( isBigInt( state[ 3 ] ), true, 'state[1] is BigInt' ); - t.strictEqual( state[ 4 ], BigInt( 1 ), 'seed length is 1n' ); - t.strictEqual( state[ 5 ], BigInt( 12345 ), 'seed is stored' ); + t.ok( isUint32Array( state ), 'state is a Uint32Array' ); + t.strictEqual( state.length, 4, 'state has length 4' ); t.end(); }); -tape( 'calling .copy() returns an independent PRNG with same state', function test( t ) { +tape( 'PRNG state property can be set', function test( t ) { + var state; var rng1 = xorshift128plus({ - 'seed': BigInt( 54321 ) + 'seed': 7777 + }); + var rng2 = xorshift128plus({ + 'seed': 1111 }); - var rng2; var v1; var v2; - var i; - // Generate some values to advance state - for ( i = 0; i < 50; i++ ) { - rng1(); - } + // Save state BEFORE generating value + state = rng1.state; - // Copy the PRNG - rng2 = rng1.copy(); + // Generate value + v1 = rng1(); + + // Restore state in rng2 + rng2.state = state; + + // Should match + v2 = rng2(); + t.strictEqual( v1, v2, 'setting state produces same sequence' ); - // Both should generate identical sequences from this point - for ( i = 0; i < 100; i++ ) { - v1 = rng1(); - v2 = rng2(); - t.strictEqual( v1.toString(), v2.toString(), 'iteration '+i+': identical output' ); - } t.end(); }); -tape( 'setting state via .state property restores sequence', function test( t ) { - var state; +tape( 'PRNG has a copy method', function test( t ) { + var copy; var rng = xorshift128plus({ - 'seed': BigInt( 54321 ) + 'seed': 2222 }); - var arr; - var i; - - // Generate some values - for ( i = 0; i < 100; i++ ) { - rng(); - } - - // Capture state - state = rng.state; - - // Generate more values - arr = []; - for ( i = 0; i < 100; i++ ) { - arr.push( rng() ); - } - // Restore state - rng.state = state; + t.ok( isFunction( rng.copy ), 'has copy method' ); - // Verify sequence is replayed - for ( i = 0; i < 100; i++ ) { - t.strictEqual( rng().toString(), arr[ i ].toString(), 'iteration '+i+': restored sequence' ); - } + copy = rng.copy(); + t.ok( isFunction( copy ), 'copy returns a function' ); t.end(); }); -tape( 'copy option=true makes independent copy', function test( t ) { - var state = [ - BigInt( 1 ), - BigInt( 2 ), - BigInt( 12345 ), - BigInt( 67890 ), - BigInt( 1 ), - BigInt( 12345 ) - ]; - var rng1 = xorshift128plus({ - 'state': state, - 'copy': true - }); - var rng2 = xorshift128plus({ - 'state': state, - 'copy': true +tape( 'copy method creates an independent PRNG at same state', function test( t ) { + var copy; + var rng = xorshift128plus({ + 'seed': 6666 }); var v1; var v2; + var i; - state[ 2 ] = BigInt( 99999 ); // Modify original state array + // Generate some values + for ( i = 0; i < 10; i++ ) { + rng(); + } - v1 = rng1(); - v2 = rng2(); + // Create copy at current state + copy = rng.copy(); - t.strictEqual( v1.toString(), v2.toString(), 'copies are independent of original' ); + // Both should produce same sequence + for ( i = 0; i < 50; i++ ) { + v1 = rng(); + v2 = copy(); + t.strictEqual( v1, v2, 'copy at state ' + i + ' produces same output' ); + } t.end(); }); -tape( 'the PRNG has a toJSON method', function test( t ) { +tape( 'PRNG has a toJSON method', function test( t ) { var json; var rng = xorshift128plus({ - 'seed': BigInt( 12345 ) + 'seed': 8888 }); - json = rng.toJSON(); - t.strictEqual( typeof json, 'object', 'returns object' ); - t.strictEqual( json.type, 'PRNG', 'type is PRNG' ); - t.strictEqual( json.name, 'xorshift128+', 'name is correct' ); - t.strictEqual( Array.isArray( json.state ), true, 'state is array' ); - t.strictEqual( json.state.length, 6, 'state array has correct length' ); + t.ok( isFunction( rng.toJSON ), 'has toJSON method' ); + + json = rng.toJSON(); + t.ok( typeof json === 'object', 'toJSON returns object' ); + t.strictEqual( json.type, 'PRNG', 'JSON object has type property' ); + t.strictEqual( json.name, 'xorshift128+', 'JSON object has correct name' ); + t.ok( isUint32Array( json.state ), 'JSON state is Uint32Array' ); t.end(); }); -tape( 'the PRNG has a NAME property', function test( t ) { - var rng = xorshift128plus(); - t.strictEqual( rng.NAME, 'xorshift128+', 'NAME is correct' ); +tape( 'NAME property is set correctly', function test( t ) { + var rng = xorshift128plus({ + 'seed': 1111 + }); + t.strictEqual( rng.NAME, 'xorshift128+', 'NAME property is correct' ); t.end(); }); -tape( 'throws error if options is not an object', function test( t ) { +tape( 'when called with invalid options, throws error', function test( t ) { var values; var i; - values = [ - 'string', - 123, - true, - null, - undefined, - [], - function noop() {} - ]; - + // Non-object options + values = [ 'invalid' ]; for ( i = 0; i < values.length; i++ ) { - t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + t.throws( badValue( values[i] ), TypeError, 'throws on non-object options' ); } - t.end(); - function badValue( value ) { - return function badValue() { - xorshift128plus( value ); - }; + // Invalid seeds + values = [ -1, 3.14 ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badSeed( values[i] ), TypeError, 'throws on invalid seed '+values[i] ); } -}); -tape( 'throws error if seed is not a number or BigInt', function test( t ) { - var values; - var i; - - values = [ - 'string', - true, - null, - undefined, - {}, - [] - ]; + // Invalid state types + values = [ [] ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badState( values[i] ), TypeError, 'throws on non-Uint32Array state' ); + } + // Invalid state length + values = [ new Uint32Array( 2 ) ]; for ( i = 0; i < values.length; i++ ) { - t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + t.throws( badState( values[i] ), RangeError, 'throws on wrong state length' ); } + t.end(); function badValue( value ) { return function badValue() { + xorshift128plus( value ); + }; + } + + function badSeed( value ) { + return function badSeed() { xorshift128plus({ 'seed': value }); }; } -}); - -tape( 'throws error if copy option is not a boolean', function test( t ) { - var values = [ 'string', 123, null, undefined, {}, [] ]; - var i; - - for ( i = 0; i < values.length; i++ ) { - t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); - } - t.end(); - function badValue( value ) { - return function badValue() { + function badState( value ) { + return function badState() { xorshift128plus({ - 'copy': value + 'state': value }); }; } }); -tape( 'throws error if state is not an Array', function test( t ) { - var values = [ 'string', 123, true, null, undefined, {}, function noop() {} ]; +tape( 'generated sequence has good variety', function test( t ) { + var values = []; + var unique; + var rng = xorshift128plus({ + 'seed': 9876 + }); var i; - for ( i = 0; i < values.length; i++ ) { - t.throws(badValue( values[ i ] ), TypeError, 'throws TypeError for '+typeof values[ i ]); + for ( i = 0; i < 1000; i++ ) { + values.push( rng() ); } + + unique = new Set( values ); + t.ok( unique.size > 990, 'output values are mostly unique' ); t.end(); +}); - function badValue( value ) { - return function badValue() { - xorshift128plus({ - 'state': value - }); - }; +tape( 'entropy mixing distributes bits well', function test( t ) { + var bitCounts = []; + var count; + var ratio; + var rng = xorshift128plus({ + 'seed': 5432 + }); + var v; + var i; + var b; + + // Initialize bit counters + for ( b = 0; b < 32; b++ ) { + bitCounts[ b ] = 0; + } + + // Generate values and count bits + for ( i = 0; i < 10000; i++ ) { + v = rng(); + for ( b = 0; b < 32; b++ ) { + if ( v & (1 << b) ) { + bitCounts[ b ] += 1; + } + } } + + // Check that bits are distributed ~50/50 + count = 0; + for ( b = 0; b < 32; b++ ) { + ratio = bitCounts[ b ] / 10000; + if ( ratio > 0.40 && ratio < 0.60 ) { + count += 1; + } + } + + t.ok( count >= 25, 'most bits (~' + count + '/32) have good distribution' ); + t.end(); +}); + +tape( 'state property returns independent copy', function test( t ) { + var state2; + var state1; + var rng = xorshift128plus({ + 'seed': 1357 + }); + state1 = rng.state; + state2 = rng.state; + + t.notEqual( state1, state2, 'state getter returns new array each time' ); + + // Modifying returned state should not affect PRNG + state1[ 0 ] = 0xffffffff; + state2 = rng.state; + t.notEqual( state2[ 0 ], 0xffffffff, 'modifying returned state does not affect PRNG' ); + t.end(); }); -tape( 'throws error if state has incorrect length', function test( t ) { - var values = [ - [], - [ BigInt( 1 ) ], - [ BigInt( 1 ), BigInt( 2 ) ] - ]; +tape( 'setting invalid state throws error', function test( t ) { + var values; + var rng = xorshift128plus({ + 'seed': 2468 + }); var i; + // Non-Uint32Array state + values = [ [] ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws on non-Uint32Array state' ); + } + + // Wrong state length + values = [ new Uint32Array( 2 ) ]; for ( i = 0; i < values.length; i++ ) { - t.throws(badValue( values[ i ] ), RangeError, 'throws RangeError for length '+values[ i ].length); + t.throws( badRange( values[i] ), RangeError, 'throws on wrong state length' ); } + t.end(); function badValue( value ) { return function badValue() { - xorshift128plus({ - 'state': value - }); + rng.state = value; }; } -}); -tape( 'throws error if state has incorrect version', function test( t ) { - var state = [ - BigInt( 0 ), - BigInt( 2 ), - BigInt( 12345 ), - BigInt( 67890 ), - BigInt( 1 ), - BigInt( 12345 ) - ]; - - t.throws(function testFn() { - xorshift128plus({ - 'state': state - }); - }, RangeError, 'throws RangeError for invalid version'); - t.end(); + function badRange( value ) { + return function badRange() { + rng.state = value; + }; + } }); -tape( 'throws error if state has incorrect state length', function test( t ) { - var state = [ - BigInt( 1 ), - BigInt( 1 ), - BigInt( 12345 ), - BigInt( 67890 ), - BigInt( 1 ), - BigInt( 12345 ) - ]; - - t.throws(function testFn() { - xorshift128plus({ - 'state': state - }); - }, RangeError, 'throws RangeError for invalid state length'); +tape( 'copy method creates independent PRNG', function test( t ) { + var copy1; + var rng = xorshift128plus({ + 'seed': 3579 + }); + var a; + var b; + + copy1 = rng.copy(); + + // First values should match + a = rng(); + b = copy1(); + t.strictEqual( a, b, 'copy starts with same state' ); + + // Next values should diverge independently + a = rng(); + b = copy1(); + t.notEqual( a, b, 'original and copy diverge independently' ); + t.end(); }); -tape( 'the PRNG has good period (state doesn\'t cycle quickly)', function test( t ) { - var firstVal; - var found; - var rng; - var i; - - rng = xorshift128plus({ - 'seed': BigInt( 42 ) +tape( 'normalized output matches formula', function test( t ) { + var expected; + var vNorm; + var rng2 = xorshift128plus({ + 'seed': 4680 }); - firstVal = rng(); - found = false; - - // Generate 10000 values and check we don't see the initial state repeated - for ( i = 1; i < 10000; i++ ) { - if ( rng().toString() === firstVal.toString() ) { - found = true; - break; - } - } + var rng = xorshift128plus({ + 'seed': 4680 + }); + expected = (rng2() / 0x100000000); + vNorm = rng.normalized(); - t.strictEqual( found, false, 'no premature cycling detected in 10000 iterations' ); + t.strictEqual( vNorm, expected, 'normalized output matches formula' ); t.end(); }); -tape( 'normalized output is reasonably uniform', function test( t ) { - var ratio; - var high = 0; - var rng = xorshift128plus({ - 'seed': BigInt( 42 ) +tape( 'PRNG state can be restored and continued', function test( t ) { + var state; + var rng1 = xorshift128plus({ + 'seed': 5791 }); - var low = 0; - var v; + var rng2 = xorshift128plus({ + 'seed': 9999 + }); + var v1; + var v2; var i; - for ( i = 0; i < 10000; i++ ) { - v = rng.normalized(); - if ( v < 0.5 ) { - low += 1; - } else { - high += 1; - } + // Generate some values from rng1 + for ( i = 0; i < 50; i++ ) { + rng1(); } - ratio = low / high; - t.strictEqual( ratio > 0.9 && ratio < 1.1, true, 'distribution is approximately uniform' ); + // Save state + state = rng1.state; + + // Set rng2 to this state + rng2.state = state; + + // Continue and verify same sequence + for ( i = 0; i < 100; i++ ) { + v1 = rng1(); + v2 = rng2(); + t.strictEqual( v1, v2, 'restored state produces same continuation at ' + i ); + } t.end(); }); From 6c46ec027ae202e195daa2285926c7c9b9415ee1 Mon Sep 17 00:00:00 2001 From: Ayushi Jain Date: Wed, 22 Apr 2026 06:26:10 +0000 Subject: [PATCH 7/7] docs: improve test files --- .../random/base/xorshift128/examples/index.js | 2 +- .../random/base/xorshift128/test/test.js | 23 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js index e379d3ff7250..986583488fbd 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/examples/index.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2018 The Stdlib Authors. +* Copyright (c) 2026 The Stdlib Authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js index 799bd87d9601..ad4bc072ad44 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js +++ b/lib/node_modules/@stdlib/random/base/xorshift128/test/test.js @@ -397,29 +397,6 @@ tape( 'setting invalid state throws error', function test( t ) { } }); -tape( 'copy method creates independent PRNG', function test( t ) { - var copy1; - var rng = xorshift128plus({ - 'seed': 3579 - }); - var a; - var b; - - copy1 = rng.copy(); - - // First values should match - a = rng(); - b = copy1(); - t.strictEqual( a, b, 'copy starts with same state' ); - - // Next values should diverge independently - a = rng(); - b = copy1(); - t.notEqual( a, b, 'original and copy diverge independently' ); - - t.end(); -}); - tape( 'normalized output matches formula', function test( t ) { var expected; var vNorm;