From 715168da8912d9ef8fa7c7ec1ca25e39795bef30 Mon Sep 17 00:00:00 2001 From: Shubham Date: Thu, 26 Feb 2026 21:59:13 +0530 Subject: [PATCH 1/4] feat: add implementation of `stats/incr/nanmprod` --- 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: na - 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: passed - task: lint_license_headers status: passed --- --- .../@stdlib/stats/incr/nanmprod/README.md | 202 ++++++++++++++++++ .../incr/nanmprod/benchmark/benchmark.js | 70 ++++++ .../docs/img/equation_moving_product.svg | 30 +++ .../@stdlib/stats/incr/nanmprod/docs/repl.txt | 55 +++++ .../stats/incr/nanmprod/docs/types/index.d.ts | 73 +++++++ .../stats/incr/nanmprod/docs/types/test.ts | 66 ++++++ .../stats/incr/nanmprod/examples/index.js | 38 ++++ .../@stdlib/stats/incr/nanmprod/lib/index.js | 57 +++++ .../@stdlib/stats/incr/nanmprod/lib/main.js | 90 ++++++++ .../@stdlib/stats/incr/nanmprod/package.json | 69 ++++++ .../@stdlib/stats/incr/nanmprod/test/test.js | 111 ++++++++++ 11 files changed, 861 insertions(+) create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/README.md create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/docs/img/equation_moving_product.svg create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/docs/repl.txt create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/lib/index.js create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/package.json create mode 100644 lib/node_modules/@stdlib/stats/incr/nanmprod/test/test.js diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md b/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md new file mode 100644 index 000000000000..fc766f2f0f50 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md @@ -0,0 +1,202 @@ + + +# incrnanmprod + +> Compute a moving product incrementally, ignoring `NaN` values. + +
+ +For a window of size `W`, the moving product is defined as + + + +```math +\prod_{i=0}^{W-1} x_i +``` + + + + + +
+ + + +
+ +## Usage + +```javascript +var incrnanmprod = require( '@stdlib/stats/incr/nanmprod' ); +``` + +#### incrnanmprod( window ) + +Returns an accumulator `function` which incrementally computes a moving product, ignoring `NaN` values. The `window` parameter defines the number of values over which to compute the moving product. + +```javascript +var accumulator = incrnanmprod( 3 ); +``` + +#### accumulator( \[x] ) + +If provided an input value `x`, the accumulator function returns an updated product. If not provided an input value `x`, the accumulator function returns the current product. + +```javascript +var accumulator = incrnanmprod( 3 ); + +var p = accumulator(); +// returns null + +// Fill the window... +p = accumulator( 2.0 ); // [2.0] +// returns 2.0 + +p = accumulator( NaN ); // [2.0] (NaN ignored) +// returns 2.0 + +p = accumulator( 3.0 ); // [2.0, 3.0] +// returns 6.0 + +// Window begins sliding... +p = accumulator( 5.0 ); // [2.0, 3.0, 5.0] +// returns 30.0 + +p = accumulator( NaN ); // [2.0, 3.0, 5.0] (NaN ignored) +// returns 30.0 + +p = accumulator( 7.0 ); // [3.0, 5.0, 7.0] +// returns 105.0 + +p = accumulator(); +// returns 105.0 +``` + +Under certain conditions, overflow may be transient. + +```javascript +// Large values: +var x = 5.0e+300; +var y = 1.0e+300; + +// Tiny value: +var z = 2.0e-302; + +// Initialize an accumulator: +var accumulator = incrnanmprod( 3 ); + +var p = accumulator( x ); +// returns 5.0e+300 + +// Transient overflow: +p = accumulator( y ); +// returns Infinity + +// Recover a finite result: +p = accumulator( z ); +// returns 1.0e+299 +``` + +Similarly, under certain conditions, underflow may be transient. + +```javascript +// Tiny values: +var x = 4.0e-302; +var y = 9.0e-303; + +// Large value: +var z = 2.0e+300; + +// Initialize an accumulator: +var accumulator = incrnanmprod( 3 ); + +var p = accumulator( x ); +// returns 4.0e-302 + +// Transient underflow: +p = accumulator( y ); +// returns 0.0 + +// Recover a non-zero result: +p = accumulator( z ); +// returns 7.2e-304 +``` + +
+ + + +
+ +## Notes + +- Input values are **not** type checked. If non-numeric inputs are possible, you are advised to type check and handle accordingly **before** passing the value to the accumulator function. +- `NaN` values are ignored and do not affect the computed moving product. +- As `W` values are needed to fill the window buffer, the first `W-1` returned values are calculated from smaller sample sizes. Until the window is full, each returned value is calculated from all provided values. +- For large accumulation windows or accumulations of either large or small numbers, care should be taken to prevent overflow and underflow. Note, however, that overflow/underflow may be transient, as the accumulator does not use a double-precision floating-point number to store an accumulated product. Instead, the accumulator splits an accumulated product into a normalized **fraction** and **exponent** and updates each component separately. Doing so guards against a loss in precision. + +
+ + + +
+ +## Examples + + + +```javascript +var randu = require( '@stdlib/random/base/randu' ); +var incrnanmprod = require( '@stdlib/stats/incr/nanmprod' ); + +// Initialize an accumulator: +var accumulator = incrnanmprod( 5 ); + +// For each simulated datum, update the moving product... +var i; +for ( i = 0; i < 100; i++ ) { + accumulator( ( randu()*10.0 ) - 5.0 ); +} +console.log( accumulator() ); +``` + +
+ + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js new file mode 100644 index 000000000000..b1554f4c6425 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js @@ -0,0 +1,70 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var bench = require( '@stdlib/bench' ); +var randu = require( '@stdlib/random/base/randu' ); +var format = require( '@stdlib/string/format' ); +var pkg = require( './../package.json' ).name; +var incrnanmprod = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var f; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + f = incrnanmprod( (i%5)+1 ); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + } + b.toc(); + if ( typeof f !== 'function' ) { + b.fail( 'should return a function' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); + +bench( format( '%s::accumulator', pkg ), function benchmark( b ) { + var acc; + var v; + var i; + + acc = incrnanmprod( 5 ); + + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + v = acc( randu() ); + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + } + b.toc(); + if ( v !== v ) { + b.fail( 'should not return NaN' ); + } + b.pass( 'benchmark finished' ); + b.end(); +}); diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/img/equation_moving_product.svg b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/img/equation_moving_product.svg new file mode 100644 index 000000000000..6805f02488ba --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/img/equation_moving_product.svg @@ -0,0 +1,30 @@ + +product Underscript i equals 0 Overscript upper W minus 1 Endscripts x Subscript i + + + \ No newline at end of file diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/repl.txt b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/repl.txt new file mode 100644 index 000000000000..e39291a99b47 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/repl.txt @@ -0,0 +1,55 @@ + +{{alias}}( W ) + Returns an accumulator function which incrementally computes a moving + product, ignoring `NaN` values. + + The `W` parameter defines the number of values over which to compute the + moving product. + + If provided a value, the accumulator function returns an updated moving + product. If not provided a value, the accumulator function returns the + current moving product. + + `NaN` values are ignored and do not affect the computed moving product. + + As `W` values are needed to fill the window buffer, the first `W-1` returned + values are calculated from smaller sample sizes. Until the window is full, + each returned value is calculated from all provided values. + + For accumulations over large windows or accumulations of large numbers, care + should be taken to prevent overflow. Note, however, that overflow/underflow + may be transient, as the accumulator does not use a double-precision + floating-point number to store an accumulated product. Instead, the + accumulator splits an accumulated product into a normalized fraction and + exponent and updates each component separately. Doing so guards against a + loss in precision. + + Parameters + ---------- + W: integer + Window size. + + Returns + ------- + acc: Function + Accumulator function. + + Examples + -------- + > var accumulator = {{alias}}( 3 ); + > var p = accumulator() + null + > p = accumulator( 2.0 ) + 2.0 + > p = accumulator( NaN ) + 2.0 + > p = accumulator( 3.0 ) + 6.0 + > p = accumulator( 5.0 ) + 30.0 + > p = accumulator() + 30.0 + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts new file mode 100644 index 000000000000..bcc95c53ac71 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts @@ -0,0 +1,73 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +// TypeScript Version: 4.1 + +/// + +/** +* If provided a value, returns an updated product; otherwise, returns the current product. +* +* @param x - value +* @returns product +*/ +type accumulator = ( x?: number ) => number | null; + +/** +* Returns an accumulator function which incrementally computes a moving product, ignoring `NaN` values. +* +* ## Notes +* +* - The `W` parameter defines the number of values over which to compute the moving product. +* - As `W` values are needed to fill the window buffer, the first `W-1` returned values are calculated from smaller sample sizes. Until the window is full, each returned value is calculated from all provided values. +* +* @param W - window size +* @returns accumulator function +* +* @example +* var nanmprod = require( '@stdlib/stats/incr/nanmprod' ); +* +* var accumulator = incrnanmprod( 3 ); +* +* var p = accumulator(); +* // returns null +* +* p = accumulator( 2.0 ); +* // returns 2.0 +* +* p = accumulator( NaN ); +* // returns 2.0 +* +* p = accumulator( 3.0 ); +* // returns 6.0 +* +* p = accumulator( 5.0 ); +* // returns 30.0 +* +* p = accumulator( 5.0 ); +* // returns 75.0 +* +* p = accumulator(); +* // returns 75.0 +*/ +declare function incrnanmprod( W: number ): accumulator; + + +// EXPORTS // + +export = incrnanmprod; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts new file mode 100644 index 000000000000..f572fb82307b --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts @@ -0,0 +1,66 @@ +/* +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +import incrnanmprod = require( './index' ); + + +// TESTS // + +// The function returns an accumulator function... +{ + incrnanmprod( 3 ); // $ExpectType accumulator +} + +// The compiler throws an error if the function is provided an argument which is not a number... +{ + incrnanmprod( '5' ); // $ExpectError + incrnanmprod( true ); // $ExpectError + incrnanmprod( false ); // $ExpectError + incrnanmprod( null ); // $ExpectError + incrnanmprod( undefined ); // $ExpectError + incrnanmprod( [] ); // $ExpectError + incrnanmprod( {} ); // $ExpectError + incrnanmprod( ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an invalid number of arguments... +{ + incrnanmprod(); // $ExpectError + incrnanmprod( 2, 3 ); // $ExpectError +} + +// The function returns an accumulator function which returns an accumulated result... +{ + const acc = incrnanmprod( 3 ); + + acc(); // $ExpectType number | null + acc( 3.14 ); // $ExpectType number | null +} + +// The compiler throws an error if the returned accumulator function is provided invalid arguments... +{ + const acc = incrnanmprod( 3 ); + + acc( '5' ); // $ExpectError + acc( true ); // $ExpectError + acc( false ); // $ExpectError + acc( null ); // $ExpectError + acc( [] ); // $ExpectError + acc( {} ); // $ExpectError + acc( ( x: number ): number => x ); // $ExpectError +} diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js new file mode 100644 index 000000000000..7a8f99414237 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js @@ -0,0 +1,38 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +var randu = require( '@stdlib/random/base/randu' ); +var incrnanmprod = require( './../lib' ); + +var accumulator; +var p; +var v; +var i; + +// Initialize an accumulator: +accumulator = incrnanmprod( 5 ); + +// For each simulated datum, update the moving product... +console.log( '\nValue\tProduct\n' ); +for ( i = 0; i < 100; i++ ) { + v = ( randu()*10.0 ) - 5.0; + p = accumulator( v ); + console.log( '%d\t%d', v.toFixed( 3 ), p.toFixed( 3 ) ); +} diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/index.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/index.js new file mode 100644 index 000000000000..35f5bfed3722 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/index.js @@ -0,0 +1,57 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +/** +* Compute a moving product incrementally, ignoring `NaN` values. +* +* @module @stdlib/stats/incr/nanmprod +* +* @example +* var incrnanmprod = require( '@stdlib/stats/incr/nanmprod' ); +* +* var accumulator = incrnanmprod( 3 ); +* +* var p = accumulator(); +* // returns null +* +* p = accumulator( 2.0 ); +* // returns 2.0 +* +* p = accumulator( NaN ); +* // returns 2.0 +* +* p = accumulator( 3.0 ); +* // returns 6.0 +* +* p = accumulator( 5.0 ); +* // returns 30.0 +* +* p = accumulator(); +* // returns 30.0 +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js new file mode 100644 index 000000000000..40c2f3465ef9 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js @@ -0,0 +1,90 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var incrmprod = require( '@stdlib/stats/incr/mprod' ); + + +// MAIN // + +/** +* Returns an accumulator function which incrementally computes a moving product, ignoring `NaN` values. +* +* ## Method +* +* To avoid overflow/underflow, we store the fractional and exponent parts of intermediate results separately. By keeping a normalized fraction, we prevent underflow/overflow of the fraction. Underflow of the exponent is impossible, as IEEE 754 floating-point exponents are integer values. Overflow of the exponent is possible, but highly unlikely. In the worst case, an intermediate exponent is greater than the minimum safe integer, and adding the exponent of an incoming value does not change the intermediate result. While incorrect, such behavior does not lead to exponent overflow. +* +* While intermediate results are largely immune to overflow and not subject to underflow, this does not mean that returned results will never be zero or infinite. In fact, zero (underflow) and infinite (overflow) results may be transient (i.e., infinity followed by a finite number). +* +* ## References +* +* - Ueberhuber, Christoph W. 1997. _Numerical Computation 1: Methods, Software, and Analysis_. Springer-Verlag Berlin Heidelberg. doi:[10.1007/978-3-642-59118-1](https://doi.org/10.1007/978-3-642-59118-1). +* +* @param {PositiveInteger} W - window size +* @returns {Function} accumulator function +* +* @example +* var nanmprod = require( '@stdlib/stats/incr/nanmprod' ); +* +* var accumulator = incrnanmprod( 3 ); +* +* var p = accumulator(); +* // returns null +* +* p = accumulator( 2.0 ); +* // returns 2.0 +* +* p = accumulator( NaN ); +* // returns 2.0 +* +* p = accumulator( 3.0 ); +* // returns 6.0 +* +* p = accumulator( 5.0 ); +* // returns 30.0 +* +* p = accumulator(); +* // returns 30.0 +*/ +function incrnanmprod( W ) { + var prod = incrmprod( W ); + return accumulator; + + /** + * If provided a value, the accumulator function returns an updated prod. If not provided a value, the accumulator function returns the current prod. + * + * @private + * @param {number} [x] - input value + * @returns {(number|null)} prod or null + */ + function accumulator( x ) { + if ( arguments.length === 0 || isnan( x ) ) { + return prod(); + } + return prod( x ); + } +} + + +// EXPORTS // + +module.exports = incrnanmprod; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/package.json b/lib/node_modules/@stdlib/stats/incr/nanmprod/package.json new file mode 100644 index 000000000000..7cd88893fa18 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/package.json @@ -0,0 +1,69 @@ +{ + "name": "@stdlib/stats/incr/nanmprod", + "version": "0.0.0", + "description": "Compute a moving product incrementally, ignoring NaN values.", + "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", + "lib": "./lib", + "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", + "statistics", + "stats", + "mathematics", + "math", + "product", + "prod", + "incremental", + "accumulator", + "moving prod", + "moving product", + "sliding window", + "sliding", + "window", + "moving" + ] +} diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/test/test.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/test/test.js new file mode 100644 index 000000000000..9a9a891d40e2 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/test/test.js @@ -0,0 +1,111 @@ +/** +* @license Apache-2.0 +* +* Copyright (c) 2026 The Stdlib Authors. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +'use strict'; + +// MODULES // + +var tape = require( 'tape' ); +var incrnanmprod = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof incrnanmprod, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function returns an accumulator function', function test( t ) { + t.strictEqual( typeof incrnanmprod( 3 ), 'function', 'returns expected value' ); + t.end(); +}); + +tape( 'the initial accumulated value is `null`', function test( t ) { + var acc = incrnanmprod( 3 ); + t.strictEqual( acc(), null, 'returns expected value' ); + t.end(); +}); + +tape( 'the function throws an error if not provided a positive integer', function test( t ) { + var values; + var i; + + values = [ + '5', + -5.0, + 0.0, + 3.14, + true, + null, + void 0, + NaN, + [], + {}, + function noop() {} + ]; + + for ( i = 0; i < values.length; i++ ) { + t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] ); + } + t.end(); + + function badValue( value ) { + return function badValue() { + incrnanmprod( value ); + }; + } +}); + +tape( 'the accumulator function computes a moving product incrementally', function test( t ) { + var expected; + var actual; + var data; + var acc; + var N; + var i; + + data = [ 2.0, 3.0, NaN, 4.0, NaN, 4.0 ]; + N = data.length; + + acc = incrnanmprod( 3 ); + + actual = []; + for ( i = 0; i < N; i++ ) { + actual.push( acc( data[ i ] ) ); + } + expected = [ 2.0, 6.0, 6.0, 24.0, 24.0, 48.0 ]; + + t.deepEqual( actual, expected, 'returns expected incremental results' ); + t.end(); +}); + +tape( 'if not provided an input value, the accumulator function returns the current product', function test( t ) { + var data; + var acc; + var i; + + data = [ 2.0, NaN, -5.0, 3.0, 5.0 ]; + acc = incrnanmprod( 3 ); + for ( i = 0; i < data.length; i++ ) { + acc( data[ i ] ); + } + t.strictEqual( acc(), -75.0, 'returns expected value' ); + t.end(); +}); From fc5789bfacc424efc707f7a3740cd986f74ac65e Mon Sep 17 00:00:00 2001 From: Shubham Date: Wed, 4 Mar 2026 19:21:28 +0530 Subject: [PATCH 2/4] fix: apply code suggestions --- 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: passed - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: passed - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - 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: passed - task: lint_license_headers status: passed --- --- lib/node_modules/@stdlib/stats/incr/nanmprod/README.md | 7 ++++--- .../@stdlib/stats/incr/nanmprod/benchmark/benchmark.js | 3 +-- .../@stdlib/stats/incr/nanmprod/docs/types/test.ts | 1 + .../@stdlib/stats/incr/nanmprod/examples/index.js | 5 +++-- .../@stdlib/stats/incr/nanmprod/lib/main.js | 10 ---------- 5 files changed, 9 insertions(+), 17 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md b/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md index fc766f2f0f50..369052469b0c 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/README.md @@ -79,13 +79,13 @@ p = accumulator( NaN ); // [2.0] (NaN ignored) p = accumulator( 3.0 ); // [2.0, 3.0] // returns 6.0 -// Window begins sliding... p = accumulator( 5.0 ); // [2.0, 3.0, 5.0] // returns 30.0 p = accumulator( NaN ); // [2.0, 3.0, 5.0] (NaN ignored) // returns 30.0 +// Window begins sliding... p = accumulator( 7.0 ); // [3.0, 5.0, 7.0] // returns 105.0 @@ -167,7 +167,8 @@ p = accumulator( z ); ```javascript -var randu = require( '@stdlib/random/base/randu' ); +var uniform = require( '@stdlib/random/base/uniform' ); +var bernoulli = require( '@stdlib/random/base/bernoulli' ); var incrnanmprod = require( '@stdlib/stats/incr/nanmprod' ); // Initialize an accumulator: @@ -176,7 +177,7 @@ var accumulator = incrnanmprod( 5 ); // For each simulated datum, update the moving product... var i; for ( i = 0; i < 100; i++ ) { - accumulator( ( randu()*10.0 ) - 5.0 ); + accumulator( ( bernoulli( 0.8 ) < 1 ) ? NaN : uniform( -30.0, 30.0 ) ); } console.log( accumulator() ); ``` diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js index b1554f4c6425..afa540b87bca 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/benchmark/benchmark.js @@ -21,7 +21,6 @@ // MODULES // var bench = require( '@stdlib/bench' ); -var randu = require( '@stdlib/random/base/randu' ); var format = require( '@stdlib/string/format' ); var pkg = require( './../package.json' ).name; var incrnanmprod = require( './../lib' ); @@ -56,7 +55,7 @@ bench( format( '%s::accumulator', pkg ), function benchmark( b ) { b.tic(); for ( i = 0; i < b.iterations; i++ ) { - v = acc( randu() ); + v = acc( (i%5) ? i : NaN ); if ( v !== v ) { b.fail( 'should not return NaN' ); } diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts index f572fb82307b..fd594b8b4b1c 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/test.ts @@ -50,6 +50,7 @@ import incrnanmprod = require( './index' ); acc(); // $ExpectType number | null acc( 3.14 ); // $ExpectType number | null + acc( NaN ); // $ExpectType number | null } // The compiler throws an error if the returned accumulator function is provided invalid arguments... diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js index 7a8f99414237..89340e37bb94 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js @@ -18,7 +18,8 @@ 'use strict'; -var randu = require( '@stdlib/random/base/randu' ); +var uniform = require( '@stdlib/random/base/uniform' ); +var bernoulli = require( '@stdlib/random/base/bernoulli' ); var incrnanmprod = require( './../lib' ); var accumulator; @@ -32,7 +33,7 @@ accumulator = incrnanmprod( 5 ); // For each simulated datum, update the moving product... console.log( '\nValue\tProduct\n' ); for ( i = 0; i < 100; i++ ) { - v = ( randu()*10.0 ) - 5.0; + v = ( bernoulli( 0.8 ) < 1 ) ? NaN : uniform( -30.0, 30.0 ); p = accumulator( v ); console.log( '%d\t%d', v.toFixed( 3 ), p.toFixed( 3 ) ); } diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js index 40c2f3465ef9..76c11fcc4e02 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js @@ -29,16 +29,6 @@ var incrmprod = require( '@stdlib/stats/incr/mprod' ); /** * Returns an accumulator function which incrementally computes a moving product, ignoring `NaN` values. * -* ## Method -* -* To avoid overflow/underflow, we store the fractional and exponent parts of intermediate results separately. By keeping a normalized fraction, we prevent underflow/overflow of the fraction. Underflow of the exponent is impossible, as IEEE 754 floating-point exponents are integer values. Overflow of the exponent is possible, but highly unlikely. In the worst case, an intermediate exponent is greater than the minimum safe integer, and adding the exponent of an incoming value does not change the intermediate result. While incorrect, such behavior does not lead to exponent overflow. -* -* While intermediate results are largely immune to overflow and not subject to underflow, this does not mean that returned results will never be zero or infinite. In fact, zero (underflow) and infinite (overflow) results may be transient (i.e., infinity followed by a finite number). -* -* ## References -* -* - Ueberhuber, Christoph W. 1997. _Numerical Computation 1: Methods, Software, and Analysis_. Springer-Verlag Berlin Heidelberg. doi:[10.1007/978-3-642-59118-1](https://doi.org/10.1007/978-3-642-59118-1). -* * @param {PositiveInteger} W - window size * @returns {Function} accumulator function * From 374e0b49343b923a85ba69bae5de738406f06e80 Mon Sep 17 00:00:00 2001 From: Shubham Date: Mon, 9 Mar 2026 18:48:16 +0530 Subject: [PATCH 3/4] fix: apply code suggestions --- 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: na - 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: passed - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - 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: passed - task: lint_license_headers status: passed --- --- .../@stdlib/stats/incr/nanmprod/docs/types/index.d.ts | 1 - .../@stdlib/stats/incr/nanmprod/examples/index.js | 2 +- lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js | 6 ++---- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts index bcc95c53ac71..23b6ea3c6921 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/docs/types/index.d.ts @@ -40,7 +40,6 @@ type accumulator = ( x?: number ) => number | null; * @returns accumulator function * * @example -* var nanmprod = require( '@stdlib/stats/incr/nanmprod' ); * * var accumulator = incrnanmprod( 3 ); * diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js index 89340e37bb94..e4b8e4ee33d7 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js @@ -35,5 +35,5 @@ console.log( '\nValue\tProduct\n' ); for ( i = 0; i < 100; i++ ) { v = ( bernoulli( 0.8 ) < 1 ) ? NaN : uniform( -30.0, 30.0 ); p = accumulator( v ); - console.log( '%d\t%d', v.toFixed( 3 ), p.toFixed( 3 ) ); + console.log( '%d\t%d', v.toFixed( 3 ), ( p === null ) ? NaN : p.toFixed( 3 ) ); } diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js index 76c11fcc4e02..50b7d11c1cd1 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js @@ -33,7 +33,6 @@ var incrmprod = require( '@stdlib/stats/incr/mprod' ); * @returns {Function} accumulator function * * @example -* var nanmprod = require( '@stdlib/stats/incr/nanmprod' ); * * var accumulator = incrnanmprod( 3 ); * @@ -60,11 +59,10 @@ function incrnanmprod( W ) { return accumulator; /** - * If provided a value, the accumulator function returns an updated prod. If not provided a value, the accumulator function returns the current prod. - * + * If provided a value, the accumulator function returns an updated product. If not provided a value, the accumulator function returns the current product. * @private * @param {number} [x] - input value - * @returns {(number|null)} prod or null + * @returns {(number|null)} product or null */ function accumulator( x ) { if ( arguments.length === 0 || isnan( x ) ) { From 7c5929594b254e2af6153f6e9dd9ab0d3159f1c0 Mon Sep 17 00:00:00 2001 From: Shubham Date: Tue, 10 Mar 2026 19:07:09 +0530 Subject: [PATCH 4/4] fix: apply code suggestions --- 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: na - 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: passed - task: lint_javascript_tests status: na - task: lint_javascript_benchmarks status: na - task: lint_python status: na - task: lint_r status: na - task: lint_c_src status: na - 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 --- --- lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js | 2 +- lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js index e4b8e4ee33d7..159013a035c8 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/examples/index.js @@ -35,5 +35,5 @@ console.log( '\nValue\tProduct\n' ); for ( i = 0; i < 100; i++ ) { v = ( bernoulli( 0.8 ) < 1 ) ? NaN : uniform( -30.0, 30.0 ); p = accumulator( v ); - console.log( '%d\t%d', v.toFixed( 3 ), ( p === null ) ? NaN : p.toFixed( 3 ) ); + console.log( '%s\t%s', v.toFixed( 3 ), ( p === null ) ? NaN : p.toFixed( 3 ) ); } diff --git a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js index 50b7d11c1cd1..0a5787a0a347 100644 --- a/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js +++ b/lib/node_modules/@stdlib/stats/incr/nanmprod/lib/main.js @@ -60,6 +60,7 @@ function incrnanmprod( W ) { /** * If provided a value, the accumulator function returns an updated product. If not provided a value, the accumulator function returns the current product. + * * @private * @param {number} [x] - input value * @returns {(number|null)} product or null