From 001eadfdbef99303d0b4407bbc3ca70f43591a8f Mon Sep 17 00:00:00 2001 From: impawstarlight Date: Sun, 23 Mar 2025 02:12:15 +0600 Subject: [PATCH 1/6] chore: copy files from `random/base/minstd` --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: passed - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: passed - task: lint_c_examples status: passed - task: lint_c_benchmarks status: passed - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- .../@stdlib/random/base/xorshift/README.md | 345 ++++ .../xorshift/benchmark/benchmark.factory.js | 104 ++ .../base/xorshift/benchmark/benchmark.js | 67 + .../xorshift/benchmark/benchmark.to_json.js | 48 + .../random/base/xorshift/benchmark/c/Makefile | 146 ++ .../base/xorshift/benchmark/c/benchmark.c | 373 ++++ .../random/base/xorshift/docs/repl.txt | 188 ++ .../base/xorshift/docs/types/index.d.ts | 197 ++ .../random/base/xorshift/docs/types/test.ts | 106 ++ .../random/base/xorshift/examples/c/Makefile | 146 ++ .../random/base/xorshift/examples/c/example.c | 75 + .../random/base/xorshift/examples/index.js | 47 + .../include/stdlib/random/base/xorshift.h | 69 + .../random/base/xorshift/lib/factory.js | 416 +++++ .../@stdlib/random/base/xorshift/lib/index.js | 57 + .../@stdlib/random/base/xorshift/lib/main.js | 102 + .../random/base/xorshift/lib/rand_int32.js | 52 + .../random/base/xorshift/manifest.json | 40 + .../@stdlib/random/base/xorshift/package.json | 77 + .../@stdlib/random/base/xorshift/src/main.c | 430 +++++ .../random/base/xorshift/test/test.factory.js | 1634 +++++++++++++++++ .../@stdlib/random/base/xorshift/test/test.js | 240 +++ 22 files changed, 4959 insertions(+) create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/README.md create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.factory.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.to_json.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/Makefile create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/benchmark.c create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/examples/c/Makefile create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/examples/c/example.c create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/examples/index.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/lib/index.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/lib/main.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/lib/rand_int32.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/manifest.json create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/package.json create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/src/main.c create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js create mode 100644 lib/node_modules/@stdlib/random/base/xorshift/test/test.js diff --git a/lib/node_modules/@stdlib/random/base/xorshift/README.md b/lib/node_modules/@stdlib/random/base/xorshift/README.md new file mode 100644 index 000000000000..11d568e94bdb --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/README.md @@ -0,0 +1,345 @@ + + +# MINSTD + +> A linear congruential pseudorandom number generator ([LCG][lcg]) based on Park and Miller. + +
+ +## Usage + +```javascript +var xorshift = require( '@stdlib/random/base/xorshift' ); +``` + +#### xorshift() + +Returns a pseudorandom integer on the interval `[1, 2147483646]`. + +```javascript +var r = xorshift(); +// returns +``` + +#### xorshift.normalized() + +Returns a pseudorandom number on the interval `[0,1)`. + +```javascript +var r = xorshift.normalized(); +// returns +``` + +#### xorshift.factory( \[options] ) + +Returns a linear congruential pseudorandom number generator ([LCG][lcg]). + +```javascript +var rand = xorshift.factory(); +``` + +The function accepts the following `options`: + +- **seed**: pseudorandom number generator seed. +- **state**: an [`Int32Array`][@stdlib/array/int32] 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 integer is used to seed the returned generator. To seed the generator, provide either an `integer` on the interval `[1, 2147483646]` + +```javascript +var rand = xorshift.factory({ + 'seed': 1234 +}); + +var r = rand(); +// returns 20739838 +``` + +or, for arbitrary length seeds, an array-like `object` containing signed 32-bit integers + +```javascript +var Int32Array = require( '@stdlib/array/int32' ); + +var rand = xorshift.factory({ + 'seed': new Int32Array( [ 1234 ] ) +}); + +var r = rand(); +// returns 20739838 +``` + +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 = xorshift(); +} + +// Create a new PRNG initialized to the current state of `xorshift`: +var rand = xorshift.factory({ + 'state': xorshift.state +}); + +// Test that the generated pseudorandom numbers are the same: +var bool = ( rand() === xorshift() ); +// returns true +``` + +#### xorshift.NAME + +The generator name. + +```javascript +var str = xorshift.NAME; +// returns 'xorshift' +``` + +#### xorshift.MIN + +Minimum possible value. + +```javascript +var min = xorshift.MIN; +// returns 1 +``` + +#### xorshift.MAX + +Maximum possible value. + +```javascript +var max = xorshift.MAX; +// returns 2147483646 +``` + +#### xorshift.seed + +The value used to seed `xorshift()`. + +```javascript +// Generate pseudorandom values... +var r; +var i; +for ( i = 0; i < 100; i++ ) { + r = xorshift(); +} + +// Generate the same pseudorandom values... +var rand = xorshift.factory({ + 'seed': xorshift.seed +}); +for ( i = 0; i < 100; i++ ) { + r = rand(); +} +``` + +#### xorshift.seedLength + +Length of generator seed. + +```javascript +var len = xorshift.seedLength; +// returns +``` + +#### xorshift.state + +Writable property for getting and setting the generator state. + +```javascript +var r = xorshift(); +// returns + +r = xorshift(); +// returns + +// ... + +// Get the current state: +var state = xorshift.state; +// returns + +r = xorshift(); +// returns + +r = xorshift(); +// returns + +// Reset the state: +xorshift.state = state; + +// Replay the last two pseudorandom numbers: +r = xorshift(); +// returns + +r = xorshift(); +// returns + +// ... +``` + +#### xorshift.stateLength + +Length of generator state. + +```javascript +var len = xorshift.stateLength; +// returns +``` + +#### xorshift.byteLength + +Size (in bytes) of generator state. + +```javascript +var sz = xorshift.byteLength; +// returns +``` + +#### xorshift.toJSON() + +Serializes the pseudorandom number generator as a JSON object. + +```javascript +var o = xorshift.toJSON(); +// returns { 'type': 'PRNG', 'name': '...', 'state': {...}, 'params': [] } +``` + +
+ + + +
+ +## Notes + +- The generator has a period of approximately `2.1e9` (see [Numerical Recipes in C, 2nd Edition](#references), p. 279). +- An [LCG][lcg] is fast and uses little memory. On the other hand, because the generator is a simple [linear congruential generator][lcg], the generator has recognized shortcomings. By today's PRNG standards, the generator's period is relatively short. More importantly, the "randomness quality" of the generator's output is lacking. These defects make the generator unsuitable, for example, in Monte Carlo simulations and in cryptographic applications. For more on the advantages and disadvantages of [LCGs][lcg], see [Wikipedia][pros-cons]. +- 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 xorshift = require( '@stdlib/random/base/xorshift' ); + +// Generate pseudorandom numbers... +var i; +for ( i = 0; i < 100; i++ ) { + console.log( xorshift() ); +} + +// Create a new pseudorandom number generator... +var seed = 1234; +var rand = xorshift.factory({ + 'seed': seed +}); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} + +// Create another pseudorandom number generator using a previous seed... +rand = xorshift.factory({ + 'seed': xorshift.seed +}); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} +``` + +
+ + + +* * * + +
+ +## References + +- Park, S. K., and K. W. Miller. 1988. "Random Number Generators: Good Ones Are Hard to Find." _Communications of the ACM_ 31 (10). New York, NY, USA: ACM: 1192–1201. doi:[10.1145/63039.63042][@park:1988]. +- Press, William H., Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling. 1992. _Numerical Recipes in C: The Art of Scientific Computing, Second Edition_. Cambridge University Press. + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.factory.js b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.factory.js new file mode 100644 index 000000000000..ca16eef6c11a --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.factory.js @@ -0,0 +1,104 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 bench = require( '@stdlib/bench' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var Int32Array = require( '@stdlib/array/int32' ); +var pkg = require( './../package.json' ).name; +var factory = require( './../lib' ).factory; + + +// MAIN // + +bench( pkg+':factory', function benchmark( b ) { + var f; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + f = factory(); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + if ( isnan( f() ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':factory:seed=', function benchmark( b ) { + var opts; + var f; + var i; + + opts = { + 'seed': 1 + }; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + opts.seed = i + 1; + f = factory( opts ); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + if ( isnan( f() ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':factory:seed=', function benchmark( b ) { + var seed; + var opts; + var f; + var i; + + opts = {}; + + seed = new Int32Array( 10 ); + for ( i = 0; i < seed.length; i++ ) { + seed[ i ] = 123 + i; + } + opts.seed = seed; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + opts.seed[ 0 ] = i + 1; + f = factory( opts ); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + if ( isnan( f() ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.js b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.js new file mode 100644 index 000000000000..26fe5b759fb5 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.js @@ -0,0 +1,67 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 bench = require( '@stdlib/bench' ); +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var pkg = require( './../package.json' ).name; +var xorshift = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var z; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = xorshift(); + if ( isnan( z ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( z ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( pkg+':normalized', function benchmark( b ) { + var z; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + z = xorshift.normalized(); + if ( isnan( z ) ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( isnan( z ) ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.to_json.js b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.to_json.js new file mode 100644 index 000000000000..d3124e9b9ec6 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/benchmark.to_json.js @@ -0,0 +1,48 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 bench = require( '@stdlib/bench' ); +var isObject = require( '@stdlib/assert/is-plain-object' ); +var pkg = require( './../package.json' ).name; +var rand = require( './../lib' ); + + +// MAIN // + +bench( pkg+':toJSON', function benchmark( b ) { + var o; + var i; + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + o = rand.toJSON(); + if ( typeof o !== 'object' ) { + b.fail( 'should return an object' ); + } + } + b.toc(); + if ( !isObject( o ) ) { + b.fail( 'should return an object' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/Makefile b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/Makefile new file mode 100644 index 000000000000..c12ea1918c97 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/Makefile @@ -0,0 +1,146 @@ +#/ +# @license Apache-2.0 +# +# 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. +# 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. +#/ + +# VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + +# Define the program used for compiling C source files: +ifdef C_COMPILER + CC := $(C_COMPILER) +else + CC := gcc +endif + +# Define the command-line options when compiling C files: +CFLAGS ?= \ + -std=c99 \ + -O3 \ + -Wall \ + -pedantic + +# Determine whether to generate position independent code ([1][1], [2][2]). +# +# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options +# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option +ifeq ($(OS), WINNT) + fPIC ?= +else + fPIC ?= -fPIC +endif + +# List of includes (e.g., `-I /foo/bar -I /beep/boop/include`): +INCLUDE ?= + +# List of source files: +SOURCE_FILES ?= + +# List of libraries (e.g., `-lopenblas -lpthread`): +LIBRARIES ?= + +# List of library paths (e.g., `-L /foo/bar -L /beep/boop`): +LIBPATH ?= + +# List of C targets: +c_targets := benchmark.out + + +# RULES # + +#/ +# Compiles C source files. +# +# @param {string} SOURCE_FILES - list of C source files +# @param {string} [INCLUDE] - list of includes (e.g., `-I /foo/bar -I /beep/boop`) +# @param {string} [LIBRARIES] - list of libraries (e.g., `-lpthread -lblas`) +# @param {string} [LIBPATH] - list of library paths (e.g., `-L /foo/bar -L /beep/boop`) +# @param {string} [C_COMPILER] - C compiler +# @param {string} [CFLAGS] - C compiler flags +# @param {(string|void)} [fPIC] - compiler flag indicating whether to generate position independent code +# +# @example +# make +# +# @example +# make all +#/ +all: $(c_targets) + +.PHONY: all + +#/ +# Compiles C source files. +# +# @private +# @param {string} SOURCE_FILES - list of C source files +# @param {(string|void)} INCLUDE - list of includes (e.g., `-I /foo/bar -I /beep/boop`) +# @param {(string|void)} LIBRARIES - list of libraries (e.g., `-lpthread -lblas`) +# @param {(string|void)} LIBPATH - list of library paths (e.g., `-L /foo/bar -L /beep/boop`) +# @param {string} CC - C compiler +# @param {string} CFLAGS - C compiler flags +# @param {(string|void)} fPIC - compiler flag indicating whether to generate position independent code +#/ +$(c_targets): %.out: %.c + $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES) + +#/ +# Runs compiled benchmarks. +# +# @example +# make run +#/ +run: $(c_targets) + $(QUIET) ./$< + +.PHONY: run + +#/ +# Removes generated files. +# +# @example +# make clean +#/ +clean: + $(QUIET) -rm -f *.o *.out + +.PHONY: clean diff --git a/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/benchmark.c b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/benchmark.c new file mode 100644 index 000000000000..e516982f2dd9 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/benchmark/c/benchmark.c @@ -0,0 +1,373 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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. +*/ + +#include "stdlib/random/base/xorshift.h" +#include "stdlib/random/base/shared.h" +#include +#include +#include +#include +#include +#include + +#define NAME "base/xorshift" +#define ITERATIONS 1000000 +#define REPEATS 3 + +/** +* Prints the TAP version. +*/ +static void print_version( void ) { + printf( "TAP version 13\n" ); +} + +/** +* Prints the TAP summary. +* +* @param total total number of tests +* @param passing total number of passing tests +*/ +static void print_summary( int total, int passing ) { + printf( "#\n" ); + printf( "1..%d\n", total ); // TAP plan + printf( "# total %d\n", total ); + printf( "# pass %d\n", passing ); + printf( "#\n" ); + printf( "# ok\n" ); +} + +/** +* Prints benchmarks results. +* +* @param elapsed elapsed time in seconds +*/ +static void print_results( double elapsed ) { + double rate = (double)ITERATIONS / elapsed; + printf( " ---\n" ); + printf( " iterations: %d\n", ITERATIONS ); + printf( " elapsed: %0.9f\n", elapsed ); + printf( " rate: %0.9f\n", rate ); + printf( " ...\n" ); +} + +/** +* Returns a clock time. +* +* @return clock time +*/ +static double tic( void ) { + struct timeval now; + gettimeofday( &now, NULL ); + return (double)now.tv_sec + (double)now.tv_usec/1.0e6; +} + +/** +* Generates a random number on the interval [0,1). +* +* @return random number +*/ +static double rand_double( void ) { + int r = rand(); + return (double)r / ( (double)RAND_MAX + 1.0 ); +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark1( void ) { + double elapsed; + double t; + int i; + + struct BasePRNGObject *obj; + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + obj = stdlib_base_random_xorshift_allocate( i+1 ); + if ( obj == NULL || obj->prng->min != 1 ) { + printf( "unexpected result\n" ); + break; + } + if ( i < ITERATIONS-1 ) { + stdlib_base_random_xorshift_free( obj ); + } + } + elapsed = tic() - t; + + if ( obj == NULL || obj->prng->min != 1 ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + + return elapsed; +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark2( void ) { + double elapsed; + int8_t status; + uint64_t max; + uint64_t v; + double t; + int i; + + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + printf( "unable to allocate memory\n" ); + exit( 1 ); + } + max = obj->prng->max; + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + status = obj->prng->next( obj, &v ); + if ( status != 0 || v > max ) { + printf( "unexpected result\n" ); + break; + } + } + elapsed = tic() - t; + + if ( status != 0 || v > max ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + + return elapsed; +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark3( void ) { + double elapsed; + int8_t status; + double v; + double t; + int i; + + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + printf( "unable to allocate memory\n" ); + exit( 1 ); + } + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + status = obj->prng->normalized( obj, &v ); + if ( status != 0 || v != v ) { + printf( "unexpected result\n" ); + break; + } + } + elapsed = tic() - t; + + if ( status != 0 || v != v ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + + return elapsed; +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark4( void ) { + double elapsed; + int8_t status; + int32_t v; + double t; + int i; + + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + printf( "unable to allocate memory\n" ); + exit( 1 ); + } + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + // NOTE: this is likely to be optimized away by a modern compiler, making this benchmark meaningless. + status = stdlib_base_random_xorshift_seed( obj, &v ); + if ( status != 0 || v != 12345 ) { + printf( "unexpected result\n" ); + break; + } + } + elapsed = tic() - t; + + if ( status != 0 || v != 12345 ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + + return elapsed; +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark5( void ) { + double elapsed; + void *state; + double t; + int i; + + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + printf( "unable to allocate memory\n" ); + exit( 1 ); + } + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + state = stdlib_base_random_xorshift_state( obj ); + if ( state == NULL ) { + printf( "unexpected result\n" ); + break; + } + if ( i < ITERATIONS-1 ) { + free( state ); + } + } + elapsed = tic() - t; + + if ( state == NULL ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + free( state ); + + return elapsed; +} + +/** +* Runs a benchmark. +* +* @return elapsed time in seconds +*/ +static double benchmark6( void ) { + stdlib_base_random_xorshift_state_t *states[2]; + double elapsed; + int8_t status; + double t; + int i; + + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + printf( "unable to allocate memory\n" ); + exit( 1 ); + } + for ( i = 0; i < 2; i++ ) { + states[i] = (stdlib_base_random_xorshift_state_t *)malloc( sizeof( stdlib_base_random_xorshift_state_t ) ); + states[i]->seed = 12345; + states[i]->state = 12345; + } + + t = tic(); + for ( i = 0; i < ITERATIONS; i++ ) { + status = stdlib_base_random_xorshift_set( obj, (void *)states[i%2] ); + if ( status != 0 ) { + printf( "unexpected result\n" ); + break; + } + } + elapsed = tic() - t; + + if ( status != 0 ) { + printf( "unexpected result\n" ); + } + stdlib_base_random_xorshift_free( obj ); + for ( i = 0; i < 2; i++ ) { + free( states[i] ); + } + + return elapsed; +} + +/** +* Main execution sequence. +*/ +int main( void ) { + double elapsed; + int count; + int i; + + count = 0; + + // Use the current time to seed the random number generator: + srand( time( NULL ) ); + + print_version(); + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s::instantiation\n", NAME ); + elapsed = benchmark1(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s:next\n", NAME ); + elapsed = benchmark2(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s:normalized\n", NAME ); + elapsed = benchmark3(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s::get:seed\n", NAME ); + elapsed = benchmark4(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s::get:state\n", NAME ); + elapsed = benchmark5(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + for ( i = 0; i < REPEATS; i++ ) { + count += 1; + printf( "# c::%s::set:state\n", NAME ); + elapsed = benchmark6(); + print_results( elapsed ); + printf( "ok %d benchmark finished\n", count ); + } + print_summary( count, count ); +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/docs/repl.txt b/lib/node_modules/@stdlib/random/base/xorshift/docs/repl.txt new file mode 100644 index 000000000000..d05be135ffa0 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/docs/repl.txt @@ -0,0 +1,188 @@ + +{{alias}}() + Returns a pseudorandom integer on the interval `[1, 2147483646]`. + + This pseudorandom number generator (PRNG) is a linear congruential + pseudorandom number generator (LCG) based on Park and Miller. + + The generator has a period of approximately `2.1e9`. + + An LCG is fast and uses little memory. On the other hand, because the + generator is a simple LCG, the generator has recognized shortcomings. By + today's PRNG standards, the generator's period is relatively short. More + importantly, the "randomness quality" of the generator's output is lacking. + These defects make the generator unsuitable, for example, in Monte Carlo + simulations and in cryptographic applications. + + Returns + ------- + r: integer + Pseudorandom number. + + Examples + -------- + > var r = {{alias}}(); + + +{{alias}}.normalized() + Returns a pseudorandom number on the interval `[0,1)`. + + Returns + ------- + r: number + Pseudorandom number. + + Examples + -------- + > var r = {{alias}}.normalized(); + + +{{alias}}.factory( [options] ) + Returns a linear congruential pseudorandom number generator (LCG). + + Parameters + ---------- + options: Object (optional) + Options. + + options.seed: integer|ArrayLikeObject (optional) + Pseudorandom number generator seed. The seed may be either a positive + signed 32-bit integer on the interval `[1, 2147483646]` or, for + arbitrary length seeds, an array-like object containing signed 32-bit + integers. + + options.state: Int32Array (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 + ------- + rand: Function + Pseudorandom number generator (PRNG). + + Examples + -------- + // Basic usage: + > var rand = {{alias}}.factory(); + > r = rand(); + > r = rand(); + + // Provide a seed: + > rand = {{alias}}.factory( { 'seed': 1234 } ); + > r = rand() + 20739838 + + +{{alias}}.NAME + Generator name. + + Examples + -------- + > var str = {{alias}}.NAME + 'xorshift' + + +{{alias}}.MIN + Minimum possible value. + + Examples + -------- + > var v = {{alias}}.MIN + 1 + + +{{alias}}.MAX + Maximum possible value. + + Examples + -------- + > var v = {{alias}}.MAX + 2147483646 + + +{{alias}}.seed + Pseudorandom number generator seed. + + Examples + -------- + > var seed = {{alias}}.seed; + + +{{alias}}.seedLength + Length of generator seed. + + Examples + -------- + > var len = {{alias}}.seedLength; + + +{{alias}}.state + Generator state. + + Examples + -------- + > var r = {{alias}}() + + > r = {{alias}}() + + > r = {{alias}}() + + + // Get the current state: + > var state = {{alias}}.state + + + > r = {{alias}}() + + > r = {{alias}}() + + + // Set the state: + > {{alias}}.state = state; + + // Replay the last two pseudorandom numbers: + > r = {{alias}}() + + > r = {{alias}}() + + + +{{alias}}.stateLength + Length of generator state. + + Examples + -------- + > var len = {{alias}}.stateLength; + + +{{alias}}.byteLength + Size (in bytes) of generator state. + + Examples + -------- + > var sz = {{alias}}.byteLength; + + +{{alias}}.toJSON() + Serializes the pseudorandom number generator as a JSON object. + + Returns + ------- + out: Object + JSON representation. + + Examples + -------- + > var o = {{alias}}.toJSON() + { 'type': 'PRNG', 'name': '...', 'state': {...}, 'params': [] } + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts new file mode 100644 index 000000000000..42735e2bff6b --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts @@ -0,0 +1,197 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2019 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 + +/// + +import * as random from '@stdlib/types/random'; + +/** +* Interface defining `factory` options. +*/ +interface Options { + /** + * Pseudorandom number generator seed. + */ + seed?: random.PRNGSeedMINSTD; + + /** + * Pseudorandom number generator state. + */ + state?: random.PRNGStateMINSTD; + + /** + * 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; + + /** + * Minimum possible value. + */ + readonly MIN: number; + + /** + * Maximum possible value. + */ + readonly MAX: number; + + /** + * PRNG seed. + */ + readonly seed: random.PRNGSeedMINSTD; + + /** + * PRNG seed length. + */ + readonly seedLength: number; + + /** + * PRNG state. + */ + state: random.PRNGStateMINSTD; + + /** + * PRNG state length. + */ + readonly stateLength: number; + + /** + * PRNG state size (in bytes). + */ + readonly byteLength: number; + + /** + * Serializes the pseudorandom number generator as a JSON object. + * + * @returns JSON representation + */ + toJSON(): string; +} + +/** +* Interface for generating pseudorandom integers on the interval `[1, 2147483646]`. +*/ +interface NullaryFunction extends PRNG { + /** + * Returns a pseudorandom integer on the interval `[1, 2147483646]`. + * + * @returns pseudorandom number + */ + (): number; +} + +/** +* Interface for generating pseudorandom integers on the interval `[1, 2147483646]`. +*/ +interface Random extends PRNG { + /** + * Returns a pseudorandom integer on the interval `[1, 2147483646]`. + * + * ## Notes + * + * - This pseudorandom number generator (PRNG) is a linear congruential pseudorandom number generator (LCG) based on Park and Miller. + * - The generator has a period of approximately `2.1e9`. + * - An LCG is fast and uses little memory. On the other hand, because the generator is a simple LCG, the generator has recognized shortcomings. By today's PRNG standards, the generator's period is relatively short. More importantly, the "randomness quality" of the generator's output is lacking. These defects make the generator unsuitable, for example, in Monte Carlo simulations and in cryptographic applications. + * + * @returns pseudorandom number + * + * @example + * var v = xorshift(); + * // returns + */ + (): number; + + /** + * Returns a pseudorandom number on the interval `[0,1)`. + * + * @returns pseudorandom number + * + * @example + * var r = xorshift.normalized(); + * // returns + */ + normalized(): number; + + /** + * Returns a linear congruential pseudorandom number generator (LCG). + * + * @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 rand = xorshift.factory(); + * var v = rand(); + * // returns + * + * @example + * var rand = xorshift.factory({ + * 'seed': 12345 + * }); + * var v = rand(); + * // returns + */ + factory( options?: Options ): NullaryFunction; +} + +/** +* Returns a pseudorandom integer on the interval `[1, 2147483646]`. +* +* ## Notes +* +* - This pseudorandom number generator (PRNG) is a linear congruential pseudorandom number generator (LCG) based on Park and Miller. +* - The generator has a period of approximately `2.1e9`. +* - An LCG is fast and uses little memory. On the other hand, because the generator is a simple LCG, the generator has recognized shortcomings. By today's PRNG standards, the generator's period is relatively short. More importantly, the "randomness quality" of the generator's output is lacking. These defects make the generator unsuitable, for example, in Monte Carlo simulations and in cryptographic applications. +* +* @returns pseudorandom number +* +* @example +* var v = xorshift(); +* // returns +* +* @example +* var v = xorshift.normalized(); +* // returns +* +* @example +* var rand = xorshift.factory({ +* 'seed': 12345 +* }); +* var v = rand(); +* // returns +*/ +declare var xorshift: Random; + + +// EXPORTS // + +export = xorshift; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/docs/types/test.ts b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/test.ts new file mode 100644 index 000000000000..c499798f62d7 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/test.ts @@ -0,0 +1,106 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2019 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 xorshift = require( './index' ); + + +// TESTS // + +// The function returns a number... +{ + xorshift(); // $ExpectType number +} + +// The compiler throws an error if the function is provided any arguments... +{ + xorshift( true ); // $ExpectError + xorshift( 2, 3 ); // $ExpectError +} + +// Attached to main export is a `normalized` method which returns a number... +{ + xorshift.normalized(); // $ExpectType number +} + +// The compiler throws an error if the `normalized` method is provided any number of arguments... +{ + xorshift.normalized( true ); // $ExpectError + xorshift.normalized( 123 ); // $ExpectError + xorshift.normalized( 'abc' ); // $ExpectError +} + +// Attached to main export is a `factory` method which returns a function... +{ + xorshift.factory(); // $ExpectType NullaryFunction + xorshift.factory( { 'copy': false } ); // $ExpectType NullaryFunction +} + +// The `factory` method returns a function which returns a number... +{ + const fcn = xorshift.factory(); + fcn(); // $ExpectType number +} + +// The compiler throws an error if the function returned by the `factory` method is provided any number of arguments... +{ + const fcn = xorshift.factory(); + fcn( 1 ); // $ExpectError + fcn( 2, 1 ); // $ExpectError + fcn( 2, 1, 1 ); // $ExpectError +} + +// The compiler throws an error if the `factory` method is provided an options argument which is not an object... +{ + xorshift.factory( null ); // $ExpectError +} + +// The compiler throws an error if the `factory` method is provided a `seed` option which is not a valid seed... +{ + xorshift.factory( { 'seed': true } ); // $ExpectError + xorshift.factory( { 'seed': 'abc' } ); // $ExpectError + xorshift.factory( { 'seed': null } ); // $ExpectError + xorshift.factory( { 'seed': [ 'a' ] } ); // $ExpectError + xorshift.factory( { 'seed': {} } ); // $ExpectError + xorshift.factory( { 'seed': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` method is provided a `state` option which is not a valid state... +{ + xorshift.factory( { 'state': 123 } ); // $ExpectError + xorshift.factory( { 'state': 'abc' } ); // $ExpectError + xorshift.factory( { 'state': null } ); // $ExpectError + xorshift.factory( { 'state': [] } ); // $ExpectError + xorshift.factory( { 'state': {} } ); // $ExpectError + xorshift.factory( { 'state': true } ); // $ExpectError + xorshift.factory( { 'state': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` method is provided a `copy` option which is not a boolean... +{ + xorshift.factory( { 'copy': 123 } ); // $ExpectError + xorshift.factory( { 'copy': 'abc' } ); // $ExpectError + xorshift.factory( { 'copy': null } ); // $ExpectError + xorshift.factory( { 'copy': [] } ); // $ExpectError + xorshift.factory( { 'copy': {} } ); // $ExpectError + xorshift.factory( { 'copy': ( x: number ): number => x } ); // $ExpectError +} + +// The compiler throws an error if the `factory` method is provided more than one argument... +{ + xorshift.factory( {}, 2 ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/examples/c/Makefile b/lib/node_modules/@stdlib/random/base/xorshift/examples/c/Makefile new file mode 100644 index 000000000000..95c166477a67 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/examples/c/Makefile @@ -0,0 +1,146 @@ +#/ +# @license Apache-2.0 +# +# 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. +# 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. +#/ + +# VARIABLES # + +ifndef VERBOSE + QUIET := @ +else + QUIET := +endif + +# Determine the OS ([1][1], [2][2]). +# +# [1]: https://en.wikipedia.org/wiki/Uname#Examples +# [2]: http://stackoverflow.com/a/27776822/2225624 +OS ?= $(shell uname) +ifneq (, $(findstring MINGW,$(OS))) + OS := WINNT +else +ifneq (, $(findstring MSYS,$(OS))) + OS := WINNT +else +ifneq (, $(findstring CYGWIN,$(OS))) + OS := WINNT +else +ifneq (, $(findstring Windows_NT,$(OS))) + OS := WINNT +endif +endif +endif +endif + +# Define the program used for compiling C source files: +ifdef C_COMPILER + CC := $(C_COMPILER) +else + CC := gcc +endif + +# Define the command-line options when compiling C files: +CFLAGS ?= \ + -std=c99 \ + -O3 \ + -Wall \ + -pedantic + +# Determine whether to generate position independent code ([1][1], [2][2]). +# +# [1]: https://gcc.gnu.org/onlinedocs/gcc/Code-Gen-Options.html#Code-Gen-Options +# [2]: http://stackoverflow.com/questions/5311515/gcc-fpic-option +ifeq ($(OS), WINNT) + fPIC ?= +else + fPIC ?= -fPIC +endif + +# List of includes (e.g., `-I /foo/bar -I /beep/boop/include`): +INCLUDE ?= + +# List of source files: +SOURCE_FILES ?= + +# List of libraries (e.g., `-lopenblas -lpthread`): +LIBRARIES ?= + +# List of library paths (e.g., `-L /foo/bar -L /beep/boop`): +LIBPATH ?= + +# List of C targets: +c_targets := example.out + + +# RULES # + +#/ +# Compiles source files. +# +# @param {string} [C_COMPILER] - C compiler (e.g., `gcc`) +# @param {string} [CFLAGS] - C compiler options +# @param {(string|void)} [fPIC] - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} [INCLUDE] - list of includes (e.g., `-I /foo/bar -I /beep/boop/include`) +# @param {string} [SOURCE_FILES] - list of source files +# @param {string} [LIBPATH] - list of library paths (e.g., `-L /foo/bar -L /beep/boop`) +# @param {string} [LIBRARIES] - list of libraries (e.g., `-lopenblas -lpthread`) +# +# @example +# make +# +# @example +# make all +#/ +all: $(c_targets) + +.PHONY: all + +#/ +# Compiles C source files. +# +# @private +# @param {string} CC - C compiler (e.g., `gcc`) +# @param {string} CFLAGS - C compiler options +# @param {(string|void)} fPIC - compiler flag determining whether to generate position independent code (e.g., `-fPIC`) +# @param {string} INCLUDE - list of includes (e.g., `-I /foo/bar`) +# @param {string} SOURCE_FILES - list of source files +# @param {string} LIBPATH - list of library paths (e.g., `-L /foo/bar`) +# @param {string} LIBRARIES - list of libraries (e.g., `-lopenblas`) +#/ +$(c_targets): %.out: %.c + $(QUIET) $(CC) $(CFLAGS) $(fPIC) $(INCLUDE) -o $@ $(SOURCE_FILES) $< $(LIBPATH) -lm $(LIBRARIES) + +#/ +# Runs compiled examples. +# +# @example +# make run +#/ +run: $(c_targets) + $(QUIET) ./$< + +.PHONY: run + +#/ +# Removes generated files. +# +# @example +# make clean +#/ +clean: + $(QUIET) -rm -f *.o *.out + +.PHONY: clean diff --git a/lib/node_modules/@stdlib/random/base/xorshift/examples/c/example.c b/lib/node_modules/@stdlib/random/base/xorshift/examples/c/example.c new file mode 100644 index 000000000000..704e2075e1f1 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/examples/c/example.c @@ -0,0 +1,75 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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. +*/ + +#include "stdlib/random/base/xorshift.h" +#include "stdlib/random/base/shared.h" +#include +#include +#include + +int main( void ) { + int8_t status; + int32_t seed; + uint64_t v; + int32_t i; + double d; + + // Create a PRNG... + struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); + if ( obj == NULL ) { + fprintf( stderr, "Error allocating memory.\n" ); + exit( 1 ); + } + + status = stdlib_base_random_xorshift_seed( obj, &seed ); + if ( status != 0 ) { + printf( "Unable to retrieve the PRNG seed.\n" ); + exit( 1 ); + } + printf( "seed = %d\n", seed ); + + printf( "name = %s\n", obj->prng->name ); + printf( "min = %"PRIu64"\n", obj->prng->min ); + printf( "max = %"PRIu64"\n", obj->prng->max ); + + printf( "\nPseudorandom integers...\n" ); + for ( i = 0; i < 10; i++ ) { + status = obj->prng->next( obj, &v ); + if ( status != 0 ) { + printf( "Unexpected result.\n" ); + exit( 1 ); + } + printf( "%"PRIu64"\n", v ); + } + + printf( "\n" ); + printf( "min (normalized) = %0.16f\n", obj->prng->normalized_min ); + printf( "max (normalized) = %0.16f\n", obj->prng->normalized_max ); + + printf( "\nPseudorandom doubles...\n" ); + for ( i = 0; i < 10; i++ ) { + status = obj->prng->normalized( obj, &d ); + if ( status != 0 ) { + printf( "Unexpected result.\n" ); + exit( 1 ); + } + printf( "%0.16f\n", d ); + } + + stdlib_base_random_xorshift_free( obj ); +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/examples/index.js b/lib/node_modules/@stdlib/random/base/xorshift/examples/index.js new file mode 100644 index 000000000000..5b46575cec0f --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/examples/index.js @@ -0,0 +1,47 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 xorshift = require( './../lib' ); + +// Generate pseudorandom numbers... +console.log( '\nseed: %d', xorshift.seed[ 0 ] ); +var i; +for ( i = 0; i < 100; i++ ) { + console.log( xorshift() ); +} + +// Create a new pseudorandom number generator... +var seed = 1234; +var rand = xorshift.factory({ + 'seed': seed +}); +console.log( '\nseed: %d', seed ); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} + +// Create another pseudorandom number generator using a previous seed... +rand = xorshift.factory({ + 'seed': xorshift.seed +}); +console.log( '\nseed: %d', rand.seed[ 0 ] ); +for ( i = 0; i < 100; i++ ) { + console.log( rand() ); +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h b/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h new file mode 100644 index 000000000000..b6a1284db22a --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h @@ -0,0 +1,69 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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. +*/ + +#ifndef STDLIB_RANDOM_BASE_MINSTD_H +#define STDLIB_RANDOM_BASE_MINSTD_H + +#include "stdlib/random/base/shared.h" +#include + +/* +* If C++, prevent name mangling so that the compiler emits a binary file having undecorated names, thus mirroring the behavior of a C compiler. +*/ +#ifdef __cplusplus +extern "C" { +#endif + +/** +* Declare an opaque type definition for the PRNG state. +*/ +typedef struct { + uint32_t seed; + uint32_t state; +} stdlib_base_random_xorshift_state_t; + +/** +* Returns a pointer to a dynamically allocated PRNG. +*/ +struct BasePRNGObject * stdlib_base_random_xorshift_allocate( const int32_t seed ); + +/** +* Frees a PRNG's allocated memory. +*/ +void stdlib_base_random_xorshift_free( struct BasePRNGObject *obj ); + +/** +* Returns a PRNG seed. +*/ +int8_t stdlib_base_random_xorshift_seed( const struct BasePRNGObject *obj, int32_t *out ); + +/** +* Returns a copy of the current PRNG state. +*/ +void * stdlib_base_random_xorshift_state( const struct BasePRNGObject *obj ); + +/** +* Sets the PRNG state. +*/ +int8_t stdlib_base_random_xorshift_set( struct BasePRNGObject *obj, const void *state ); + +#ifdef __cplusplus +} +#endif + +#endif // !STDLIB_RANDOM_BASE_MINSTD_H diff --git a/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js b/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js new file mode 100644 index 000000000000..761bf9db66bb --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js @@ -0,0 +1,416 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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. +*/ + +/* eslint-disable max-len */ + +'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 isCollection = require( '@stdlib/assert/is-collection' ); +var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive; +var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var format = require( '@stdlib/string/format' ); +var INT32_MAX = require( '@stdlib/constants/int32/max' ); +var Int32Array = require( '@stdlib/array/int32' ); +var gcopy = require( '@stdlib/blas/base/gcopy' ); +var typedarray2json = require( '@stdlib/array/to-json' ); +var randint32 = require( './rand_int32.js' ); + + +// VARIABLES // + +var NORMALIZATION_CONSTANT = (INT32_MAX - 1)|0; // asm type annotation +var MAX_SEED = (INT32_MAX - 1)|0; // asm type annotation +var A = 16807|0; // asm type annotation + +// Define the state array schema version: +var STATE_ARRAY_VERSION = 1; // NOTE: anytime the state array schema changes, this value should be incremented!!! + +// Define the number of sections in the state array: +var NUM_STATE_SECTIONS = 2; // state, seed + +// Define the index offset of the "state" section in the state array: +var STATE_SECTION_OFFSET = 2; // | version | num_sections | state_length | ...state | seed_length | ...seed | + +// Define the index offset of the seed section in the state array: +var SEED_SECTION_OFFSET = 4; // | version | num_sections | state_length | ...state | seed_length | ...seed | + +// Define the length of the "fixed" length portion of the state array: +var STATE_FIXED_LENGTH = 5; // 1 (version) + 1 (num_sections) + 1 (state_length) + 1 (state) + 1 (seed_length) + + +// FUNCTIONS // + +/** +* Verifies state array integrity. +* +* @private +* @param {Int32Array} state - state array +* @param {boolean} FLG - flag indicating whether the state array was provided as an option (true) or an argument (false) +* @returns {(Error|null)} an error or `null` +*/ +function verifyState( state, FLG ) { + var s1; + if ( FLG ) { + s1 = 'option'; + } else { + s1 = 'argument'; + } + // The state array must have a minimum length... + if ( state.length < STATE_FIXED_LENGTH+1 ) { + return new RangeError( format( 'invalid %s. State array has insufficient length.', s1 ) ); + } + // The first element of the state array must equal the supported state array schema version... + if ( state[ 0 ] !== STATE_ARRAY_VERSION ) { + return new RangeError( format( 'invalid %s. State array has an incompatible schema version. Expected: `%s`. Actual: `%s`.', s1, STATE_ARRAY_VERSION, state[ 0 ] ) ); + } + // The second element of the state array must contain the number of sections... + if ( state[ 1 ] !== NUM_STATE_SECTIONS ) { + return new RangeError( format( 'invalid %s. State array has an incompatible number of sections. Expected: `%s`. Actual: `%s`.', s1, NUM_STATE_SECTIONS, state[ 1 ] ) ); + } + // The length of the "state" section must equal `1`... + if ( state[ STATE_SECTION_OFFSET ] !== 1 ) { + return new RangeError( format( 'invalid %s. State array has an incompatible state length. Expected: `%u`. Actual: `%u`.', s1, 1, state[ STATE_SECTION_OFFSET ] ) ); + } + // The length of the "seed" section much match the empirical length... + if ( state[ SEED_SECTION_OFFSET ] !== state.length-STATE_FIXED_LENGTH ) { + return new RangeError( format( 'invalid %s. State array length is incompatible with seed section length. Expected: `%u`. Actual: `%u`.', s1, state.length-STATE_FIXED_LENGTH, state[ SEED_SECTION_OFFSET ] ) ); + } + return null; +} + + +// MAIN // + +/** +* Returns a linear congruential pseudorandom number generator (LCG) based on Park and Miller. +* +* @param {Options} [options] - options +* @param {PRNGSeedMINSTD} [options.seed] - pseudorandom number generator seed +* @param {PRNGStateMINSTD} [options.state] - pseudorandom number generator state +* @param {boolean} [options.copy=true] - boolean indicating whether to copy a provided pseudorandom number generator state +* @throws {TypeError} options argument must be an object +* @throws {TypeError} a seed must be either a positive integer less than the maximum signed 32-bit integer or an array-like object containing integers less than the maximum signed 32-bit integer +* @throws {RangeError} a numeric seed must be a positive integer less than the maximum signed 32-bit integer +* @throws {TypeError} state must be an `Int32Array` +* @throws {Error} must provide a valid state +* @throws {TypeError} `copy` option must be a boolean +* @returns {PRNG} LCG PRNG +* +* @example +* var xorshift = factory(); +* +* var v = xorshift(); +* // returns +* +* @example +* // Return a seeded LCG: +* var xorshift = factory({ +* 'seed': 1234 +* }); +* +* var v = xorshift(); +* // returns 20739838 +*/ +function factory( options ) { + var STATE; + var state; + var opts; + var seed; + var slen; + var err; + + opts = {}; + if ( arguments.length ) { + if ( !isObject( options ) ) { + throw new TypeError( format( 'invalid argument. Options argument must be an object. Value: `%s`.', options ) ); + } + if ( hasOwnProp( options, 'copy' ) ) { + opts.copy = options.copy; + if ( !isBoolean( options.copy ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be a boolean. Option: `%s`.', 'copy', options.copy ) ); + } + } + if ( hasOwnProp( options, 'state' ) ) { + state = options.state; + opts.state = true; + if ( !isInt32Array( state ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be an Int32Array. Option: `%s`.', 'state', state ) ); + } + err = verifyState( state, true ); + if ( err ) { + throw err; + } + if ( opts.copy === false ) { + STATE = state; + } else { + STATE = new Int32Array( state.length ); + gcopy( state.length, state, 1, STATE, 1 ); + } + // Create a state "view": + state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + + // Create a seed "view": + seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), state[ SEED_SECTION_OFFSET ] ); + } + // If provided a PRNG state, we ignore the `seed` option... + if ( seed === void 0 ) { + if ( hasOwnProp( options, 'seed' ) ) { + seed = options.seed; + opts.seed = true; + if ( isPositiveInteger( seed ) ) { + if ( seed > MAX_SEED ) { + throw new RangeError( format( 'invalid option. `%s` option must be a positive integer less than the maximum signed 32-bit integer. Option: `%u`.', 'seed', seed ) ); + } + seed |= 0; // asm type annotation + } else if ( isCollection( seed ) && seed.length > 0 ) { + slen = seed.length; + STATE = new Int32Array( STATE_FIXED_LENGTH+slen ); + + // Initialize sections: + STATE[ 0 ] = STATE_ARRAY_VERSION; + STATE[ 1 ] = NUM_STATE_SECTIONS; + STATE[ STATE_SECTION_OFFSET ] = 1; + STATE[ SEED_SECTION_OFFSET ] = slen; + + // Copy the provided seed array to prevent external mutation, as mutation would lead to an inability to reproduce PRNG values according to the PRNG's stated seed: + gcopy.ndarray( slen, seed, 1, 0, STATE, 1, SEED_SECTION_OFFSET+1 ); + + // Create a state "view": + state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + + // Create a seed "view": + seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), slen ); + + // Initialize the internal PRNG state: + state[ 0 ] = seed[ 0 ]; + } else { + throw new TypeError( format( 'invalid option. `%s` option must be either a positive integer less than the maximum signed 32-bit integer or an array-like object containing integer values less than the maximum signed 32-bit integer. Option: `%s`.', 'seed', seed ) ); + } + } else { + seed = randint32()|0; // asm type annotation + } + } + } else { + seed = randint32()|0; // asm type annotation + } + if ( state === void 0 ) { + STATE = new Int32Array( STATE_FIXED_LENGTH+1 ); + + // Initialize sections: + STATE[ 0 ] = STATE_ARRAY_VERSION; + STATE[ 1 ] = NUM_STATE_SECTIONS; + STATE[ STATE_SECTION_OFFSET ] = 1; + STATE[ SEED_SECTION_OFFSET ] = 1; + STATE[ SEED_SECTION_OFFSET+1 ] = seed; + + // Create a state "view": + state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + + // Create a seed "view": + seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + + // Initialize the internal PRNG state: + state[ 0 ] = seed[ 0 ]; + } + setReadOnly( xorshift, 'NAME', 'xorshift' ); + setReadOnlyAccessor( xorshift, 'seed', getSeed ); + setReadOnlyAccessor( xorshift, 'seedLength', getSeedLength ); + setReadWriteAccessor( xorshift, 'state', getState, setState ); + setReadOnlyAccessor( xorshift, 'stateLength', getStateLength ); + setReadOnlyAccessor( xorshift, 'byteLength', getStateSize ); + setReadOnly( xorshift, 'toJSON', toJSON ); + setReadOnly( xorshift, 'MIN', 1 ); + setReadOnly( xorshift, 'MAX', INT32_MAX-1 ); + setReadOnly( xorshift, 'normalized', normalized ); + + setReadOnly( normalized, 'NAME', xorshift.NAME ); + setReadOnlyAccessor( normalized, 'seed', getSeed ); + setReadOnlyAccessor( normalized, 'seedLength', getSeedLength ); + setReadWriteAccessor( normalized, 'state', getState, setState ); + setReadOnlyAccessor( normalized, 'stateLength', getStateLength ); + setReadOnlyAccessor( normalized, 'byteLength', getStateSize ); + setReadOnly( normalized, 'toJSON', toJSON ); + setReadOnly( normalized, 'MIN', (xorshift.MIN-1.0) / NORMALIZATION_CONSTANT ); + setReadOnly( normalized, 'MAX', (xorshift.MAX-1.0) / NORMALIZATION_CONSTANT ); + + return xorshift; + + /** + * Returns the PRNG seed. + * + * @private + * @returns {PRNGSeedMINSTD} seed + */ + function getSeed() { + var len = STATE[ SEED_SECTION_OFFSET ]; + return gcopy( len, seed, 1, new Int32Array( len ), 1 ); + } + + /** + * Returns the PRNG seed length. + * + * @private + * @returns {PositiveInteger} seed length + */ + function getSeedLength() { + return STATE[ SEED_SECTION_OFFSET ]; + } + + /** + * Returns the PRNG state length. + * + * @private + * @returns {PositiveInteger} state length + */ + function getStateLength() { + return STATE.length; + } + + /** + * Returns the PRNG state size (in bytes). + * + * @private + * @returns {PositiveInteger} state size (in bytes) + */ + function getStateSize() { + return STATE.byteLength; + } + + /** + * Returns the current PRNG state. + * + * ## Notes + * + * - The PRNG state array is comprised of a preamble followed by `2` sections: + * + * 0. preamble (version + number of sections) + * 1. internal PRNG state + * 2. PRNG seed + * + * - The first element of the PRNG state array preamble is the state array schema version. + * + * - The second element of the PRNG state array preamble is the number of state array sections (i.e., `2`). + * + * - The first element of each section following the preamble specifies the section length. The remaining section elements comprise the section contents. + * + * @private + * @returns {PRNGStateMINSTD} current state + */ + function getState() { + var len = STATE.length; + return gcopy( len, STATE, 1, new Int32Array( len ), 1 ); + } + + /** + * Sets the PRNG state. + * + * ## Notes + * + * - 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). + * + * @private + * @param {PRNGStateMINSTD} s - generator state + * @throws {TypeError} must provide an `Int32Array` + * @throws {Error} must provide a valid state + */ + function setState( s ) { + var err; + if ( !isInt32Array( s ) ) { + throw new TypeError( format( 'invalid argument. Must provide an Int32Array. Value: `%s`.', s ) ); + } + err = verifyState( s, false ); + if ( err ) { + throw err; + } + if ( opts.copy === false ) { + if ( opts.state && s.length === STATE.length ) { + gcopy( s.length, s, 1, STATE, 1 ); // update current shared state + } else { + STATE = s; // point to new shared state + opts.state = true; // setting this flag allows updating a shared state even if a state array was not provided at PRNG creation + } + } else { + // Check if we can reuse allocated memory... + if ( s.length !== STATE.length ) { + STATE = new Int32Array( s.length ); // reallocate + } + gcopy( s.length, s, 1, STATE, 1 ); + } + // Create a new state "view": + state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + + // Create a new seed "view": + seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), STATE[ SEED_SECTION_OFFSET ] ); + } + + /** + * Serializes the pseudorandom number generator as a JSON object. + * + * ## Notes + * + * - `JSON.stringify()` implicitly calls this method when stringifying a PRNG. + * + * @private + * @returns {Object} JSON representation + */ + function toJSON() { + var out = {}; + out.type = 'PRNG'; + out.name = xorshift.NAME; + out.state = typedarray2json( STATE ); + out.params = []; + return out; + } + + /** + * Generates a pseudorandom integer on the interval \\( [1,2^{31}-1) \\). + * + * @private + * @returns {integer32} pseudorandom integer + */ + function xorshift() { + var s = state[ 0 ]|0; // asm type annotation + s = ( (A*s)%INT32_MAX )|0; // asm type annotation + state[ 0 ] = s; + return s|0; // asm type annotation + } + + /** + * Generates a pseudorandom number on the interval \\( [0,1) \\). + * + * @private + * @returns {number} pseudorandom number + */ + function normalized() { + return (xorshift()-1) / NORMALIZATION_CONSTANT; + } +} + + +// EXPORTS // + +module.exports = factory; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/lib/index.js b/lib/node_modules/@stdlib/random/base/xorshift/lib/index.js new file mode 100644 index 000000000000..b01618d28920 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/lib/index.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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'; + +/** +* A linear congruential pseudorandom number generator (LCG) based on Park and Miller. +* +* @module @stdlib/random/base/xorshift +* +* @example +* var xorshift = require( '@stdlib/random/base/xorshift' ); +* +* var v = xorshift(); +* // returns +* +* @example +* var factory = require( '@stdlib/random/base/xorshift' ).factory; +* +* var xorshift = factory({ +* 'seed': 1234 +* }); +* +* var v = xorshift(); +* // returns 20739838 +*/ + +// MODULES // + +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); +var main = require( './main.js' ); +var factory = require( './factory.js' ); + + +// MAIN // + +setReadOnly( main, 'factory', factory ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/lib/main.js b/lib/node_modules/@stdlib/random/base/xorshift/lib/main.js new file mode 100644 index 000000000000..fe9d77fee217 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/lib/main.js @@ -0,0 +1,102 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 factory = require( './factory.js' ); +var randint32 = require( './rand_int32.js' ); + + +// MAIN // + +/** +* Generates a pseudorandom integer on the interval \\( [1,2^{31}-1) \\). +* +* ## Method +* +* Linear congruential generators (LCGs) use the recurrence relation +* +* ```tex +* X_{n+1} = ( a \cdot X_n + c ) \operatorname{mod}(m) +* ``` +* +* where the modulus \\( m \\) is a prime number or power of a prime number and \\( a \\) is a primitive root modulo \\( m \\). +* +* +* +* For an LCG to be a Lehmer RNG, the seed \\( X_0 \\) must be coprime to \\( m \\). +* +* +* +* In this implementation, the constants \\( a \\), \\( c \\), and \\( m \\) have the values +* +* ```tex +* \begin{align*} +* a &= 7^5 = 16807 \\ +* c &= 0 \\ +* m &= 2^{31} - 1 = 2147483647 +* \end{align*} +* ``` +* +* +* +* The constant \\( m \\) is a Mersenne prime (modulo \\(31\\)). +* +* +* +* +* +* The constant \\( a \\) is a primitive root (modulo \\(31\\)). +* +* +* +* Accordingly, the maximum possible product is +* +* ```tex +* 16807 \cdot (m - 1) \approx 2^{46} +* ``` +* +* The values for \\( a \\), \\( c \\), and \\( m \\) are taken from Park and Miller, "Random Number Generators: Good Ones Are Hard To Find". Park's and Miller's article is also the basis for a recipe in the second edition of _Numerical Recipes in C_. +* +* ## Notes +* +* - The generator has a period of approximately \\(2.1\mbox{e}9\\) (see [Numerical Recipes in C, 2nd Edition](#references), p. 279). +* +* ## References +* +* - Park, S. K., and K. W. Miller. 1988. "Random Number Generators: Good Ones Are Hard to Find." _Communications of the ACM_ 31 (10). New York, NY, USA: ACM: 1192–1201. doi:[10.1145/63039.63042](http://dx.doi.org/10.1145/63039.63042). +* - Press, William H., Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling. 1992. _Numerical Recipes in C: The Art of Scientific Computing, Second Edition_. Cambridge University Press. +* +* @function xorshift +* @type {PRNG} +* @returns {PositiveInteger} pseudorandom integer +* +* @example +* var v = xorshift(); +* // returns +*/ +var xorshift = factory({ + 'seed': randint32() +}); + + +// EXPORTS // + +module.exports = xorshift; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/lib/rand_int32.js b/lib/node_modules/@stdlib/random/base/xorshift/lib/rand_int32.js new file mode 100644 index 000000000000..925d4d6e299d --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/lib/rand_int32.js @@ -0,0 +1,52 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 INT32_MAX = require( '@stdlib/constants/int32/max' ); +var floor = require( '@stdlib/math/base/special/floor' ); + + +// VARIABLES // + +var MAX = INT32_MAX - 1; + + +// MAIN // + +/** +* Returns a pseudorandom integer on the interval \\([1, 2^{31}-1)\\). +* +* @private +* @returns {PositiveInteger} pseudorandom integer +* +* @example +* var v = randint32(); +* // returns +*/ +function randint32() { + var v = floor( 1.0 + (MAX*Math.random()) ); // eslint-disable-line stdlib/no-builtin-math + return v|0; // asm type annotation +} + + +// EXPORTS // + +module.exports = randint32; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/manifest.json b/lib/node_modules/@stdlib/random/base/xorshift/manifest.json new file mode 100644 index 000000000000..5d00c6c96783 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/manifest.json @@ -0,0 +1,40 @@ +{ + "options": {}, + "fields": [ + { + "field": "src", + "resolve": true, + "relative": true + }, + { + "field": "include", + "resolve": true, + "relative": true + }, + { + "field": "libraries", + "resolve": false, + "relative": false + }, + { + "field": "libpath", + "resolve": true, + "relative": false + } + ], + "confs": [ + { + "src": [ + "./src/main.c" + ], + "include": [ + "./include" + ], + "libraries": [], + "libpath": [], + "dependencies": [ + "@stdlib/random/base/shared" + ] + } + ] +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/package.json b/lib/node_modules/@stdlib/random/base/xorshift/package.json new file mode 100644 index 000000000000..e02b8bdc840a --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/package.json @@ -0,0 +1,77 @@ +{ + "name": "@stdlib/random/base/xorshift", + "version": "0.0.0", + "description": "A linear congruential pseudorandom number generator (LCG) based on Park and Miller.", + "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", + "directories": { + "benchmark": "./benchmark", + "doc": "./docs", + "example": "./examples", + "include": "./include", + "lib": "./lib", + "src": "./src", + "test": "./test" + }, + "types": "./docs/types", + "scripts": {}, + "homepage": "https://github.com/stdlib-js/stdlib", + "repository": { + "type": "git", + "url": "git://github.com/stdlib-js/stdlib.git" + }, + "bugs": { + "url": "https://github.com/stdlib-js/stdlib/issues" + }, + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=0.10.0", + "npm": ">2.7.0" + }, + "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", + "lcg", + "xorshift", + "lehmer", + "park", + "miller", + "park-miller", + "seed", + "seedable" + ] +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/src/main.c b/lib/node_modules/@stdlib/random/base/xorshift/src/main.c new file mode 100644 index 000000000000..ff3075c1050b --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/src/main.c @@ -0,0 +1,430 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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. +*/ + +#include "stdlib/random/base/xorshift.h" +#include "stdlib/random/base/shared.h" +#include +#include +#include + +// Forward declarations: +static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out ); +static inline int8_t normalized( struct BasePRNGObject *obj, double *out ); +static inline void xorshift_free( struct BasePRNGObject *obj ); + +// Define the LCG multiplier: +static const uint32_t A = 16807; + +// Define the maximum signed 32-bit integer: 2147483647 => 0x7fffffff => 01111111111111111111111111111111 +static const uint32_t MAX_INT32 = 0x7fffffff; + +// Define the normalization constant: +static const double NORMALIZATION_CONSTANT = 2147483646.0; // MAX_INT32 - 1 + +/** +* MINSTD PRNG. +* +*/ +static const struct BasePRNG xorshift_prng = { + "xorshift", // name + (uint64_t)1, // min + (uint64_t)MAX_INT32-1, // max: (2^{31}-1) - 1 + 0.0, // min (normalized) + (MAX_INT32-2) / NORMALIZATION_CONSTANT, // max (normalized): (MAX-1)/MAX + sizeof( stdlib_base_random_xorshift_state_t ), // state_size + &next, // next() + &normalized, // normalized() + &xorshift_free // free() +}; + +/** +* Returns a pseudorandom integer. +* +* ## Notes +* +* - The function returns `-1` if unable to generate a pseudorandom integer and `0` otherwise. +* +* @param obj PRNG object +* @param out output address +* @return status code +*/ +static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out ) { + if ( obj == NULL || obj->prng != &xorshift_prng ) { + return -1; + } + // Retrieve the state object: + stdlib_base_random_xorshift_state_t *so = (stdlib_base_random_xorshift_state_t *)( obj->state ); + + // Retrieve the current state: + uint32_t state = so->state; + + // Explicitly cast to 64-bit to handle integer overflow: + state = (A*(uint64_t)state) % MAX_INT32; + + // Update the PRNG state: + so->state = state; + + // Set the output value: + *out = (uint64_t)state; + + return 0; +} + +/** +* Returns a pseudorandom double-precision floating-point number on the interval `[0,1)`. +* +* ## Notes +* +* - The function returns `-1` if unable to generate a pseudorandom number and `0` otherwise. +* +* @param obj PRNG object +* @param out output address +* @return status code +*/ +static inline int8_t normalized( struct BasePRNGObject *obj, double *out ) { + uint64_t state; + int8_t status = next( obj, &state ); + if ( status != 0 ) { + return -1; + } + // Note: casting `state` to a double here is fine, as `state` will never exceed the maximum "safe" double-precision floating-point number: + *out = ((double)state-1.0) / NORMALIZATION_CONSTANT; + + return 0; +} + +/** +* Frees a PRNG's allocated memory. +* +* @param obj PRNG object +*/ +static inline void xorshift_free( struct BasePRNGObject *obj ) { + if ( obj == NULL || obj->prng != &xorshift_prng ) { + return; + } + free( obj->state ); + free( obj ); +} + +/** +* Returns a pointer to a dynamically allocated PRNG. +* +* ## Notes +* +* - The user is responsible for freeing the allocated memory. +* - A provided `seed` is mapped to the interval `[1,2147483646]`. +* +* @param seed PRNG seed +* @return pointer to a dynamically allocated PRNG or, if unable to allocate memory, a null pointer +* +* @example +* #include "stdlib/random/base/xorshift.h" +* #include "stdlib/random/base/shared.h" +* #include +* #include +* #include +* +* // Create a PRNG: +* struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); +* if ( obj == NULL ) { +* fprintf( stderr, "Error allocating memory.\n" ); +* exit( 1 ); +* } +* +* uint64_t r; +* int8_t status = obj->prng->next( obj, &r ); +* if ( status != 0 ) { +* fprintf( stderr, "Unexpected result.\n" ); +* exit( 1 ); +* } +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* // Free allocated memory: +* stdlib_base_random_xorshift_free( obj ); +*/ +struct BasePRNGObject * stdlib_base_random_xorshift_allocate( const int32_t seed ) { + uint32_t iseed; + + struct BasePRNGObject *obj = malloc( sizeof( struct BasePRNGObject ) ); + if ( obj == NULL ) { + return NULL; + } + stdlib_base_random_xorshift_state_t *state = malloc( sizeof( stdlib_base_random_xorshift_state_t ) ); + if ( state == NULL ) { + free( obj ); // prevent memory leaks + return NULL; + } + // Ensure that the provided seed is within allowed bounds... + if ( seed == 0 ) { + iseed = 1; + } else if ( seed == MAX_INT32 ) { + iseed = MAX_INT32 - 1; + } else if ( seed < 0 ) { + iseed = -seed; + } else { + iseed = seed; + } + state->seed = (uint32_t)iseed; + state->state = (uint32_t)iseed; + + obj->prng = &xorshift_prng; + obj->state = state; + + return obj; +} + +/** +* Frees a PRNG's allocated memory. +* +* @param obj PRNG object +* +* @example +* #include "stdlib/random/base/xorshift.h" +* #include "stdlib/random/base/shared.h" +* #include +* #include +* #include +* +* // Create a PRNG: +* struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); +* if ( obj == NULL ) { +* fprintf( stderr, "Error allocating memory.\n" ); +* exit( 1 ); +* } +* +* uint64_t r; +* int8_t status = obj->prng->next( obj, &r ); +* if ( status != 0 ) { +* fprintf( stderr, "Unexpected result.\n" ); +* exit( 1 ); +* } +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* // Free allocated memory: +* stdlib_base_random_xorshift_free( obj ); +*/ +void stdlib_base_random_xorshift_free( struct BasePRNGObject *obj ) { + if ( obj == NULL || obj->prng != &xorshift_prng ) { + return; + } + obj->prng->free( obj ); +} + +/** +* Returns a PRNG seed. +* +* ## Notes +* +* - The function returns `-1` if unable to resolve a PRNG seed and `0` otherwise. +* +* @param obj PRNG object +* @param out output address +* @return status code +* +* @example +* #include "stdlib/random/base/xorshift.h" +* #include "stdlib/random/base/shared.h" +* #include +* #include +* #include +* +* // Create a PRNG: +* struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); +* if ( obj == NULL ) { +* fprintf( stderr, "Error allocating memory.\n" ); +* exit( 1 ); +* } +* +* int32_t seed; +* int8_t status = stdlib_base_random_xorshift_seed( obj, &seed ); +* if ( status != 0 ) { +* fprintf( stderr, "Error encountered when attempting to retrieve the PRNG seed.\n" ); +* exit( 1 ); +* } +* +* // Use the seed to, e.g., create another PRNG which will generate the same sequence... +* +* // Free allocated memory: +* stdlib_base_random_xorshift_free( obj ); +*/ +int8_t stdlib_base_random_xorshift_seed( const struct BasePRNGObject *obj, int32_t *out ) { + if ( obj == NULL || obj->prng != &xorshift_prng ) { + return -1; + } + // Retrieve the MINSTD state object: + const stdlib_base_random_xorshift_state_t *state = (stdlib_base_random_xorshift_state_t *)( obj->state ); + + // Set the output value: + *out = (int32_t)( state->seed ); + + return 0; +} + +/** +* Returns a **copy** of the current PRNG state. +* +* ## Notes +* +* - The user is responsible for freeing the allocated memory. +* +* @param obj PRNG object +* @return pointer to a copy of the PRNG's internal state or, if unable to allocate memory, a null pointer +* +* @example +* #include "stdlib/random/base/xorshift.h" +* #include "stdlib/random/base/shared.h" +* #include +* #include +* #include +* +* // Create a PRNG: +* struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); +* if ( obj == NULL ) { +* fprintf( stderr, "Error allocating memory.\n" ); +* exit( 1 ); +* } +* +* void *state = stdlib_base_random_xorshift_state( obj ); +* if ( state == NULL ) { +* fprintf( stderr, "Unable to retrieve PRNG state.\n" ); +* exit( 1 ); +* } +* +* // Use the captured state to, e.g., sync another PRNG or to reset a PRNG to a particular state in order to "replay" generated values at a later point in time... +* +* // Free allocated memory: +* stdlib_base_random_xorshift_free( obj ); +* free( state ); +*/ +void * stdlib_base_random_xorshift_state( const struct BasePRNGObject *obj ) { + if ( obj == NULL || obj->prng != &xorshift_prng ) { + return NULL; + } + void *state = malloc( obj->prng->state_size ); + if ( state == NULL ) { + return NULL; + } + memcpy( state, obj->state, obj->prng->state_size ); + return state; +} + +/** +* Sets the PRNG state. +* +* ## Notes +* +* - The function returns `-1` if unable to set a PRNG state and `0` otherwise. +* +* @param obj PRNG object +* @param state state +* @return status code +* +* @example +* #include "stdlib/random/base/xorshift.h" +* #include "stdlib/random/base/shared.h" +* #include +* #include +* #include +* +* // Create a PRNG: +* struct BasePRNGObject *obj = stdlib_base_random_xorshift_allocate( 12345 ); +* if ( obj == NULL ) { +* fprintf( stderr, "Error allocating memory.\n" ); +* exit( 1 ); +* } +* +* uint64_t r; +* int8_t status = obj->prng->next( obj, &r ); +* if ( status != 0 ) { +* fprintf( stderr, "Unexpected result.\n" ); +* exit( 1 ); +* } +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* // Retrieve the current PRNG state... +* void *state = stdlib_base_random_xorshift_state( obj ); +* if ( state == NULL ) { +* fprintf( stderr, "Error encountered when attempting to retrieve PRNG state.\n" ); +* exit( 1 ); +* } +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* // Reset the PRNG to a previous state... +* status = stdlib_base_random_xorshift_set( obj, state ); +* if ( status != 0 ) { +* fprintf( stderr, "Error encountered when attempting to set PRNG state.\n" ); +* exit( 1 ); +* } +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* status = obj->prng->next( obj, &r ); +* +* // ... +* +* // Free allocated memory: +* stdlib_base_random_xorshift_free( obj ); +* free( state ); +*/ +int8_t stdlib_base_random_xorshift_set( struct BasePRNGObject *obj, const void *state ) { + if ( obj == NULL || state == NULL || obj->prng != &xorshift_prng ) { + return -1; + } + memcpy( obj->state, state, obj->prng->state_size ); + return 0; +} diff --git a/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js b/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js new file mode 100644 index 000000000000..740631687e30 --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js @@ -0,0 +1,1634 @@ +/* eslint-disable max-lines */ + +/** +* @license Apache-2.0 +* +* 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. +* 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 ENV = require( '@stdlib/process/env' ); +var INT32_MAX = require( '@stdlib/constants/int32/max' ); +var now = require( '@stdlib/time/now' ); +var isPositiveInteger = require( '@stdlib/math/base/assert/is-positive-integer' ); +var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var Int32Array = require( '@stdlib/array/int32' ); +var kstest = require( '@stdlib/stats/kstest' ); +var gcopy = require( '@stdlib/blas/base/gcopy' ); +var typedarray2json = require( '@stdlib/array/to-json' ); +var factory = require( './../lib/factory.js' ); + + +// VARIABLES // + +var opts = { + 'skip': ( ENV.TEST_MODE === 'coverage' ) +}; + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof factory, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'if provided an options argument which is not an object, the factory function throws an error', function test( t ) { + var values; + var i; + + values = [ + '5', + 3, + NaN, + true, + false, + null, + void 0, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory( value ); + }; + } +}); + +tape( 'if provided a `copy` option which is not a boolean, the factory function throws an error', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + null, + void 0, + {}, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'copy': value + }); + }; + } +}); + +tape( 'if provided a `seed` which is not a positive integer or a non-empty array-like object, the factory function throws an error', function test( t ) { + var values; + var i; + + values = [ + '5', + 3.14, + 0.0, + -5.0, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'seed': value + }); + }; + } +}); + +tape( 'the function throws a range error if provided a `seed` greater than or equal to the maximum signed 32-bit integer', function test( t ) { + var values; + var i; + + values = [ + INT32_MAX, + INT32_MAX + 1, + INT32_MAX + 2 + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws a range error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'seed': value + }); + }; + } +}); + +tape( 'if provided a `state` option which is not an Int32Array, the factory function throws an error', function test( t ) { + var values; + var i; + + values = [ + '5', + 5, + NaN, + true, + false, + null, + void 0, + {}, + [], + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'if provided a `state` option having an insufficient length, the factory function throws an error', function test( t ) { + var values; + var i; + + values = [ + new Int32Array( 0 ), + new Int32Array( 1 ) + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'if provided a `state` option containing an unsupported version, the factory function throws an error', function test( t ) { + var values; + var v; + var i; + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'if provided a `state` option containing an unsupported number of sections, the factory function throws an error', function test( t ) { + var values; + var v; + var i; + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 1; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'if provided a `state` option containing an unsupported state length, the factory function throws an error', function test( t ) { + var values; + var v; + var i; + + values = []; + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 8 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + v[ 7 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'if provided a `state` option containing an incompatible seed length, the factory function throws an error', function test( t ) { + var values; + var v; + var i; + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + factory({ + 'state': value + }); + }; + } +}); + +tape( 'the function returns a pseudorandom number generator (no options)', function test( t ) { + var xorshift; + var v; + var i; + + xorshift = factory(); + for ( i = 0; i < 1e3; i++ ) { + v = xorshift(); + t.equal( typeof v, 'number', 'returns a number' ); + t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); + t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + } + t.end(); +}); + +tape( 'the function returns a pseudorandom number generator (options; no seed)', function test( t ) { + var xorshift; + var v; + var i; + + xorshift = factory( {} ); + for ( i = 0; i < 1e3; i++ ) { + v = xorshift(); + t.equal( typeof v, 'number', 'returns a number' ); + t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); + t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + } + t.end(); +}); + +tape( 'the function returns a seeded pseudorandom number generator (integer seed)', function test( t ) { + var xorshift1; + var xorshift2; + var seed; + var v1; + var v2; + var i; + + seed = now(); + + xorshift1 = factory({ + 'seed': seed + }); + xorshift2 = factory({ + 'seed': seed + }); + + t.notEqual( xorshift1, xorshift2, 'separate generators' ); + + for ( i = 0; i < 1e3; i++ ) { + v1 = xorshift1(); + v2 = xorshift2(); + t.equal( v1, v2, 'both return same number' ); + } + t.end(); +}); + +tape( 'the function returns a seeded pseudorandom number generator (array seed)', function test( t ) { + var xorshift1; + var xorshift2; + var seed; + var v1; + var v2; + var i; + + seed = [ now() ]; + + xorshift1 = factory({ + 'seed': seed + }); + xorshift2 = factory({ + 'seed': seed + }); + + t.notEqual( xorshift1, xorshift2, 'separate generators' ); + + for ( i = 0; i < 1e3; i++ ) { + v1 = xorshift1(); + v2 = xorshift2(); + t.equal( v1, v2, 'both return same number' ); + } + t.end(); +}); + +tape( 'attached to the returned function is the generator name', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.NAME, 'xorshift', 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the minimum possible generated number', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.MIN, 1, 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the maximum possible generated number', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.MAX, INT32_MAX-1, 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the generator seed (integer seed)', function test( t ) { + var xorshift; + var actual; + + xorshift = factory({ + 'seed': 12345 + }); + actual = xorshift.seed; + + t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( actual.length, 1, 'has expected length' ); + t.equal( actual[ 0 ], 12345, 'equal to provided seed' ); + t.end(); +}); + +tape( 'attached to the returned function is the generator seed (array seed)', function test( t ) { + var xorshift; + var actual; + var seed; + var i; + + seed = [ 12345 ]; + + xorshift = factory({ + 'seed': seed + }); + actual = xorshift.seed; + + t.equal( isInt32Array( actual ), true, 'has property' ); + for ( i = 0; i < seed.length; i++ ) { + t.equal( actual[ i ], seed[ i ], 'returns expected value for word '+i ); + } + t.end(); +}); + +tape( 'attached to the returned function is the generator seed length', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.seedLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the generator state', function test( t ) { + var xorshift = factory(); + t.equal( isInt32Array( xorshift.state ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the generator state length', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.stateLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is the generator state size', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.byteLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the returned function is a method to serialize the generator as a JSON object', function test( t ) { + var xorshift; + var o; + + xorshift = factory(); + t.equal( typeof xorshift.toJSON, 'function', 'has method' ); + + o = xorshift.toJSON(); + t.equal( o.type, 'PRNG', 'has property' ); + t.equal( o.name, xorshift.NAME, 'has property' ); + t.deepEqual( o.state, typedarray2json( xorshift.state ), 'has property' ); + t.deepEqual( o.params, [], 'has property' ); + + t.end(); +}); + +tape( 'if the `state` property is set to a value other than an Int32Array, an error is thrown', function test( t ) { + var xorshift; + var values; + var i; + + xorshift = factory(); + + values = [ + '3', + 3, + -3, + 3.14, + 0, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws a type error when set to '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported version, an error is thrown', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported number of sections, an error is thrown', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 1; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported state length, an error is thrown', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 8 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + v[ 7 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an incompatible seed length, an error is thrown', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 1; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.state = value; + }; + } +}); + +tape( 'attached to the returned function is a `normalized` method for generating pseudorandom numbers strictly between 0 (inclusive) and 1 (exclusive)', function test( t ) { + var xorshift; + var v; + var i; + + xorshift = factory(); + for ( i = 0; i < 1e3; i++ ) { + v = xorshift.normalized(); + t.equal( typeof v, 'number', 'returns a number' ); + t.equal( v >= 0.0 && v < 1.0, true, 'returns a number between 0 (inclusive) and 1 (exclusive)' ); + } + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator name', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.normalized.NAME, 'xorshift', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the minimum possible generated number', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.normalized.MIN, 0.0, 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the maximum possible generated number', function test( t ) { + var xorshift = factory(); + t.equal( xorshift.normalized.MAX, (INT32_MAX-2.0)/(INT32_MAX-1.0), 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator seed (integer seed)', function test( t ) { + var xorshift; + var actual; + + xorshift = factory({ + 'seed': 12345 + }); + actual = xorshift.normalized.seed; + + t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( actual.length, 1, 'has expected length' ); + t.equal( actual[ 0 ], 12345, 'equal to provided seed' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator seed (array seed)', function test( t ) { + var xorshift; + var actual; + var seed; + var i; + + seed = [ 12345 ]; + xorshift = factory({ + 'seed': seed + }); + actual = xorshift.normalized.seed; + + t.equal( isInt32Array( actual ), true, 'has property' ); + for ( i = 0; i < seed.length; i++ ) { + t.equal( actual[ i ], seed[ i ], 'returns expected value for word '+i ); + } + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator seed length', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.normalized.seedLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state', function test( t ) { + var xorshift = factory(); + t.equal( isInt32Array( xorshift.normalized.state ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state length', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.normalized.stateLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state size', function test( t ) { + var xorshift = factory(); + t.equal( typeof xorshift.normalized.byteLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is a method to serialize the generator as a JSON object', function test( t ) { + var xorshift; + var o; + + xorshift = factory(); + t.equal( typeof xorshift.normalized.toJSON, 'function', 'has method' ); + + o = xorshift.normalized.toJSON(); + t.equal( o.type, 'PRNG', 'has property' ); + t.equal( o.name, xorshift.normalized.NAME, 'has property' ); + t.deepEqual( o.state, typedarray2json( xorshift.normalized.state ), 'has property' ); + + t.end(); +}); + +tape( 'if the `state` property is set to a value other than an Int32Array, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var i; + + xorshift = factory(); + + values = [ + '3', + -3, + 3, + 3.14, + 0, + NaN, + true, + false, + null, + void 0, + [], + {}, + function noop() {} + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when set to '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array having an unexpected length, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var i; + + xorshift = factory(); + + values = [ + new Int32Array( 0 ), + new Int32Array( 1 ) + ]; + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when set to '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported version, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported number of sections, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 0; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 3; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an unsupported state length, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 8 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 2; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 1; // state + v[ 5 ] = 1; // seed length + v[ 6 ] = 123; // seed + v[ 7 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'if the `state` property is set to an Int32Array containing an incompatible seed length, an error is thrown (normalized)', function test( t ) { + var xorshift; + var values; + var v; + var i; + + xorshift = factory(); + + values = []; + + v = new Int32Array( 6 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + values.push( v ); + + v = new Int32Array( 7 ); + v[ 0 ] = 0; // version + v[ 1 ] = 2; // number of sections + v[ 2 ] = 1; // state length + v[ 3 ] = 1; // state + v[ 4 ] = 9; // seed length + v[ 5 ] = 123; // seed + v[ 6 ] = 456; // seed + values.push( v ); + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), RangeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + xorshift.normalized.state = value; + }; + } +}); + +tape( 'the `normalized` method returns pseudorandom numbers drawn from a uniform distribution', opts, function test( t ) { + var threshold; + var count; + var npass; + var N; + var x; + + threshold = 0.10; + + x = []; + N = 500; + + count = -1; + npass = 0; + + gof(); + + function gof() { + var rejected; + var xorshift; + var pValue; + var bool; + var i; + var j; + + count += 1; + rejected = 0; + for ( i = 0; i < N; i++ ) { + xorshift = factory(); + t.ok( true, 'seed: '+xorshift.seed ); + for ( j = 0; j < 1e3; j++ ) { + x.push(xorshift.normalized()); + if ( x[ j ] < 0.0 || x[ j ] > 1.0 ) { + t.ok( false, 'returned a number outside support: '+x[ j ] ); + } + } + // Test using Kolmogorov-Smirnov goodness-of-fit test: + pValue = kstest( x, 'uniform', 0.0, 1.0 ).pValue; + t.equal( typeof pValue, 'number', 'returns a p-value: '+pValue ); + if ( pValue < 0.05 ) { + rejected += 1; + } + } + // Account for small sample size and few repeats... + bool = ( rejected / N < threshold ); + + // If we succeed the first time, we are done... + if ( count === 0 && bool ) { + return done( bool, rejected ); + } + // Retry mode... + if ( bool ) { + npass += 1; + } + // Retry twice... + if ( count < 2 ) { + return gof(); + } + // Both retries must succeed for test to pass: + bool = ( npass >= 2 ); + return done( bool, rejected ); + } + + function done( bool, rejected ) { + t.ok( bool, 'null hypothesis (i.e., that numbers are drawn from Uniform(0,1)) is rejected in less than '+(threshold*100)+'% of cases ('+rejected+' of '+N+'). Repeats: '+npass+' of '+count+'.' ); + t.end(); + } +}); + +tape( 'the function supports specifying the generator state', function test( t ) { + var xorshift; + var state; + var arr; + var i; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create another PRNG using the captured state: + xorshift = factory({ + 'state': state + }); + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the function supports specifying a shared generator state', function test( t ) { + var xorshift; + var shared; + var state; + var rand1; + var rand2; + var arr; + var v1; + var v2; + var i; + var j; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Create PRNGs using the captured state: + rand1 = factory({ + 'state': shared, + 'copy': false + }); + rand2 = factory({ + 'state': shared, + 'copy': false + }); + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + t.end(); +}); + +tape( 'the returned function supports setting the generator state', function test( t ) { + var xorshift; + var state; + var arr; + var i; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + // Set the state: + xorshift.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the returned function supports setting the generator state to a state array having a different length', function test( t ) { + var xorshift; + var shared; + var state; + var rand1; + var rand2; + var arr; + var v1; + var v2; + var i; + + // Seed length: 2 + xorshift = factory({ + 'seed': [ 1234, 5678 ] + }); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Create PRNGs having seed lengths equal to 1: + rand1 = factory({ + 'seed': [ 6789 ] + }); + rand2 = factory({ + 'seed': [ 4321 ] + }); + + // Move to future states... + for ( i = 0; i < 100; i++ ) { + v1 = rand1(); + v2 = rand2(); + } + + // Reset the PRNG states: + rand1.state = shared; + rand2.state = shared; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + v1 = rand1(); + t.equal( v1, arr[ i ], 'returns expected value. i: '+i+'.' ); + v2 = rand2(); + t.equal( v2, arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the returned function supports setting the generator state (normalized)', function test( t ) { + var xorshift; + var state; + var arr; + var i; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift.normalized(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift.normalized() ); + } + // Set the state: + xorshift.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift.normalized(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the returned function supports setting the generator state (normalized)', function test( t ) { + var xorshift; + var state; + var arr; + var i; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift.normalized(); + } + // Capture the current state: + state = xorshift.normalized.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift.normalized() ); + } + // Set the state: + xorshift.normalized.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift.normalized(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the returned function supports setting a shared generator state (same length)', function test( t ) { + var xorshift; + var shared; + var state; + var rand1; + var rand2; + var arr; + var v1; + var v2; + var i; + var j; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Create PRNGs using the captured state: + rand1 = factory({ + 'state': shared, + 'copy': false + }); + rand2 = factory({ + 'state': shared, + 'copy': false + }); + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + v2 = rand2(); + } + + // Reset the (shared) state: + rand1.state = new Int32Array( state ); + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + t.end(); +}); + +tape( 'the returned function supports setting a shared generator state (different length)', function test( t ) { + var xorshift; + var shared; + var state; + var rand1; + var rand2; + var arr; + var v1; + var v2; + var s; + var i; + var j; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Create PRNGs using the captured state: + rand1 = factory({ + 'state': shared, + 'copy': false + }); + rand2 = factory({ + 'state': shared, + 'copy': false + }); + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + v2 = rand2(); + } + + // Reset the (*previously* shared) state: + s = new Int32Array( state.length+1 ); + gcopy( state.length, state, 1, s, 1 ); + s[ s.length-3 ] = 2; + s[ s.length-1 ] = 1234; + rand1.state = s; + + // Attempt to replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + + // `rand1()` state is not affected by `rand2()`: + t.equal( v1, arr[ i ], 'returns expected value. i: '+i+'.' ); + + // `rand2()` state was never reset: + t.notEqual( v2, arr[ j+1 ], 'does not return expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + + // Reset the (*previously* shared) state: + rand2.state = s; + + // Reset to a shared state: + shared = new Int32Array( state ); + rand1.state = shared; + rand2.state = shared; + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + t.end(); +}); + +tape( 'the returned function supports setting a shared generator state (no initial shared state)', function test( t ) { + var xorshift; + var shared; + var state; + var rand1; + var rand2; + var arr; + var v1; + var v2; + var i; + var j; + + xorshift = factory(); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + + // Create PRNGs using the captured state: + rand1 = factory({ + 'copy': false + }); + rand2 = factory({ + 'copy': false + }); + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + v1 = rand1(); + v2 = rand2(); + } + + // Reset to a shared state: + rand1.state = shared; + rand2.state = shared; + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + + // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: + shared = new Int32Array( state ); + + // Reset the (shared) state: + rand1.state = shared; + rand2.state = shared; + + // Replay previously generated values... + j = 0; + for ( i = 0; i < 50; i++ ) { + v1 = rand1(); + v2 = rand2(); + t.equal( v1, arr[ j ], 'returns expected value. i: '+j+'.' ); + t.equal( v2, arr[ j+1 ], 'returns expected value. i: '+(j+1)+'.' ); + j += 2; // stride + } + t.end(); +}); diff --git a/lib/node_modules/@stdlib/random/base/xorshift/test/test.js b/lib/node_modules/@stdlib/random/base/xorshift/test/test.js new file mode 100644 index 000000000000..79ab0e8437ba --- /dev/null +++ b/lib/node_modules/@stdlib/random/base/xorshift/test/test.js @@ -0,0 +1,240 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 INT32_MAX = require( '@stdlib/constants/int32/max' ); +var isPositiveInteger = require( '@stdlib/math/base/assert/is-positive-integer' ); +var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var xorshift = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof xorshift, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'attached to the main export is a method to generate normalized pseudorandom numbers', function test( t ) { + t.equal( typeof xorshift.normalized, 'function', 'has method' ); + t.end(); +}); + +tape( 'attached to the main export is a method to generate linear congruential pseudorandom number generator', function test( t ) { + t.equal( typeof xorshift.factory, 'function', 'has method' ); + t.end(); +}); + +tape( 'attached to the main export is a method to serialize a pseudorandom number generator as JSON', function test( t ) { + t.equal( typeof xorshift.toJSON, 'function', 'has method' ); + t.end(); +}); + +tape( 'attached to the main export is the generator name', function test( t ) { + t.equal( xorshift.NAME, 'xorshift', 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the minimum possible generated number', function test( t ) { + t.equal( xorshift.MIN, 1, 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the maximum possible generated number', function test( t ) { + t.equal( xorshift.MAX, INT32_MAX-1, 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the generator seed', function test( t ) { + t.equal( isInt32Array( xorshift.seed ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the generator seed length', function test( t ) { + t.equal( typeof xorshift.seedLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the generator state', function test( t ) { + t.equal( isInt32Array( xorshift.state ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the generator state length', function test( t ) { + t.equal( typeof xorshift.stateLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the main export is the generator state size', function test( t ) { + t.equal( typeof xorshift.byteLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'the function returns pseudorandom integers strictly between 0 and 2^31-1 (inclusive)', function test( t ) { + var v; + var i; + for ( i = 0; i < 1e3; i++ ) { + v = xorshift(); + t.equal( typeof v, 'number', 'returns a number' ); + t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); + t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + } + t.end(); +}); + +tape( 'the `normalized` method returns pseudorandom numbers strictly between 0 (inclusive) and 1 (exclusive)', function test( t ) { + var v; + var i; + for ( i = 0; i < 1e3; i++ ) { + v = xorshift.normalized(); + t.equal( typeof v, 'number', 'returns a number' ); + t.equal( v >= 0.0 && v < 1.0, true, 'returns a number between 0 (inclusive) and 1 (exclusive)' ); + } + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator name', function test( t ) { + t.equal( xorshift.normalized.NAME, 'xorshift', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the minimum possible generated number', function test( t ) { + t.equal( xorshift.normalized.MIN, 0.0, 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the maximum possible generated number', function test( t ) { + t.equal( xorshift.normalized.MAX, (INT32_MAX-2.0)/(INT32_MAX-1.0), 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator seed', function test( t ) { + t.equal( isInt32Array( xorshift.normalized.seed ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator seed length', function test( t ) { + t.equal( typeof xorshift.normalized.seedLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state', function test( t ) { + t.equal( isInt32Array( xorshift.normalized.state ), true, 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state length', function test( t ) { + t.equal( typeof xorshift.normalized.stateLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is the generator state size', function test( t ) { + t.equal( typeof xorshift.normalized.byteLength, 'number', 'has property' ); + t.end(); +}); + +tape( 'attached to the `normalized` method is a method to serialize a pseudorandom number generator as JSON', function test( t ) { + t.equal( typeof xorshift.normalized.toJSON, 'function', 'has method' ); + t.end(); +}); + +tape( 'the generator supports setting the generator state', function test( t ) { + var state; + var arr; + var i; + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift() ); + } + // Set the state: + xorshift.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the generator supports setting the generator state (normalized)', function test( t ) { + var state; + var arr; + var i; + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift.normalized(); + } + // Capture the current state: + state = xorshift.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift.normalized() ); + } + // Set the state: + xorshift.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift.normalized(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); + +tape( 'the generator supports setting the generator state (normalized)', function test( t ) { + var state; + var arr; + var i; + + // Move to a future state... + for ( i = 0; i < 100; i++ ) { + xorshift.normalized(); + } + // Capture the current state: + state = xorshift.normalized.state; + + // Move to a future state... + arr = []; + for ( i = 0; i < 100; i++ ) { + arr.push( xorshift.normalized() ); + } + // Set the state: + xorshift.normalized.state = state; + + // Replay previously generated values... + for ( i = 0; i < 100; i++ ) { + t.equal( xorshift.normalized(), arr[ i ], 'returns expected value. i: '+i+'.' ); + } + t.end(); +}); From 338603973501e3ed137daa1a361b92ba018029e5 Mon Sep 17 00:00:00 2001 From: impawstarlight Date: Sun, 23 Mar 2025 18:17:45 +0600 Subject: [PATCH 2/6] feat(random): implement xorshift generator --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: na - task: lint_repl_help status: na - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: na - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: passed - task: lint_c_examples status: na - task: lint_c_benchmarks status: na - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../@stdlib/random/base/xorshift/README.md | 10 +- .../base/xorshift/docs/types/index.d.ts | 8 +- .../include/stdlib/random/base/xorshift.h | 6 +- .../random/base/xorshift/lib/factory.js | 81 +++++------ .../@stdlib/random/base/xorshift/src/main.c | 52 +++---- .../random/base/xorshift/test/test.factory.js | 134 +++++++++--------- .../@stdlib/random/base/xorshift/test/test.js | 20 +-- 7 files changed, 153 insertions(+), 158 deletions(-) diff --git a/lib/node_modules/@stdlib/random/base/xorshift/README.md b/lib/node_modules/@stdlib/random/base/xorshift/README.md index 11d568e94bdb..080b60f81b07 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/README.md +++ b/lib/node_modules/@stdlib/random/base/xorshift/README.md @@ -18,7 +18,7 @@ limitations under the License. --> -# MINSTD +# XORSHIFT > A linear congruential pseudorandom number generator ([LCG][lcg]) based on Park and Miller. @@ -70,7 +70,7 @@ var rand = xorshift.factory({ }); var r = rand(); -// returns 20739838 +// returns 332584831 ``` or, for arbitrary length seeds, an array-like `object` containing signed 32-bit integers @@ -83,7 +83,7 @@ var rand = xorshift.factory({ }); var r = rand(); -// returns 20739838 +// returns 332584831 ``` To return a generator having a specific initial state, set the generator `state` option. @@ -130,7 +130,7 @@ Maximum possible value. ```javascript var max = xorshift.MAX; -// returns 2147483646 +// returns 4294967295 ``` #### xorshift.seed @@ -178,7 +178,7 @@ r = xorshift(); // Get the current state: var state = xorshift.state; -// returns +// returns r = xorshift(); // returns diff --git a/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts index 42735e2bff6b..dea96d025aea 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/random/base/xorshift/docs/types/index.d.ts @@ -29,12 +29,12 @@ interface Options { /** * Pseudorandom number generator seed. */ - seed?: random.PRNGSeedMINSTD; + seed?: random.PRNGSeedXORSHIFT; /** * Pseudorandom number generator state. */ - state?: random.PRNGStateMINSTD; + state?: random.PRNGStateXORSHIFT; /** * Specifies whether to copy a provided pseudorandom number generator state. @@ -64,7 +64,7 @@ interface PRNG { /** * PRNG seed. */ - readonly seed: random.PRNGSeedMINSTD; + readonly seed: random.PRNGSeedXORSHIFT; /** * PRNG seed length. @@ -74,7 +74,7 @@ interface PRNG { /** * PRNG state. */ - state: random.PRNGStateMINSTD; + state: random.PRNGStateXORSHIFT; /** * PRNG state length. diff --git a/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h b/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h index b6a1284db22a..4d1e71cdddeb 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h +++ b/lib/node_modules/@stdlib/random/base/xorshift/include/stdlib/random/base/xorshift.h @@ -16,8 +16,8 @@ * limitations under the License. */ -#ifndef STDLIB_RANDOM_BASE_MINSTD_H -#define STDLIB_RANDOM_BASE_MINSTD_H +#ifndef STDLIB_RANDOM_BASE_XORSHIFT_H +#define STDLIB_RANDOM_BASE_XORSHIFT_H #include "stdlib/random/base/shared.h" #include @@ -66,4 +66,4 @@ int8_t stdlib_base_random_xorshift_set( struct BasePRNGObject *obj, const void * } #endif -#endif // !STDLIB_RANDOM_BASE_MINSTD_H +#endif // !STDLIB_RANDOM_BASE_XORSHIFT_H diff --git a/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js b/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js index 761bf9db66bb..2e231ef35fce 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js +++ b/lib/node_modules/@stdlib/random/base/xorshift/lib/factory.js @@ -30,10 +30,10 @@ var isObject = require( '@stdlib/assert/is-plain-object' ); var isBoolean = require( '@stdlib/assert/is-boolean' ).isPrimitive; var isCollection = require( '@stdlib/assert/is-collection' ); var isPositiveInteger = require( '@stdlib/assert/is-positive-integer' ).isPrimitive; -var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var isUint32Array = require( '@stdlib/assert/is-uint32array' ); var format = require( '@stdlib/string/format' ); -var INT32_MAX = require( '@stdlib/constants/int32/max' ); -var Int32Array = require( '@stdlib/array/int32' ); +var UINT32_MAX = require( '@stdlib/constants/uint32/max' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var gcopy = require( '@stdlib/blas/base/gcopy' ); var typedarray2json = require( '@stdlib/array/to-json' ); var randint32 = require( './rand_int32.js' ); @@ -41,9 +41,8 @@ var randint32 = require( './rand_int32.js' ); // VARIABLES // -var NORMALIZATION_CONSTANT = (INT32_MAX - 1)|0; // asm type annotation -var MAX_SEED = (INT32_MAX - 1)|0; // asm type annotation -var A = 16807|0; // asm type annotation +var NORMALIZATION_CONSTANT = UINT32_MAX >>> 0; // asm type annotation +var MAX_SEED = UINT32_MAX >>> 0; // asm type annotation // Define the state array schema version: var STATE_ARRAY_VERSION = 1; // NOTE: anytime the state array schema changes, this value should be incremented!!! @@ -67,7 +66,7 @@ var STATE_FIXED_LENGTH = 5; // 1 (version) + 1 (num_sections) + 1 (state_length) * Verifies state array integrity. * * @private -* @param {Int32Array} state - state array +* @param {Uint32Array} state - state array * @param {boolean} FLG - flag indicating whether the state array was provided as an option (true) or an argument (false) * @returns {(Error|null)} an error or `null` */ @@ -108,13 +107,13 @@ function verifyState( state, FLG ) { * Returns a linear congruential pseudorandom number generator (LCG) based on Park and Miller. * * @param {Options} [options] - options -* @param {PRNGSeedMINSTD} [options.seed] - pseudorandom number generator seed -* @param {PRNGStateMINSTD} [options.state] - pseudorandom number generator state +* @param {PRNGSeedXORSHIFT} [options.seed] - pseudorandom number generator seed +* @param {PRNGStateXORSHIFT} [options.state] - pseudorandom number generator state * @param {boolean} [options.copy=true] - boolean indicating whether to copy a provided pseudorandom number generator state * @throws {TypeError} options argument must be an object * @throws {TypeError} a seed must be either a positive integer less than the maximum signed 32-bit integer or an array-like object containing integers less than the maximum signed 32-bit integer * @throws {RangeError} a numeric seed must be a positive integer less than the maximum signed 32-bit integer -* @throws {TypeError} state must be an `Int32Array` +* @throws {TypeError} state must be an `Uint32Array` * @throws {Error} must provide a valid state * @throws {TypeError} `copy` option must be a boolean * @returns {PRNG} LCG PRNG @@ -132,7 +131,7 @@ function verifyState( state, FLG ) { * }); * * var v = xorshift(); -* // returns 20739838 +* // returns 332584831 */ function factory( options ) { var STATE; @@ -156,8 +155,8 @@ function factory( options ) { if ( hasOwnProp( options, 'state' ) ) { state = options.state; opts.state = true; - if ( !isInt32Array( state ) ) { - throw new TypeError( format( 'invalid option. `%s` option must be an Int32Array. Option: `%s`.', 'state', state ) ); + if ( !isUint32Array( state ) ) { + throw new TypeError( format( 'invalid option. `%s` option must be an Uint32Array. Option: `%s`.', 'state', state ) ); } err = verifyState( state, true ); if ( err ) { @@ -166,14 +165,14 @@ function factory( options ) { if ( opts.copy === false ) { STATE = state; } else { - STATE = new Int32Array( state.length ); + STATE = new Uint32Array( state.length ); gcopy( state.length, state, 1, STATE, 1 ); } // Create a state "view": - state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + state = new Uint32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); // Create a seed "view": - seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), state[ SEED_SECTION_OFFSET ] ); + seed = new Uint32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), state[ SEED_SECTION_OFFSET ] ); } // If provided a PRNG state, we ignore the `seed` option... if ( seed === void 0 ) { @@ -187,7 +186,7 @@ function factory( options ) { seed |= 0; // asm type annotation } else if ( isCollection( seed ) && seed.length > 0 ) { slen = seed.length; - STATE = new Int32Array( STATE_FIXED_LENGTH+slen ); + STATE = new Uint32Array( STATE_FIXED_LENGTH+slen ); // Initialize sections: STATE[ 0 ] = STATE_ARRAY_VERSION; @@ -199,10 +198,10 @@ function factory( options ) { gcopy.ndarray( slen, seed, 1, 0, STATE, 1, SEED_SECTION_OFFSET+1 ); // Create a state "view": - state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + state = new Uint32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); // Create a seed "view": - seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), slen ); + seed = new Uint32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), slen ); // Initialize the internal PRNG state: state[ 0 ] = seed[ 0 ]; @@ -210,14 +209,14 @@ function factory( options ) { throw new TypeError( format( 'invalid option. `%s` option must be either a positive integer less than the maximum signed 32-bit integer or an array-like object containing integer values less than the maximum signed 32-bit integer. Option: `%s`.', 'seed', seed ) ); } } else { - seed = randint32()|0; // asm type annotation + seed = randint32() >>> 0; // asm type annotation } } } else { - seed = randint32()|0; // asm type annotation + seed = randint32() >>> 0; // asm type annotation } if ( state === void 0 ) { - STATE = new Int32Array( STATE_FIXED_LENGTH+1 ); + STATE = new Uint32Array( STATE_FIXED_LENGTH+1 ); // Initialize sections: STATE[ 0 ] = STATE_ARRAY_VERSION; @@ -227,10 +226,10 @@ function factory( options ) { STATE[ SEED_SECTION_OFFSET+1 ] = seed; // Create a state "view": - state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + state = new Uint32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); // Create a seed "view": - seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + seed = new Uint32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); // Initialize the internal PRNG state: state[ 0 ] = seed[ 0 ]; @@ -243,7 +242,7 @@ function factory( options ) { setReadOnlyAccessor( xorshift, 'byteLength', getStateSize ); setReadOnly( xorshift, 'toJSON', toJSON ); setReadOnly( xorshift, 'MIN', 1 ); - setReadOnly( xorshift, 'MAX', INT32_MAX-1 ); + setReadOnly( xorshift, 'MAX', UINT32_MAX ); setReadOnly( xorshift, 'normalized', normalized ); setReadOnly( normalized, 'NAME', xorshift.NAME ); @@ -262,11 +261,11 @@ function factory( options ) { * Returns the PRNG seed. * * @private - * @returns {PRNGSeedMINSTD} seed + * @returns {PRNGSeedXORSHIFT} seed */ function getSeed() { var len = STATE[ SEED_SECTION_OFFSET ]; - return gcopy( len, seed, 1, new Int32Array( len ), 1 ); + return gcopy( len, seed, 1, new Uint32Array( len ), 1 ); } /** @@ -317,11 +316,11 @@ function factory( options ) { * - The first element of each section following the preamble specifies the section length. The remaining section elements comprise the section contents. * * @private - * @returns {PRNGStateMINSTD} current state + * @returns {PRNGStateXORSHIFT} current state */ function getState() { var len = STATE.length; - return gcopy( len, STATE, 1, new Int32Array( len ), 1 ); + return gcopy( len, STATE, 1, new Uint32Array( len ), 1 ); } /** @@ -333,14 +332,14 @@ function factory( options ) { * - 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). * * @private - * @param {PRNGStateMINSTD} s - generator state - * @throws {TypeError} must provide an `Int32Array` + * @param {PRNGStateXORSHIFT} s - generator state + * @throws {TypeError} must provide an `Uint32Array` * @throws {Error} must provide a valid state */ function setState( s ) { var err; - if ( !isInt32Array( s ) ) { - throw new TypeError( format( 'invalid argument. Must provide an Int32Array. Value: `%s`.', s ) ); + if ( !isUint32Array( s ) ) { + throw new TypeError( format( 'invalid argument. Must provide an Uint32Array. Value: `%s`.', s ) ); } err = verifyState( s, false ); if ( err ) { @@ -356,15 +355,15 @@ function factory( options ) { } else { // Check if we can reuse allocated memory... if ( s.length !== STATE.length ) { - STATE = new Int32Array( s.length ); // reallocate + STATE = new Uint32Array( s.length ); // reallocate } gcopy( s.length, s, 1, STATE, 1 ); } // Create a new state "view": - state = new Int32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); + state = new Uint32Array( STATE.buffer, STATE.byteOffset+((STATE_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), 1 ); // Create a new seed "view": - seed = new Int32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), STATE[ SEED_SECTION_OFFSET ] ); + seed = new Uint32Array( STATE.buffer, STATE.byteOffset+((SEED_SECTION_OFFSET+1)*STATE.BYTES_PER_ELEMENT), STATE[ SEED_SECTION_OFFSET ] ); } /** @@ -387,16 +386,18 @@ function factory( options ) { } /** - * Generates a pseudorandom integer on the interval \\( [1,2^{31}-1) \\). + * Generates a pseudorandom integer on the interval \\( [1,2^{31}) \\). * * @private * @returns {integer32} pseudorandom integer */ function xorshift() { - var s = state[ 0 ]|0; // asm type annotation - s = ( (A*s)%INT32_MAX )|0; // asm type annotation + var s = state[ 0 ] >>> 0; // asm type annotation + s ^= s << 13; + s ^= s >>> 17; + s ^= s << 5; state[ 0 ] = s; - return s|0; // asm type annotation + return s >>> 0; // asm type annotation } /** diff --git a/lib/node_modules/@stdlib/random/base/xorshift/src/main.c b/lib/node_modules/@stdlib/random/base/xorshift/src/main.c index ff3075c1050b..3df27a67c5fc 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/src/main.c +++ b/lib/node_modules/@stdlib/random/base/xorshift/src/main.c @@ -27,29 +27,26 @@ static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out ); static inline int8_t normalized( struct BasePRNGObject *obj, double *out ); static inline void xorshift_free( struct BasePRNGObject *obj ); -// Define the LCG multiplier: -static const uint32_t A = 16807; - -// Define the maximum signed 32-bit integer: 2147483647 => 0x7fffffff => 01111111111111111111111111111111 -static const uint32_t MAX_INT32 = 0x7fffffff; +// Define the maximum unsigned 32-bit integer: 4294967295 => 0xffffffff => 11111111111111111111111111111111 +static const uint32_t MAX_UINT32 = 0xffffffff; // Define the normalization constant: -static const double NORMALIZATION_CONSTANT = 2147483646.0; // MAX_INT32 - 1 +static const double NORMALIZATION_CONSTANT = (double)MAX_UINT32; /** -* MINSTD PRNG. +* XORSHIFT PRNG. * */ static const struct BasePRNG xorshift_prng = { - "xorshift", // name - (uint64_t)1, // min - (uint64_t)MAX_INT32-1, // max: (2^{31}-1) - 1 - 0.0, // min (normalized) - (MAX_INT32-2) / NORMALIZATION_CONSTANT, // max (normalized): (MAX-1)/MAX - sizeof( stdlib_base_random_xorshift_state_t ), // state_size - &next, // next() - &normalized, // normalized() - &xorshift_free // free() + "xorshift", // name + (uint64_t)1, // min + (uint64_t)MAX_UINT32, // max: 2^{32}-1 + 0.0, // min (normalized) + (MAX_UINT32-1) / NORMALIZATION_CONSTANT, // max (normalized): (MAX-1)/MAX + sizeof( stdlib_base_random_xorshift_state_t ), // state_size + &next, // next() + &normalized, // normalized() + &xorshift_free // free() }; /** @@ -73,8 +70,9 @@ static inline int8_t next( struct BasePRNGObject *obj, uint64_t *out ) { // Retrieve the current state: uint32_t state = so->state; - // Explicitly cast to 64-bit to handle integer overflow: - state = (A*(uint64_t)state) % MAX_INT32; + state ^= state << 13; + state ^= state >> 17; + state ^= state << 5; // Update the PRNG state: so->state = state; @@ -166,7 +164,7 @@ static inline void xorshift_free( struct BasePRNGObject *obj ) { * // Free allocated memory: * stdlib_base_random_xorshift_free( obj ); */ -struct BasePRNGObject * stdlib_base_random_xorshift_allocate( const int32_t seed ) { +struct BasePRNGObject * stdlib_base_random_xorshift_allocate( const uint32_t seed ) { uint32_t iseed; struct BasePRNGObject *obj = malloc( sizeof( struct BasePRNGObject ) ); @@ -181,15 +179,11 @@ struct BasePRNGObject * stdlib_base_random_xorshift_allocate( const int32_t seed // Ensure that the provided seed is within allowed bounds... if ( seed == 0 ) { iseed = 1; - } else if ( seed == MAX_INT32 ) { - iseed = MAX_INT32 - 1; - } else if ( seed < 0 ) { - iseed = -seed; } else { iseed = seed; } - state->seed = (uint32_t)iseed; - state->state = (uint32_t)iseed; + state->seed = iseed; + state->state = iseed; obj->prng = &xorshift_prng; obj->state = state; @@ -268,7 +262,7 @@ void stdlib_base_random_xorshift_free( struct BasePRNGObject *obj ) { * exit( 1 ); * } * -* int32_t seed; +* uint32_t seed; * int8_t status = stdlib_base_random_xorshift_seed( obj, &seed ); * if ( status != 0 ) { * fprintf( stderr, "Error encountered when attempting to retrieve the PRNG seed.\n" ); @@ -280,15 +274,15 @@ void stdlib_base_random_xorshift_free( struct BasePRNGObject *obj ) { * // Free allocated memory: * stdlib_base_random_xorshift_free( obj ); */ -int8_t stdlib_base_random_xorshift_seed( const struct BasePRNGObject *obj, int32_t *out ) { +int8_t stdlib_base_random_xorshift_seed( const struct BasePRNGObject *obj, uint32_t *out ) { if ( obj == NULL || obj->prng != &xorshift_prng ) { return -1; } - // Retrieve the MINSTD state object: + // Retrieve the XORSHIFT state object: const stdlib_base_random_xorshift_state_t *state = (stdlib_base_random_xorshift_state_t *)( obj->state ); // Set the output value: - *out = (int32_t)( state->seed ); + *out = state->seed; return 0; } diff --git a/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js b/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js index 740631687e30..15ad7bdb1abc 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js +++ b/lib/node_modules/@stdlib/random/base/xorshift/test/test.factory.js @@ -24,11 +24,11 @@ var tape = require( 'tape' ); var ENV = require( '@stdlib/process/env' ); -var INT32_MAX = require( '@stdlib/constants/int32/max' ); +var UINT32_MAX = require( '@stdlib/constants/uint32/max' ); var now = require( '@stdlib/time/now' ); var isPositiveInteger = require( '@stdlib/math/base/assert/is-positive-integer' ); -var isInt32Array = require( '@stdlib/assert/is-int32array' ); -var Int32Array = require( '@stdlib/array/int32' ); +var isUint32Array = require( '@stdlib/assert/is-uint32array' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var kstest = require( '@stdlib/stats/kstest' ); var gcopy = require( '@stdlib/blas/base/gcopy' ); var typedarray2json = require( '@stdlib/array/to-json' ); @@ -140,14 +140,14 @@ tape( 'if provided a `seed` which is not a positive integer or a non-empty array } }); -tape( 'the function throws a range error if provided a `seed` greater than or equal to the maximum signed 32-bit integer', function test( t ) { +tape( 'the function throws a range error if provided a `seed` greater than the maximum unsigned 32-bit integer', function test( t ) { var values; var i; values = [ - INT32_MAX, - INT32_MAX + 1, - INT32_MAX + 2 + UINT32_MAX + 1, + UINT32_MAX + 2, + UINT32_MAX + 3 ]; for ( i = 0; i < values.length; i++ ) { @@ -164,7 +164,7 @@ tape( 'the function throws a range error if provided a `seed` greater than or eq } }); -tape( 'if provided a `state` option which is not an Int32Array, the factory function throws an error', function test( t ) { +tape( 'if provided a `state` option which is not an Uint32Array, the factory function throws an error', function test( t ) { var values; var i; @@ -200,8 +200,8 @@ tape( 'if provided a `state` option having an insufficient length, the factory f var i; values = [ - new Int32Array( 0 ), - new Int32Array( 1 ) + new Uint32Array( 0 ), + new Uint32Array( 1 ) ]; for ( i = 0; i < values.length; i++ ) { @@ -225,7 +225,7 @@ tape( 'if provided a `state` option containing an unsupported version, the facto values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -234,7 +234,7 @@ tape( 'if provided a `state` option containing an unsupported version, the facto v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -265,7 +265,7 @@ tape( 'if provided a `state` option containing an unsupported number of sections values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 1; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -274,7 +274,7 @@ tape( 'if provided a `state` option containing an unsupported number of sections v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -305,7 +305,7 @@ tape( 'if provided a `state` option containing an unsupported state length, the values = []; - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -315,7 +315,7 @@ tape( 'if provided a `state` option containing an unsupported state length, the v[ 6 ] = 123; // seed values.push( v ); - v = new Int32Array( 8 ); + v = new Uint32Array( 8 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -347,7 +347,7 @@ tape( 'if provided a `state` option containing an incompatible seed length, the values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -356,7 +356,7 @@ tape( 'if provided a `state` option containing an incompatible seed length, the v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -390,7 +390,7 @@ tape( 'the function returns a pseudorandom number generator (no options)', funct v = xorshift(); t.equal( typeof v, 'number', 'returns a number' ); t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); - t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + t.equal( v >= 1 && v <= UINT32_MAX, true, 'returns an integer between 1 and 2^32-1 (inclusive)' ); } t.end(); }); @@ -405,7 +405,7 @@ tape( 'the function returns a pseudorandom number generator (options; no seed)', v = xorshift(); t.equal( typeof v, 'number', 'returns a number' ); t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); - t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + t.equal( v >= 1 && v <= UINT32_MAX, true, 'returns an integer between 1 and 2^32-1 (inclusive)' ); } t.end(); }); @@ -478,7 +478,7 @@ tape( 'attached to the returned function is the minimum possible generated numbe tape( 'attached to the returned function is the maximum possible generated number', function test( t ) { var xorshift = factory(); - t.equal( xorshift.MAX, INT32_MAX-1, 'has property' ); + t.equal( xorshift.MAX, UINT32_MAX, 'has property' ); t.end(); }); @@ -491,7 +491,7 @@ tape( 'attached to the returned function is the generator seed (integer seed)', }); actual = xorshift.seed; - t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( isUint32Array( actual ), true, 'has property' ); t.equal( actual.length, 1, 'has expected length' ); t.equal( actual[ 0 ], 12345, 'equal to provided seed' ); t.end(); @@ -510,7 +510,7 @@ tape( 'attached to the returned function is the generator seed (array seed)', fu }); actual = xorshift.seed; - t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( isUint32Array( actual ), true, 'has property' ); for ( i = 0; i < seed.length; i++ ) { t.equal( actual[ i ], seed[ i ], 'returns expected value for word '+i ); } @@ -525,7 +525,7 @@ tape( 'attached to the returned function is the generator seed length', function tape( 'attached to the returned function is the generator state', function test( t ) { var xorshift = factory(); - t.equal( isInt32Array( xorshift.state ), true, 'has property' ); + t.equal( isUint32Array( xorshift.state ), true, 'has property' ); t.end(); }); @@ -557,7 +557,7 @@ tape( 'attached to the returned function is a method to serialize the generator t.end(); }); -tape( 'if the `state` property is set to a value other than an Int32Array, an error is thrown', function test( t ) { +tape( 'if the `state` property is set to a value other than an Uint32Array, an error is thrown', function test( t ) { var xorshift; var values; var i; @@ -591,7 +591,7 @@ tape( 'if the `state` property is set to a value other than an Int32Array, an er } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported version, an error is thrown', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported version, an error is thrown', function test( t ) { var xorshift; var values; var v; @@ -601,7 +601,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -610,7 +610,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -632,7 +632,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported number of sections, an error is thrown', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported number of sections, an error is thrown', function test( t ) { var xorshift; var values; var v; @@ -642,7 +642,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 1; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -651,7 +651,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -673,7 +673,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported state length, an error is thrown', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported state length, an error is thrown', function test( t ) { var xorshift; var values; var v; @@ -683,7 +683,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -693,7 +693,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 6 ] = 123; // seed values.push( v ); - v = new Int32Array( 8 ); + v = new Uint32Array( 8 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -716,7 +716,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an incompatible seed length, an error is thrown', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an incompatible seed length, an error is thrown', function test( t ) { var xorshift; var values; var v; @@ -726,7 +726,7 @@ tape( 'if the `state` property is set to an Int32Array containing an incompatibl values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -735,7 +735,7 @@ tape( 'if the `state` property is set to an Int32Array containing an incompatibl v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 1; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -785,7 +785,7 @@ tape( 'attached to the `normalized` method is the minimum possible generated num tape( 'attached to the `normalized` method is the maximum possible generated number', function test( t ) { var xorshift = factory(); - t.equal( xorshift.normalized.MAX, (INT32_MAX-2.0)/(INT32_MAX-1.0), 'has property' ); + t.equal( xorshift.normalized.MAX, (UINT32_MAX-1.0)/UINT32_MAX, 'has property' ); t.end(); }); @@ -798,7 +798,7 @@ tape( 'attached to the `normalized` method is the generator seed (integer seed)' }); actual = xorshift.normalized.seed; - t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( isUint32Array( actual ), true, 'has property' ); t.equal( actual.length, 1, 'has expected length' ); t.equal( actual[ 0 ], 12345, 'equal to provided seed' ); t.end(); @@ -816,7 +816,7 @@ tape( 'attached to the `normalized` method is the generator seed (array seed)', }); actual = xorshift.normalized.seed; - t.equal( isInt32Array( actual ), true, 'has property' ); + t.equal( isUint32Array( actual ), true, 'has property' ); for ( i = 0; i < seed.length; i++ ) { t.equal( actual[ i ], seed[ i ], 'returns expected value for word '+i ); } @@ -831,7 +831,7 @@ tape( 'attached to the `normalized` method is the generator seed length', functi tape( 'attached to the `normalized` method is the generator state', function test( t ) { var xorshift = factory(); - t.equal( isInt32Array( xorshift.normalized.state ), true, 'has property' ); + t.equal( isUint32Array( xorshift.normalized.state ), true, 'has property' ); t.end(); }); @@ -862,7 +862,7 @@ tape( 'attached to the `normalized` method is a method to serialize the generato t.end(); }); -tape( 'if the `state` property is set to a value other than an Int32Array, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to a value other than an Uint32Array, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var i; @@ -896,7 +896,7 @@ tape( 'if the `state` property is set to a value other than an Int32Array, an er } }); -tape( 'if the `state` property is set to an Int32Array having an unexpected length, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array having an unexpected length, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var i; @@ -904,8 +904,8 @@ tape( 'if the `state` property is set to an Int32Array having an unexpected leng xorshift = factory(); values = [ - new Int32Array( 0 ), - new Int32Array( 1 ) + new Uint32Array( 0 ), + new Uint32Array( 1 ) ]; for ( i = 0; i < values.length; i++ ) { t.throws( badValue( values[i] ), RangeError, 'throws an error when set to '+values[i] ); @@ -919,7 +919,7 @@ tape( 'if the `state` property is set to an Int32Array having an unexpected leng } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported version, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported version, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var v; @@ -929,7 +929,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -938,7 +938,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -960,7 +960,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported number of sections, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported number of sections, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var v; @@ -970,7 +970,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 0; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -979,7 +979,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 3; // number of sections v[ 2 ] = 1; // state length @@ -1001,7 +1001,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an unsupported state length, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an unsupported state length, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var v; @@ -1011,7 +1011,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported values = []; - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -1021,7 +1021,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported v[ 6 ] = 123; // seed values.push( v ); - v = new Int32Array( 8 ); + v = new Uint32Array( 8 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 2; // state length @@ -1044,7 +1044,7 @@ tape( 'if the `state` property is set to an Int32Array containing an unsupported } }); -tape( 'if the `state` property is set to an Int32Array containing an incompatible seed length, an error is thrown (normalized)', function test( t ) { +tape( 'if the `state` property is set to an Uint32Array containing an incompatible seed length, an error is thrown (normalized)', function test( t ) { var xorshift; var values; var v; @@ -1054,7 +1054,7 @@ tape( 'if the `state` property is set to an Int32Array containing an incompatibl values = []; - v = new Int32Array( 6 ); + v = new Uint32Array( 6 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -1063,7 +1063,7 @@ tape( 'if the `state` property is set to an Int32Array containing an incompatibl v[ 5 ] = 123; // seed values.push( v ); - v = new Int32Array( 7 ); + v = new Uint32Array( 7 ); v[ 0 ] = 0; // version v[ 1 ] = 2; // number of sections v[ 2 ] = 1; // state length @@ -1094,7 +1094,6 @@ tape( 'the `normalized` method returns pseudorandom numbers drawn from a uniform threshold = 0.10; - x = []; N = 500; count = -1; @@ -1115,6 +1114,7 @@ tape( 'the `normalized` method returns pseudorandom numbers drawn from a uniform for ( i = 0; i < N; i++ ) { xorshift = factory(); t.ok( true, 'seed: '+xorshift.seed ); + x = []; for ( j = 0; j < 1e3; j++ ) { x.push(xorshift.normalized()); if ( x[ j ] < 0.0 || x[ j ] > 1.0 ) { @@ -1215,7 +1215,7 @@ tape( 'the function supports specifying a shared generator state', function test } // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Create PRNGs using the captured state: rand1 = factory({ @@ -1299,7 +1299,7 @@ tape( 'the returned function supports setting the generator state to a state arr } // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Create PRNGs having seed lengths equal to 1: rand1 = factory({ @@ -1417,7 +1417,7 @@ tape( 'the returned function supports setting a shared generator state (same len } // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Create PRNGs using the captured state: rand1 = factory({ @@ -1445,7 +1445,7 @@ tape( 'the returned function supports setting a shared generator state (same len } // Reset the (shared) state: - rand1.state = new Int32Array( state ); + rand1.state = new Uint32Array( state ); // Replay previously generated values... j = 0; @@ -1488,7 +1488,7 @@ tape( 'the returned function supports setting a shared generator state (differen } // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Create PRNGs using the captured state: rand1 = factory({ @@ -1516,7 +1516,7 @@ tape( 'the returned function supports setting a shared generator state (differen } // Reset the (*previously* shared) state: - s = new Int32Array( state.length+1 ); + s = new Uint32Array( state.length+1 ); gcopy( state.length, state, 1, s, 1 ); s[ s.length-3 ] = 2; s[ s.length-1 ] = 1234; @@ -1540,7 +1540,7 @@ tape( 'the returned function supports setting a shared generator state (differen rand2.state = s; // Reset to a shared state: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); rand1.state = shared; rand2.state = shared; @@ -1578,7 +1578,7 @@ tape( 'the returned function supports setting a shared generator state (no initi state = xorshift.state; // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Move to a future state... arr = []; @@ -1615,7 +1615,7 @@ tape( 'the returned function supports setting a shared generator state (no initi } // Create a copy of the state (to prevent mutation) which will be shared by more than one PRNG: - shared = new Int32Array( state ); + shared = new Uint32Array( state ); // Reset the (shared) state: rand1.state = shared; diff --git a/lib/node_modules/@stdlib/random/base/xorshift/test/test.js b/lib/node_modules/@stdlib/random/base/xorshift/test/test.js index 79ab0e8437ba..0fba895f7ed1 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/test/test.js +++ b/lib/node_modules/@stdlib/random/base/xorshift/test/test.js @@ -21,9 +21,9 @@ // MODULES // var tape = require( 'tape' ); -var INT32_MAX = require( '@stdlib/constants/int32/max' ); +var UINT32_MAX = require( '@stdlib/constants/uint32/max' ); var isPositiveInteger = require( '@stdlib/math/base/assert/is-positive-integer' ); -var isInt32Array = require( '@stdlib/assert/is-int32array' ); +var isUint32Array = require( '@stdlib/assert/is-uint32array' ); var xorshift = require( './../lib' ); @@ -61,12 +61,12 @@ tape( 'attached to the main export is the minimum possible generated number', fu }); tape( 'attached to the main export is the maximum possible generated number', function test( t ) { - t.equal( xorshift.MAX, INT32_MAX-1, 'has property' ); + t.equal( xorshift.MAX, UINT32_MAX, 'has property' ); t.end(); }); tape( 'attached to the main export is the generator seed', function test( t ) { - t.equal( isInt32Array( xorshift.seed ), true, 'has property' ); + t.equal( isUint32Array( xorshift.seed ), true, 'has property' ); t.end(); }); @@ -76,7 +76,7 @@ tape( 'attached to the main export is the generator seed length', function test( }); tape( 'attached to the main export is the generator state', function test( t ) { - t.equal( isInt32Array( xorshift.state ), true, 'has property' ); + t.equal( isUint32Array( xorshift.state ), true, 'has property' ); t.end(); }); @@ -90,14 +90,14 @@ tape( 'attached to the main export is the generator state size', function test( t.end(); }); -tape( 'the function returns pseudorandom integers strictly between 0 and 2^31-1 (inclusive)', function test( t ) { +tape( 'the function returns pseudorandom integers strictly between 1 and 2^32-1 (inclusive)', function test( t ) { var v; var i; for ( i = 0; i < 1e3; i++ ) { v = xorshift(); t.equal( typeof v, 'number', 'returns a number' ); t.equal( isPositiveInteger( v ), true, 'returns a positive integer' ); - t.equal( v >= 1 && v <= INT32_MAX-1, true, 'returns an integer between 1 and 2^31-1 (inclusive)' ); + t.equal( v >= 1 && v <= UINT32_MAX, true, 'returns an integer between 1 and 2^32-1 (inclusive)' ); } t.end(); }); @@ -124,12 +124,12 @@ tape( 'attached to the `normalized` method is the minimum possible generated num }); tape( 'attached to the `normalized` method is the maximum possible generated number', function test( t ) { - t.equal( xorshift.normalized.MAX, (INT32_MAX-2.0)/(INT32_MAX-1.0), 'has property' ); + t.equal( xorshift.normalized.MAX, (UINT32_MAX-1.0)/UINT32_MAX, 'has property' ); t.end(); }); tape( 'attached to the `normalized` method is the generator seed', function test( t ) { - t.equal( isInt32Array( xorshift.normalized.seed ), true, 'has property' ); + t.equal( isUint32Array( xorshift.normalized.seed ), true, 'has property' ); t.end(); }); @@ -139,7 +139,7 @@ tape( 'attached to the `normalized` method is the generator seed length', functi }); tape( 'attached to the `normalized` method is the generator state', function test( t ) { - t.equal( isInt32Array( xorshift.normalized.state ), true, 'has property' ); + t.equal( isUint32Array( xorshift.normalized.state ), true, 'has property' ); t.end(); }); From 41768f5372c85b2aadbabd894e5fd0e7b262d264 Mon Sep 17 00:00:00 2001 From: impawstarlight Date: Mon, 24 Mar 2025 01:46:00 +0600 Subject: [PATCH 3/6] docs: update docs and comments --- type: pre_commit_static_analysis_report description: Results of running static analysis checks when committing changes. report: - task: lint_filenames status: passed - task: lint_editorconfig status: passed - task: lint_markdown status: passed - task: lint_package_json status: passed - task: lint_repl_help status: passed - task: lint_javascript_src status: passed - task: lint_javascript_cli status: na - task: lint_javascript_examples status: passed - task: lint_javascript_tests status: passed - task: lint_javascript_benchmarks status: passed - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: passed - task: lint_c_examples status: passed - task: lint_c_benchmarks status: passed - task: lint_c_tests_fixtures status: na - task: lint_shell status: na - task: lint_typescript_declarations status: passed - task: lint_typescript_tests status: passed - task: lint_license_headers status: passed --- --- .../@stdlib/random/base/xorshift/README.md | 47 +++++++++-------- .../xorshift/benchmark/benchmark.factory.js | 6 +-- .../base/xorshift/benchmark/benchmark.js | 2 +- .../xorshift/benchmark/benchmark.to_json.js | 2 +- .../random/base/xorshift/benchmark/c/Makefile | 2 +- .../base/xorshift/benchmark/c/benchmark.c | 2 +- .../random/base/xorshift/docs/repl.txt | 33 ++++++------ .../base/xorshift/docs/types/index.d.ts | 26 +++++----- .../random/base/xorshift/docs/types/test.ts | 2 +- .../random/base/xorshift/examples/c/Makefile | 2 +- .../random/base/xorshift/examples/c/example.c | 6 +-- .../random/base/xorshift/examples/index.js | 2 +- .../include/stdlib/random/base/xorshift.h | 6 +-- .../random/base/xorshift/lib/factory.js | 24 ++++----- .../@stdlib/random/base/xorshift/lib/index.js | 4 +- .../@stdlib/random/base/xorshift/lib/main.js | 52 +++++++------------ .../lib/{rand_int32.js => rand_uint32.js} | 16 +++--- .../@stdlib/random/base/xorshift/package.json | 2 +- .../@stdlib/random/base/xorshift/src/main.c | 4 +- .../random/base/xorshift/test/test.factory.js | 2 +- .../@stdlib/random/base/xorshift/test/test.js | 4 +- lib/node_modules/@stdlib/types/index.d.ts | 20 +++++++ lib/node_modules/@stdlib/types/test.ts | 16 ++++++ 23 files changed, 152 insertions(+), 130 deletions(-) rename lib/node_modules/@stdlib/random/base/xorshift/lib/{rand_int32.js => rand_uint32.js} (74%) diff --git a/lib/node_modules/@stdlib/random/base/xorshift/README.md b/lib/node_modules/@stdlib/random/base/xorshift/README.md index 080b60f81b07..1ae25da8a7e1 100644 --- a/lib/node_modules/@stdlib/random/base/xorshift/README.md +++ b/lib/node_modules/@stdlib/random/base/xorshift/README.md @@ -2,7 +2,7 @@ @license Apache-2.0 -Copyright (c) 2018 The Stdlib Authors. +Copyright (c) 2025 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. @@ -20,7 +20,7 @@ limitations under the License. # XORSHIFT -> A linear congruential pseudorandom number generator ([LCG][lcg]) based on Park and Miller. +> A 32-bit xorshift pseudorandom number generator ([XORSHIFT][xorshift]) based on George Marsaglia.
@@ -32,7 +32,7 @@ var xorshift = require( '@stdlib/random/base/xorshift' ); #### xorshift() -Returns a pseudorandom integer on the interval `[1, 2147483646]`. +Returns a pseudorandom integer on the interval `[1, 4294967295]`. ```javascript var r = xorshift(); @@ -50,7 +50,7 @@ var r = xorshift.normalized(); #### xorshift.factory( \[options] ) -Returns a linear congruential pseudorandom number generator ([LCG][lcg]). +Returns a 32-bit xorshift pseudorandom number generator ([XORSHIFT][xorshift]). ```javascript var rand = xorshift.factory(); @@ -59,10 +59,10 @@ var rand = xorshift.factory(); The function accepts the following `options`: - **seed**: pseudorandom number generator seed. -- **state**: an [`Int32Array`][@stdlib/array/int32] containing pseudorandom number generator state. If provided, the function ignores the `seed` option. +- **state**: an [`Uint32Array`][@stdlib/array/uint32] 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 integer is used to seed the returned generator. To seed the generator, provide either an `integer` on the interval `[1, 2147483646]` +By default, a random integer is used to seed the returned generator. To seed the generator, provide either an `integer` on the interval `[1, 4294967295]` ```javascript var rand = xorshift.factory({ @@ -73,13 +73,13 @@ var r = rand(); // returns 332584831 ``` -or, for arbitrary length seeds, an array-like `object` containing signed 32-bit integers +or, for arbitrary length seeds, an array-like `object` containing unsigned 32-bit integers ```javascript -var Int32Array = require( '@stdlib/array/int32' ); +var Uint32Array = require( '@stdlib/array/uint32' ); var rand = xorshift.factory({ - 'seed': new Int32Array( [ 1234 ] ) + 'seed': new Uint32Array( [ 1234 ] ) }); var r = rand(); @@ -234,8 +234,8 @@ var o = xorshift.toJSON(); ## Notes -- The generator has a period of approximately `2.1e9` (see [Numerical Recipes in C, 2nd Edition](#references), p. 279). -- An [LCG][lcg] is fast and uses little memory. On the other hand, because the generator is a simple [linear congruential generator][lcg], the generator has recognized shortcomings. By today's PRNG standards, the generator's period is relatively short. More importantly, the "randomness quality" of the generator's output is lacking. These defects make the generator unsuitable, for example, in Monte Carlo simulations and in cryptographic applications. For more on the advantages and disadvantages of [LCGs][lcg], see [Wikipedia][pros-cons]. +- The generator has a period of `2^32-1`. +- Like all [LFSR][lfsr]s, the parameters have to be chosen very carefully in order to achieve a long period. For execution in software, xorshift generators are among the fastest PRNGs, requiring very small code and state. However, they do not pass every statistical test without further refinement. - 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). @@ -286,8 +286,7 @@ for ( i = 0; i < 100; i++ ) { ## References -- Park, S. K., and K. W. Miller. 1988. "Random Number Generators: Good Ones Are Hard to Find." _Communications of the ACM_ 31 (10). New York, NY, USA: ACM: 1192–1201. doi:[10.1145/63039.63042][@park:1988]. -- Press, William H., Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling. 1992. _Numerical Recipes in C: The Art of Scientific Computing, Second Edition_. Cambridge University Press. +- Marsaglia, G. 2003. "Xorshift RNGs." _Journal of Statistical Software_ 8 (14). Los Angeles, CA, USA: American Statistical Association: 1–6. doi:[10.18637/jss.v008.i14][@marsaglia:2003].
@@ -301,10 +300,12 @@ for ( i = 0; i < 100; i++ ) { ## See Also -- [`@stdlib/random/array/xorshift`][@stdlib/random/array/xorshift]: create an array containing pseudorandom numbers generated using a linear congruential pseudorandom number generator (LCG). -- [`@stdlib/random/iter/xorshift`][@stdlib/random/iter/xorshift]: create an iterator for a linear congruential pseudorandom number generator (LCG) based on Park and Miller. -- [`@stdlib/random/streams/xorshift`][@stdlib/random/streams/xorshift]: create a readable stream for a linear congruential pseudorandom number generator (LCG) based on Park and Miller. -- [`@stdlib/random/base/xorshift-shuffle`][@stdlib/random/base/xorshift-shuffle]: A linear congruential pseudorandom number generator (LCG) whose output is shuffled. + + - [`@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. @@ -316,23 +317,23 @@ for ( i = 0; i < 100; i++ ) {