diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/README.md b/lib/node_modules/@stdlib/stats/incr/nanmstdev/README.md new file mode 100644 index 000000000000..3d652c8b71df --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/README.md @@ -0,0 +1,183 @@ + + +# incrnanmstdev + +> Compute a moving [corrected sample standard deviation][standard-deviation] incrementally, ignoring NaN values. + +
+ +For a window of size `W`, the [corrected sample standard deviation][standard-deviation] is defined as + + + +```math +s = \sqrt{\frac{1}{W-1} \sum_{i=0}^{W-1} ( x_i - \bar{x} )^2} +``` + + + + + +
+ + + +
+ +## Usage + +```javascript +var incrnanmstdev = require( '@stdlib/stats/incr/nanmstdev' ); +``` + +#### incrnanmstdev( window\[, mean] ) + +Returns an accumulator `function` which incrementally computes a moving [corrected sample standard deviation][standard-deviation], ignoring `NaN` values. The `window` parameter defines the number of values over which to compute the moving [corrected sample standard deviation][standard-deviation]. + +```javascript +var accumulator = incrnanmstdev( 3 ); +``` + +If the mean is already known, provide a `mean` argument. + +```javascript +var accumulator = incrnanmstdev( 3, 5.0 ); +``` + +#### accumulator( \[x] ) + +If provided an input value `x`, the accumulator function returns an updated [corrected sample standard deviation][standard-deviation]. If not provided an input value `x`, the accumulator function returns the current [corrected sample standard deviation][standard-deviation]. If provided `NaN`, the accumulator function ignores the value and returns the current [corrected sample standard deviation][standard-deviation] without updating the window. + +```javascript +var accumulator = incrnanmstdev( 3 ); + +var s = accumulator(); +// returns null + +// Fill the window with non-NaN values... +s = accumulator( 2.0 ); // [2.0] +// returns 0.0 + +s = accumulator( NaN ); // [2.0] +// returns 0.0 + +s = accumulator( 3.0 ); // [2.0, 3.0] +// returns ~0.7071 + +s = accumulator( 5.0 ); // [2.0, 3.0, 5.0] +// returns ~1.53 + +// Window begins sliding... +s = accumulator( -7.0 ); // [3.0, 5.0, -7.0] +// returns ~6.43 + +s = accumulator( NaN ); // [3.0, 5.0, -7.0] +// returns ~6.43 + +s = accumulator( -5.0 ); // [5.0, -7.0, -5.0] +// returns ~6.43 + +s = accumulator(); +// returns ~6.43 +``` + +
+ + + +
+ +## Notes + +- Input values are **not** type checked. If provided `NaN`, the value is ignored and the accumulator function returns the current [corrected sample standard deviation][standard-deviation] without updating the window. If non-numeric inputs are possible, you are advised to type check and handle accordingly **before** passing the value to the accumulator function. +- 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 (excluding NaN values). + +
+ + + +
+ +## Examples + + + +```javascript +var randu = require( '@stdlib/random/base/randu' ); +var incrnanmstdev = require( '@stdlib/stats/incr/nanmstdev' ); + +var accumulator; +var v; +var i; + +// Initialize an accumulator: +accumulator = incrnanmstdev( 5 ); + +// For each simulated datum, update the moving corrected sample standard deviation... +for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = randu() * 100.0; + } + accumulator( v ); +} +console.log( accumulator() ); +``` + +
+ + + + + + + + + + + + + + diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/incr/nanmstdev/benchmark/benchmark.js new file mode 100644 index 000000000000..219f6c3bcf9d --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/benchmark/benchmark.js @@ -0,0 +1,91 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 pkg = require( './../package.json' ).name; +var incrnanmstdev = require( './../lib' ); + + +// MAIN // + +bench( pkg, function benchmark( b ) { + var f; + var i; + b.tic(); + for ( i = 0; i < b.iterations; i++ ) { + f = incrnanmstdev( (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( pkg+'::accumulator', function benchmark( b ) { + var acc; + var v; + var i; + + acc = incrnanmstdev( 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(); +}); + +bench( pkg+'::accumulator,known_mean', function benchmark( b ) { + var acc; + var v; + var i; + + acc = incrnanmstdev( 5, 3.0 ); + + 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/nanmstdev/docs/img/equation_corrected_sample_standard_deviation.svg b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/img/equation_corrected_sample_standard_deviation.svg new file mode 100644 index 000000000000..dfe5a3d60cbb --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/img/equation_corrected_sample_standard_deviation.svg @@ -0,0 +1,73 @@ + +s equals StartRoot StartFraction 1 Over upper W minus 1 EndFraction sigma-summation Underscript i equals 0 Overscript upper W minus 1 Endscripts left-parenthesis x Subscript i Baseline minus x overbar right-parenthesis squared EndRoot + + + \ No newline at end of file diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/repl.txt b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/repl.txt new file mode 100644 index 000000000000..4589f9e9d77b --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/repl.txt @@ -0,0 +1,56 @@ + +{{alias}}( W[, mean] ) + Returns an accumulator function which incrementally computes a moving + corrected sample standard deviation, ignoring NaN values. + + The `W` parameter defines the number of values over which to compute the + moving corrected sample standard deviation. + + If provided a value, the accumulator function returns an updated moving + corrected sample standard deviation. If not provided a value, the + accumulator function returns the current moving corrected sample standard + deviation. + + 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. + + NaN values are ignored during computation. If provided NaN, the + accumulator returns the current corrected sample standard deviation. + + Parameters + ---------- + W: integer + Window size. + + mean: number (optional) + Known mean. + + Returns + ------- + acc: Function + Accumulator function. + + Examples + -------- + > var accumulator = {{alias}}( 3 ); + > var s = accumulator() + null + > s = accumulator( 2.0 ) + 0.0 + > s = accumulator( NaN ) + 0.0 + > s = accumulator( -5.0 ) + ~4.95 + > s = accumulator( 3.0 ) + ~4.36 + > s = accumulator( NaN ) + ~4.36 + > s = accumulator( 5.0 ) + ~5.29 + > s = accumulator() + ~5.29 + + See Also + -------- + diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/index.d.ts new file mode 100644 index 000000000000..7661335a91e1 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/index.d.ts @@ -0,0 +1,84 @@ +/* +* @license Apache-2.0 +* +* 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. +* 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 corrected sample standard deviation; otherwise, returns the current corrected sample standard deviation. +* +* ## Notes +* +* - If provided `NaN` or a value which, when used in computations, results in `NaN`, the accumulated value is not updated (i.e., NaN values are ignored). +* +* @param x - value +* @returns corrected sample standard deviation +*/ +type accumulator = ( x?: number ) => number | null; + +/** +* Returns an accumulator function which incrementally computes a moving corrected sample standard deviation, ignoring NaN values. +* +* ## Notes +* +* - The `W` parameter defines the number of values over which to compute the moving corrected sample standard deviation. +* - 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. +* - NaN values are ignored. +* +* @param W - window size +* @param mean - mean value +* @throws first argument must be a positive integer +* @returns accumulator function +* +* @example +* var accumulator = incrnanmstdev( 3 ); +* +* var s = accumulator(); +* // returns null +* +* s = accumulator( 2.0 ); +* // returns 0.0 +* +* s = accumulator( NaN ); +* // returns 0.0 +* +* s = accumulator( -5.0 ); +* // returns ~4.95 +* +* s = accumulator( 3.0 ); +* // returns ~4.36 +* +* s = accumulator( NaN ); +* // returns ~4.36 +* +* s = accumulator( 5.0 ); +* // returns ~5.29 +* +* s = accumulator(); +* // returns ~5.29 +* +* @example +* var accumulator = incrnanmstdev( 3, 5.0 ); +*/ +declare function incrnanmstdev( W: number, mean?: number ): accumulator; + + +// EXPORTS // + +export = incrnanmstdev; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/test.ts b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/test.ts new file mode 100644 index 000000000000..da67fda500e6 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/docs/types/test.ts @@ -0,0 +1,77 @@ +/* +* @license Apache-2.0 +* +* 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. +* 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 incrnanmstdev = require( './index' ); + + +// TESTS // + +// The function returns an accumulator function... +{ + incrnanmstdev( 3 ); // $ExpectType accumulator + incrnanmstdev( 3, 0.0 ); // $ExpectType accumulator +} + +// The compiler throws an error if the function is provided a first argument which is not a number... +{ + incrnanmstdev( '5' ); // $ExpectError + incrnanmstdev( true ); // $ExpectError + incrnanmstdev( false ); // $ExpectError + incrnanmstdev( null ); // $ExpectError + incrnanmstdev( [] ); // $ExpectError + incrnanmstdev( {} ); // $ExpectError + incrnanmstdev( ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided a second argument which is not a number... +{ + incrnanmstdev( 3, '5' ); // $ExpectError + incrnanmstdev( 3, true ); // $ExpectError + incrnanmstdev( 3, false ); // $ExpectError + incrnanmstdev( 3, null ); // $ExpectError + incrnanmstdev( 3, [] ); // $ExpectError + incrnanmstdev( 3, {} ); // $ExpectError + incrnanmstdev( 3, ( x: number ): number => x ); // $ExpectError +} + +// The compiler throws an error if the function is provided an invalid number of arguments... +{ + incrnanmstdev(); // $ExpectError + incrnanmstdev( 3, 2.5, 3 ); // $ExpectError +} + +// The function returns an accumulator function which returns an accumulated result... +{ + const acc = incrnanmstdev( 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 = incrnanmstdev( 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/nanmstdev/examples/index.js b/lib/node_modules/@stdlib/stats/incr/nanmstdev/examples/index.js new file mode 100644 index 000000000000..1c6661472c92 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/examples/index.js @@ -0,0 +1,42 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 incrnanmstdev = require( './../lib' ); + +var accumulator; +var s; +var v; +var i; + +// Initialize an accumulator: +accumulator = incrnanmstdev( 5 ); + +// For each simulated datum, update the moving t-student standard deviation... +console.log( '\nValue\tT-Student Stdev\n' ); +for ( i = 0; i < 100; i++ ) { + if ( randu() < 0.2 ) { + v = NaN; + } else { + v = randu() * 100.0; + } + s = accumulator( v ); + console.log( '%d\t%d', v.toFixed( 4 ), (s === null) ? NaN : s.toFixed( 4 ) ); +} diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/index.js b/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/index.js new file mode 100644 index 000000000000..77da373559f8 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/index.js @@ -0,0 +1,63 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 corrected sample standard deviation incrementally, ignoring NaN values. +* +* @module @stdlib/stats/incr/nanmstdev +* +* @example +* var incrnanmstdev = require( '@stdlib/stats/incr/nanmstdev' ); +* +* var accumulator = incrnanmstdev( 3 ); +* +* var s = accumulator(); +* // returns null +* +* s = accumulator( 2.0 ); +* // returns 0.0 +* +* s = accumulator( NaN ); +* // returns 0.0 +* +* s = accumulator( -5.0 ); +* // returns ~4.95 +* +* s = accumulator( 3.0 ); +* // returns ~4.36 +* +* s = accumulator( NaN ); +* // returns ~4.36 +* +* s = accumulator( 5.0 ); +* // returns ~5.29 +* +* s = accumulator(); +* // returns ~5.29 +*/ + +// MODULES // + +var main = require( './main.js' ); + + +// EXPORTS // + +module.exports = main; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/main.js b/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/main.js new file mode 100644 index 000000000000..c6019c85afb5 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/lib/main.js @@ -0,0 +1,167 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 incrmstdev = require( '@stdlib/stats/incr/mstdev' ); + + +// MAIN // + +/** +* Returns an accumulator function which incrementally computes a moving corrected sample standard deviation, ignoring NaN values. +* +* ## Method +* +* - Let \\(W\\) be a window of \\(N\\) elements over which we want to compute an corrected sample standard deviation. +* +* - We first recognize that the corrected sample standard deviation is defined as the square root of the unbiased sample variance. Accordingly, in order to derive an update equation for the corrected sample standard deviation, deriving an update equation for the unbiased sample variance is sufficient. +* +* - The difference between the unbiased sample variance in a window \\(W_i\\) and the unbiased sample variance in a window \\(W_{i+1})\\) is given by +* +* ```tex +* \Delta s^2 = s_{i+1}^2 - s_{i}^2 +* ``` +* +* - If we multiply both sides by \\(N-1\\), +* +* ```tex +* (N-1)(\Delta s^2) = (N-1)s_{i+1}^2 - (N-1)s_{i}^2 +* ``` +* +* - If we substitute the definition of the unbiased sample variance having the form +* +* ```tex +* \begin{align*} +* s^2 &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} (x_i - \bar{x})^2 \biggr) \\ +* &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} (x_i^2 - 2\bar{x}x_i + \bar{x}^2) \biggr) \\ +* &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} x_i^2 - 2\bar{x} \sum_{i=1}^{N} x_i + \sum_{i=1}^{N} \bar{x}^2) \biggr) \\ +* &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} x_i^2 - \frac{2N\bar{x}\sum_{i=1}^{N} x_i}{N} + N\bar{x}^2 \biggr) \\ +* &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} x_i^2 - 2N\bar{x}^2 + N\bar{x}^2 \biggr) \\ +* &= \frac{1}{N-1} \biggl( \sum_{i=1}^{N} x_i^2 - N\bar{x}^2 \biggr) +* \end{align*} +* ``` +* +* we return +* +* ```tex +* (N-1)(\Delta s^2) = \biggl(\sum_{k=1}^N x_k^2 - N\bar{x}_{i+1}^2 \biggr) - \biggl(\sum_{k=0}^{N-1} x_k^2 - N\bar{x}_{i}^2 \biggr) +* ``` +* +* - This can be further simplified by recognizing that subtracting the sums reduces to \\(x_N^2 - x_0^2\\); in which case, +* +* ```tex +* \begin{align*} +* (N-1)(\Delta s^2) &= x_N^2 - x_0^2 - N\bar{x}_{i+1}^2 + N\bar{x}_{i}^2 \\ +* &= x_N^2 - x_0^2 - N(\bar{x}_{i+1}^2 - \bar{x}_{i}^2) \\ +* &= x_N^2 - x_0^2 - N(\bar{x}_{i+1} - \bar{x}_{i})(\bar{x}_{i+1} + \bar{x}_{i}) +* \end{align*} +* ``` +* +* - Recognizing that the difference of means can be expressed +* +* ```tex +* \bar{x}_{i+1} - \bar{x}_i = \frac{1}{N} \biggl( \sum_{k=1}^N x_k - \sum_{k=0}^{N-1} x_k \biggr) = \frac{x_N - x_0}{N} +* ``` +* +* and substituting into the equation above +* +* ```tex +* (N-1)(\Delta s^2) = x_N^2 - x_0^2 - (x_N - x_0)(\bar{x}_{i+1} + \bar{x}_{i}) +* ``` +* +* - Rearranging terms gives us the update equation +* +* ```tex +* \begin{align*} +* (N-1)(\Delta s^2) &= (x_N - x_0)(x_N + x_0) - (x_N - x_0)(\bar{x}_{i+1} + \bar{x}_{i}) \\ +* &= (x_N - x_0)(x_N + x_0 - \bar{x}_{i+1} - \bar{x}_{i}) \\ +* &= (x_N - x_0)(x_N - \bar{x}_{i+1} + x_0 - \bar{x}_{i}) +* \end{align*} +* ``` +* +* @param {PositiveInteger} W - window size +* @param {number} [mean] - mean value +* @throws {TypeError} first argument must be a positive integer +* @throws {TypeError} second argument must be a number +* @returns {Function} accumulator function +* +* @example +* var accumulator = incrnanmstdev( 3 ); +* +* var s = accumulator(); +* // returns null +* +* s = accumulator( 2.0 ); +* // returns 0.0 +* +* s = accumulator( NaN ); +* // returns 0.0 +* +* s = accumulator( -5.0 ); +* // returns ~4.95 +* +* s = accumulator( 3.0 ); +* // returns ~4.36 +* +* s = accumulator( NaN ); +* // returns ~4.36 +* +* s = accumulator( 5.0 ); +* // returns ~5.29 +* +* s = accumulator(); +* // returns ~5.29 +* +* @example +* var accumulator = incrnanmstdev( 3, 5.0 ); +*/ +function incrnanmstdev( W, mean ) { + var acc; + if ( arguments.length > 1 ) { + acc = incrmstdev( W, mean ); + } else { + acc = incrmstdev( W ); + } + return accumulator; + + /** + * If provided a value, the accumulator function returns an updated standard deviation. If not provided a value, the accumulator function returns the current standard deviation. + * + * @private + * @param {number} [x] - new value + * @returns {(number|null)} standard deviation or null + */ + function accumulator( x ) { + if ( arguments.length === 0 ) { + return acc(); + } + if ( isnan( x ) ) { + return acc(); + } + return acc( x ); + } +} + + +// EXPORTS // + +module.exports = incrnanmstdev; diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/package.json b/lib/node_modules/@stdlib/stats/incr/nanmstdev/package.json new file mode 100644 index 000000000000..38a9bb398e03 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/package.json @@ -0,0 +1,74 @@ +{ + "name": "@stdlib/stats/incr/nanmstdev", + "version": "0.0.0", + "description": "Compute a moving corrected sample standard deviation 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", + "variance", + "sample", + "sample variance", + "stdev", + "standard", + "deviation", + "corrected", + "dispersion", + "incremental", + "accumulator", + "moving variance", + "sliding window", + "sliding", + "window", + "moving" + ] +} diff --git a/lib/node_modules/@stdlib/stats/incr/nanmstdev/test/test.js b/lib/node_modules/@stdlib/stats/incr/nanmstdev/test/test.js new file mode 100644 index 000000000000..c693f7684b13 --- /dev/null +++ b/lib/node_modules/@stdlib/stats/incr/nanmstdev/test/test.js @@ -0,0 +1,414 @@ +/** +* @license Apache-2.0 +* +* 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. +* 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 abs = require( '@stdlib/math/base/special/abs' ); +var sqrt = require( '@stdlib/math/base/special/sqrt' ); +var randu = require( '@stdlib/random/base/randu' ); +var EPS = require( '@stdlib/constants/float64/eps' ); +var incrnanmstdev = require( './../lib' ); + + +// TESTS // + +tape( 'main export is a function', function test( t ) { + t.ok( true, __filename ); + t.strictEqual( typeof incrnanmstdev, 'function', 'main export is a function' ); + t.end(); +}); + +tape( 'the function throws an error if not provided a positive integer for the window size', 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() { + incrnanmstdev( value ); + }; + } +}); + +tape( 'the function throws an error if not provided a positive integer for the window size (known mean)', 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() { + incrnanmstdev( value, 5.0 ); + }; + } +}); + +tape( 'the function throws an error if not provided a number as the mean value', function test( t ) { + var values; + var i; + + values = [ + '5', + true, + false, + null, + void 0, + [], + {}, + 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() { + incrnanmstdev( 3, value ); + }; + } +}); + +tape( 'the function returns an accumulator function', function test( t ) { + t.equal( typeof incrnanmstdev( 3 ), 'function', 'returns a function' ); + t.end(); +}); + +tape( 'the function returns an accumulator function (known mean)', function test( t ) { + t.equal( typeof incrnanmstdev( 3, 3.0 ), 'function', 'returns a function' ); + t.end(); +}); + +tape( 'the accumulator function computes a moving corrected sample standard deviation incrementally', function test( t ) { + var expected; + var actual; + var data; + var acc; + var N; + var i; + + data = [ 2.0, 3.0, 4.0, -1.0, 3.0, 1.0 ]; + N = data.length; + + acc = incrnanmstdev( 3 ); + + actual = []; + for ( i = 0; i < N; i++ ) { + actual.push( acc( data[ i ] ) ); + } + expected = [ + 0.0, + sqrt( 0.5 ), + 1.0, + sqrt( 7.0 ), + sqrt( 7.0 ), + 2.0 + ]; + + t.deepEqual( actual, expected, 'returns expected incremental results' ); + t.end(); +}); + +tape( 'the accumulator function computes a moving corrected sample standard deviation incrementally (known mean)', function test( t ) { + var expected; + var actual; + var data; + var acc; + var N; + var i; + + data = [ 2.0, 3.0, 4.0, -1.0, 3.0, 1.0 ]; + N = data.length; + + acc = incrnanmstdev( 3, 2.0 ); + + actual = []; + for ( i = 0; i < N; i++ ) { + actual.push( acc( data[ i ] ) ); + } + expected = [ + 0.0, + sqrt( 0.5 ), + sqrt( 1.6666666666666666 ), + sqrt( 4.6666666666666666 ), + sqrt( 4.6666666666666666 ), + sqrt( 3.6666666666666666 ) + ]; + + t.deepEqual( actual, expected, 'returns expected incremental results' ); + t.end(); +}); + +tape( 'if not provided an input value, the accumulator function returns the current corrected sample standard deviation', function test( t ) { + var expected; + var actual; + var delta; + var data; + var tol; + var acc; + var i; + + data = [ 2.0, 3.0, 10.0 ]; + acc = incrnanmstdev( 3 ); + for ( i = 0; i < data.length-1; i++ ) { + acc( data[ i ] ); + } + t.equal( acc(), sqrt( 0.5 ), 'returns current corrected sample standard deviation' ); + + acc( data[ data.length-1 ] ); + + expected = sqrt( 19.0 ); + actual = acc(); + delta = abs( actual - expected ); + tol = EPS * expected; + + t.equal( delta < tol, true, 'expected: '+expected+'. actual: '+actual+'. tol: '+tol+'. delta: '+delta+'.' ); + t.end(); +}); + +tape( 'if not provided an input value, the accumulator function returns the current corrected sample standard deviation (known mean)', function test( t ) { + var expected; + var actual; + var delta; + var data; + var tol; + var acc; + var i; + + data = [ 2.0, 3.0, 10.0 ]; + acc = incrnanmstdev( 3, 5.0 ); + for ( i = 0; i < data.length-1; i++ ) { + acc( data[ i ] ); + } + t.equal( acc(), sqrt( 6.5 ), 'returns current unbiased sample variance' ); + + acc( data[ data.length-1 ] ); + + expected = sqrt( 12.666666666666666 ); + actual = acc(); + delta = abs( actual - expected ); + tol = EPS * expected; + + t.equal( delta < tol, true, 'expected: '+expected+'. actual: '+actual+'. tol: '+tol+'. delta: '+delta+'.' ); + t.end(); +}); + +tape( 'if data has yet to be provided, the accumulator function returns `null`', function test( t ) { + var acc = incrnanmstdev( 3 ); + t.equal( acc(), null, 'returns null' ); + t.end(); +}); + +tape( 'if data has yet to be provided, the accumulator function returns `null` (known mean)', function test( t ) { + var acc = incrnanmstdev( 3, 3.0 ); + t.equal( acc(), null, 'returns null' ); + t.end(); +}); + +tape( 'if only one datum has been provided and the mean is unknown, the accumulator function returns `0`', function test( t ) { + var acc = incrnanmstdev( 3 ); + acc( 2.0 ); + t.equal( acc(), 0.0, 'returns 0' ); + t.end(); +}); + +tape( 'if only one datum has been provided and the mean is known, the accumulator function may not return `0`', function test( t ) { + var acc = incrnanmstdev( 3, 3.0 ); + acc( 2.0 ); + t.notEqual( acc(), 0.0, 'does not return 0' ); + t.end(); +}); + +tape( 'if the window size is `1` and the mean is unknown, the accumulator functions always returns `0`', function test( t ) { + var acc; + var s; + var i; + + acc = incrnanmstdev( 1 ); + for ( i = 0; i < 100; i++ ) { + s = acc( randu() * 100.0 ); + t.equal( s, 0.0, 'returns 0' ); + } + t.end(); +}); + +tape( 'if the window size is `1` and the mean is known, the accumulator functions does not always returns `0`', function test( t ) { + var acc; + var s; + var i; + + acc = incrnanmstdev( 1, 500.0 ); // mean is larger than simulated value range, so stdev should never be zero + for ( i = 0; i < 100; i++ ) { + s = acc( randu() * 100.0 ); + t.notEqual( s, 0.0, 'does not return 0' ); + } + t.end(); +}); + +tape( 'if provided a NaN, the accumulator function ignores it (unknown mean, W=1)', function test( t ) { + var expected; + var data; + var acc; + var v; + var i; + + acc = incrnanmstdev( 1 ); + + data = [ + NaN, // NaN (ignored) -> null + 3.14, // 3.14 -> 0 + NaN, // NaN (ignored) -> 0 + 4.2, // 4.2 -> 0 + NaN, // NaN (ignored) -> 0 + 5.6 // 5.6 -> 0 + ]; + + expected = [ + null, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ]; + + for ( i = 0; i < data.length; i++ ) { + v = acc( data[ i ] ); + if ( expected[i] === null ) { + t.equal( v, null, 'returns null for window '+i ); + } else { + t.equal( v, expected[ i ], 'returns expected value for window '+i ); + } + + // Test accumulator without arguments + if (expected[i] === null) { + t.equal( acc(), null, 'returns correct value for window '+i ); + } else { + t.equal( acc(), expected[ i ], 'returns expected value for window '+i ); + } + } + t.end(); +}); + +tape( 'if provided a NaN, the accumulator function ignores it (known mean, W=1)', function test( t ) { + var expected; + var data; + var acc; + var v; + var i; + + acc = incrnanmstdev( 1, 5.0 ); + + data = [ + NaN, // NaN (ignored) -> null + 3.0, // 3.0 -> 2.0 + NaN, // NaN (ignored) -> 2.0 + 4.0, // 4.0 -> 1.0 + NaN, // NaN (ignored) -> 1.0 + 5.0 // 5.0 -> 0.0 + ]; + + expected = [ + null, + 2.0, + 2.0, + 1.0, + 1.0, + 0.0 + ]; + + for ( i = 0; i < data.length; i++ ) { + v = acc( data[ i ] ); + if ( expected[i] === null ) { + t.equal( v, null, 'returns null for window '+i ); + } else { + t.equal( v, expected[ i ], 'returns expected value for window '+i ); + } + + // Test accumulator without arguments + if (expected[i] === null) { + t.equal( acc(), null, 'returns correct value for window '+i ); + } else { + t.equal( acc(), expected[ i ], 'returns expected value for window '+i ); + } + } + t.end(); +}); + +tape( 'if provided a sequence of NaN values, the accumulator function should continue to ignore them', function test( t ) { + var acc; + var v; + + acc = incrnanmstdev( 3 ); + + v = acc( 2.0 ); + t.equal( v, 0.0, 'returns expected value' ); + + v = acc( NaN ); + t.equal( v, 0.0, 'returns expected value' ); + + v = acc( NaN ); + t.equal( v, 0.0, 'returns expected value' ); + + v = acc( NaN ); + t.equal( v, 0.0, 'returns expected value' ); + + v = acc( 3.0 ); + t.equal( v.toFixed(4), sqrt(0.5).toFixed(4), 'returns expected value' ); + + t.end(); +});