From 6412e1b483964a36fe3bae48a84573b1ddae383b Mon Sep 17 00:00:00 2001 From: prajjwalbajpai Date: Sun, 9 Mar 2025 17:20:49 +0530 Subject: [PATCH 1/5] Refactor variancetk --- .../base/variancetk/benchmark/benchmark.js | 19 +-- .../variancetk/benchmark/benchmark.ndarray.js | 17 +-- .../stats/base/variancetk/docs/repl.txt | 30 +++-- .../base/variancetk/docs/types/index.d.ts | 17 ++- .../stats/base/variancetk/docs/types/test.ts | 3 + .../stats/base/variancetk/examples/index.js | 14 +-- .../lib/{variancetk.js => accessors.js} | 47 +++++--- .../stats/base/variancetk/lib/index.js | 14 ++- .../@stdlib/stats/base/variancetk/lib/main.js | 23 +++- .../stats/base/variancetk/lib/ndarray.js | 30 +++-- .../test/{test.variancetk.js => test.main.js} | 62 +++++++--- .../base/variancetk/test/test.ndarray.js | 108 ++++++++++++++++-- 12 files changed, 274 insertions(+), 110 deletions(-) rename lib/node_modules/@stdlib/stats/base/variancetk/lib/{variancetk.js => accessors.js} (54%) rename lib/node_modules/@stdlib/stats/base/variancetk/test/{test.variancetk.js => test.main.js} (81%) diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.js b/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.js index e0939f181fbf..a9d37ff8895a 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.js @@ -21,11 +21,18 @@ // MODULES // var bench = require( '@stdlib/bench' ); -var randu = require( '@stdlib/random/base/randu' ); +var uniform = require( '@stdlib/random/array/uniform' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); var pow = require( '@stdlib/math/base/special/pow' ); var pkg = require( './../package.json' ).name; -var variancetk = require( './../lib/variancetk.js' ); +var variancetk = require( './../lib/main.js' ); + + +// VARIABLES // + +var options = { + 'dtype': 'generic' +}; // FUNCTIONS // @@ -38,13 +45,7 @@ var variancetk = require( './../lib/variancetk.js' ); * @returns {Function} benchmark function */ function createBenchmark( len ) { - var x; - var i; - - x = []; - for ( i = 0; i < len; i++ ) { - x.push( ( randu()*20.0 ) - 10.0 ); - } + var x = uniform( len, -10, 10, options ); return benchmark; function benchmark( b ) { diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.ndarray.js b/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.ndarray.js index cc06ca851296..f6dcfaf8ba5f 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.ndarray.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/benchmark/benchmark.ndarray.js @@ -21,13 +21,20 @@ // MODULES // var bench = require( '@stdlib/bench' ); -var randu = require( '@stdlib/random/base/randu' ); +var uniform = require( '@stdlib/random/array/uniform' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); var pow = require( '@stdlib/math/base/special/pow' ); var pkg = require( './../package.json' ).name; var variancetk = require( './../lib/ndarray.js' ); +// VARIABLES // + +var options = { + 'dtype': 'generic' +}; + + // FUNCTIONS // /** @@ -38,13 +45,7 @@ var variancetk = require( './../lib/ndarray.js' ); * @returns {Function} benchmark function */ function createBenchmark( len ) { - var x; - var i; - - x = []; - for ( i = 0; i < len; i++ ) { - x.push( ( randu()*20.0 ) - 10.0 ); - } + var x = uniform( len, -10, 10, options ); return benchmark; function benchmark( b ) { diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/docs/repl.txt b/lib/node_modules/@stdlib/stats/base/variancetk/docs/repl.txt index 75fe4234ae5a..21fe5ee73a7e 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/docs/repl.txt +++ b/lib/node_modules/@stdlib/stats/base/variancetk/docs/repl.txt @@ -1,10 +1,10 @@ -{{alias}}( N, correction, x, stride ) +{{alias}}( N, correction, x, strideX ) Computes the variance of a strided array using a one-pass textbook algorithm. - The `N` and `stride` parameters determine which elements in `x` are accessed - at runtime. + The `N` and stride parameters determine which elements in the strided array + are accessed at runtime. Indexing is relative to the first index. To introduce an offset, use a typed array view. @@ -31,8 +31,8 @@ x: Array|TypedArray Input array. - stride: integer - Index increment. + strideX: integer + Stride length. Returns ------- @@ -46,11 +46,9 @@ > {{alias}}( x.length, 1, x, 1 ) ~4.3333 - // Using `N` and `stride` parameters: + // Using `N` and stride parameters: > x = [ -2.0, 1.0, 1.0, -5.0, 2.0, -1.0 ]; - > var N = {{alias:@stdlib/math/base/special/floor}}( x.length / 2 ); - > var stride = 2; - > {{alias}}( N, 1, x, stride ) + > {{alias}}( 3, 1, x, 2 ) ~4.3333 // Using view offsets: @@ -58,10 +56,11 @@ > var x1 = new {{alias:@stdlib/array/float64}}( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); > N = {{alias:@stdlib/math/base/special/floor}}( x0.length / 2 ); > stride = 2; - > {{alias}}( N, 1, x1, stride ) + > {{alias}}( 3, 1, x1, 2 ) ~4.3333 -{{alias}}.ndarray( N, correction, x, stride, offset ) + +{{alias}}.ndarray( N, correction, x, strideX, offsetX ) Computes the variance of a strided array using a one-pass textbook algorithm and alternative indexing semantics. @@ -89,10 +88,10 @@ x: Array|TypedArray Input array. - stride: integer - Index increment. + strideX: integer + Stride length. - offset: integer + offsetX: integer Starting index. Returns @@ -109,8 +108,7 @@ // Using offset parameter: > var x = [ 1.0, -2.0, 3.0, 2.0, 5.0, -1.0 ]; - > var N = {{alias:@stdlib/math/base/special/floor}}( x.length / 2 ); - > {{alias}}.ndarray( N, 1, x, 2, 1 ) + > {{alias}}.ndarray( 3, 1, x, 2, 1 ) ~4.3333 See Also diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/index.d.ts b/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/index.d.ts index dbe717e14dc0..552d25b8160e 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/index.d.ts +++ b/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/index.d.ts @@ -20,7 +20,12 @@ /// -import { NumericArray } from '@stdlib/types/array'; +import { NumericArray, Collection, AccessorArrayLike } from '@stdlib/types/array'; + +/** +* Input array. +*/ +type InputArray = NumericArray | Collection | AccessorArrayLike; /** * Interface describing `variancetk`. @@ -32,7 +37,7 @@ interface Routine { * @param N - number of indexed elements * @param correction - degrees of freedom adjustment * @param x - input array - * @param stride - stride length + * @param strideX - stride length * @returns variance * * @example @@ -41,7 +46,7 @@ interface Routine { * var v = variancetk( x.length, 1, x, 1 ); * // returns ~4.3333 */ - ( N: number, correction: number, x: NumericArray, stride: number ): number; + ( N: number, correction: number, x: InputArray, strideX: number ): number; /** * Computes the variance of a strided array using a one-pass textbook algorithm and alternative indexing semantics. @@ -49,8 +54,8 @@ interface Routine { * @param N - number of indexed elements * @param correction - degrees of freedom adjustment * @param x - input array - * @param stride - stride length - * @param offset - starting index + * @param strideX - stride length + * @param offsetX - starting index * @returns variance * * @example @@ -68,7 +73,7 @@ interface Routine { * @param N - number of indexed elements * @param correction - degrees of freedom adjustment * @param x - input array -* @param stride - stride length +* @param strideX - stride length * @returns variance * * @example diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/test.ts b/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/test.ts index 35734d2e48e0..8a654deb2d90 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/test.ts +++ b/lib/node_modules/@stdlib/stats/base/variancetk/docs/types/test.ts @@ -16,6 +16,7 @@ * limitations under the License. */ +import AccessorArray = require( '@stdlib/array/base/accessor' ); import variancetk = require( './index' ); @@ -26,6 +27,7 @@ import variancetk = require( './index' ); const x = new Float64Array( 10 ); variancetk( x.length, 1, x, 1 ); // $ExpectType number + variancetk( x.length, 1, new AccessorArray( x ), 1 ); // $ExpectType number } // The compiler throws an error if the function is provided a first argument which is not a number... @@ -101,6 +103,7 @@ import variancetk = require( './index' ); const x = new Float64Array( 10 ); variancetk.ndarray( x.length, 1, x, 1, 0 ); // $ExpectType number + variancetk.ndarray( x.length, 1, new AccessorArray( x ), 1, 0 ); // $ExpectType number } // The compiler throws an error if the `ndarray` method is provided a first argument which is not a number... diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/examples/index.js b/lib/node_modules/@stdlib/stats/base/variancetk/examples/index.js index 5ad74c6fb8ae..50517c278915 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/examples/index.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/examples/index.js @@ -18,18 +18,12 @@ 'use strict'; -var randu = require( '@stdlib/random/base/randu' ); -var round = require( '@stdlib/math/base/special/round' ); -var Float64Array = require( '@stdlib/array/float64' ); +var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); var variancetk = require( './../lib' ); -var x; -var i; - -x = new Float64Array( 10 ); -for ( i = 0; i < x.length; i++ ) { - x[ i ] = round( (randu()*100.0) - 50.0 ); -} +var x = discreteUniform( 10, -50, 50, { + 'dtype': 'float64' +}); console.log( x ); var v = variancetk( x.length, 1, x, 1 ); diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/variancetk.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js similarity index 54% rename from lib/node_modules/@stdlib/stats/base/variancetk/lib/variancetk.js rename to lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js index a8e405c071eb..6927e4a28341 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/variancetk.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js @@ -1,7 +1,7 @@ /** * @license Apache-2.0 * -* Copyright (c) 2020 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. @@ -23,19 +23,28 @@ /** * Computes the variance of a strided array using a one-pass textbook algorithm. * +* @private * @param {PositiveInteger} N - number of indexed elements * @param {number} correction - degrees of freedom adjustment -* @param {NumericArray} x - input array -* @param {integer} stride - stride length +* @param {Object} x - input array object +* @param {Collection} x.data - input array data +* @param {Array} x.accessors - array element accessors +* @param {integer} strideX - stride length +* @param {NonNegativeInteger} offsetX - starting index * @returns {number} variance * * @example -* var x = [ 1.0, -2.0, 2.0 ]; +* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); +* var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); * -* var v = variancetk( x.length, 1, x, 1 ); +* var x = toAccessorArray( [ 1.0, -2.0, 2.0 ] ); +* +* var v = variancetk( x.length, 1, arraylike2object( x ), 1, 1 ); * // returns ~4.3333 */ -function variancetk( N, correction, x, stride ) { +function variancetk( N, correction, x, strideX, offsetX ) { + var xbuf; + var get; var S2; var ix; var S; @@ -44,24 +53,24 @@ function variancetk( N, correction, x, stride ) { var i; n = N - correction; - if ( N <= 0 || n <= 0.0 ) { - return NaN; - } - if ( N === 1 || stride === 0 ) { - return 0.0; - } - if ( stride < 0 ) { - ix = (1-N) * stride; - } else { - ix = 0; + + // Cache reference to array data: + xbuf = x.data; + + // Cache a reference to the element accessor: + get = x.accessors[ 0 ]; + + if ( N === 1 || strideX === 0 ) { + return get( xbuf, offsetX ); } - S2 = 0.0; + ix = offsetX; + S2 = get( xbuf, ix ); S = 0.0; for ( i = 0; i < N; i++ ) { - v = x[ ix ]; + v = get( xbuf, ix ); S2 += v * v; S += v; - ix += stride; + ix += strideX; } return (S2 - ((S/N)*S)) / n; } diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/index.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/index.js index 3607e87814a5..c7393ac857a5 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/index.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/index.js @@ -27,25 +27,29 @@ * var variancetk = require( '@stdlib/stats/base/variancetk' ); * * var x = [ 1.0, -2.0, 2.0 ]; -* var N = x.length; * -* var v = variancetk( N, 1, x, 1 ); +* var v = variancetk( x.length, 1, x, 1 ); * // returns ~4.3333 * * @example -* var floor = require( '@stdlib/math/base/special/floor' ); * var variancetk = require( '@stdlib/stats/base/variancetk' ); * * var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ]; -* var N = floor( x.length / 2 ); * -* var v = variancetk.ndarray( N, 1, x, 2, 1 ); +* var v = variancetk.ndarray( 4, 1, x, 2, 1 ); * // returns 6.25 */ // MODULES // +var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); var main = require( './main.js' ); +var ndarray = require( './ndarray.js' ); + + +// MAIN // + +setReadOnly( main, 'ndarray', ndarray ); // EXPORTS // diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js index 024e93aff02d..e0786697d4ca 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js @@ -20,14 +20,31 @@ // MODULES // -var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' ); -var variancetk = require( './variancetk.js' ); +var stride2offset = require( '@stdlib/strided/base/stride2offset' ); var ndarray = require( './ndarray.js' ); // MAIN // -setReadOnly( variancetk, 'ndarray', ndarray ); +/** +* Computes the variance of a strided array. +* +* @param {PositiveInteger} N - number of indexed elements +* @param {PositiveInteger} correction - degrees of freedom adjustment +* @param {NumericArray} x - input array +* @param {integer} strideX - stride length +* @returns {number} minimum value +* +* @example +* var x = [ 1.0, -2.0, 2.0 ]; +* var N = x.length; +* +* var v = variancetk( N, 1, x, 1 ); +* // returns +*/ +function variancetk( N, correction, x, strideX ) { + return ndarray( N, correction, x, strideX, stride2offset( N, strideX ) ); +} // EXPORTS // diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js index 90f1bb04897f..ac44b892dce4 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js @@ -18,6 +18,12 @@ 'use strict'; +// MODULES // + +var arraylike2object = require( '@stdlib/array/base/arraylike2object' ); +var accessors = require( './accessors.js' ); + + // MAIN // /** @@ -26,22 +32,20 @@ * @param {PositiveInteger} N - number of indexed elements * @param {number} correction - degrees of freedom adjustment * @param {NumericArray} x - input array -* @param {integer} stride - stride length -* @param {NonNegativeInteger} offset - starting index +* @param {integer} strideX - stride length +* @param {NonNegativeInteger} offsetX - starting index * @returns {number} variance * * @example -* var floor = require( '@stdlib/math/base/special/floor' ); -* * var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ]; -* var N = floor( x.length / 2 ); * -* var v = variancetk( N, 1, x, 2, 1 ); +* var v = variancetk( 4, 1, x, 2, 1 ); * // returns 6.25 */ -function variancetk( N, correction, x, stride, offset ) { +function variancetk( N, correction, x, strideX, offsetX ) { var S2; var ix; + var o; var S; var v; var n; @@ -51,17 +55,21 @@ function variancetk( N, correction, x, stride, offset ) { if ( N <= 0 || n <= 0.0 ) { return NaN; } - if ( N === 1 || stride === 0 ) { - return 0.0; + o = arraylike2object( x ); + if ( o.accessorProtocol ) { + return accessors( N, o, strideX, offsetX ); + } + if ( N === 1 || strideX === 0 ) { + return x[ offsetX ]; } - ix = offset; + ix = offsetX; S2 = 0.0; S = 0.0; for ( i = 0; i < N; i++ ) { v = x[ ix ]; S2 += v * v; S += v; - ix += stride; + ix += strideX; } return (S2 - ((S/N)*S)) / n; } diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.variancetk.js b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js similarity index 81% rename from lib/node_modules/@stdlib/stats/base/variancetk/test/test.variancetk.js rename to lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js index 229197f46ff8..0c78ee435c82 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.variancetk.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js @@ -21,10 +21,10 @@ // MODULES // var tape = require( 'tape' ); -var floor = require( '@stdlib/math/base/special/floor' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var Float64Array = require( '@stdlib/array/float64' ); -var variancetk = require( './../lib/variancetk.js' ); +var variancetk = require( './../lib/main.js' ); // TESTS // @@ -59,12 +59,12 @@ tape( 'the function calculates the population variance of a strided array', func t.end(); }); -tape( 'the function calculates the sample variance of a strided array', function test( t ) { +tape( 'the function calculates the sample variance of a strided array (accessors)', function test( t ) { var x; var v; x = [ 1.0, -2.0, -4.0, 5.0, 0.0, 3.0 ]; - v = variancetk( x.length, 1, x, 1 ); + v = variancetk( x.length, 1, toAccessorArray( x ), 1 ); t.strictEqual( v, 53.5/(x.length-1), 'returns expected value' ); x = [ -4.0, -4.0 ]; @@ -121,7 +121,6 @@ tape( 'if provided a `correction` parameter yielding `N-correction` less than or }); tape( 'the function supports a `stride` parameter', function test( t ) { - var N; var x; var v; @@ -136,15 +135,34 @@ tape( 'the function supports a `stride` parameter', function test( t ) { 2.0 ]; - N = floor( x.length / 2 ); - v = variancetk( N, 1, x, 2 ); + v = variancetk( 4, 1, x, 2 ); + + t.strictEqual( v, 6.25, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a `stride` parameter (accessors)', function test( t ) { + var x; + var v; + + x = [ + 1.0, // 0 + 2.0, + 2.0, // 1 + -7.0, + -2.0, // 2 + 3.0, + 4.0, // 3 + 2.0 + ]; + + v = variancetk( 4, 1, toAccessorArray( x ), 2 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); }); tape( 'the function supports a negative `stride` parameter', function test( t ) { - var N; var x; var v; @@ -159,8 +177,28 @@ tape( 'the function supports a negative `stride` parameter', function test( t ) 2.0 ]; - N = floor( x.length / 2 ); - v = variancetk( N, 1, x, -2 ); + v = variancetk( 4, 1, x, -2 ); + + t.strictEqual( v, 6.25, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a negative `stride` parameter (accessors)', function test( t ) { + var x; + var v; + + x = [ + 1.0, // 3 + 2.0, + 2.0, // 2 + -7.0, + -2.0, // 1 + 3.0, + 4.0, // 0 + 2.0 + ]; + + v = variancetk( 4, 1, toAccessorArray( x ), -2 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); @@ -181,7 +219,6 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns `0`', tape( 'the function supports view offsets', function test( t ) { var x0; var x1; - var N; var v; x0 = new Float64Array([ @@ -197,9 +234,8 @@ tape( 'the function supports view offsets', function test( t ) { ]); x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element - N = floor(x1.length / 2); - v = variancetk( N, 1, x1, 2 ); + v = variancetk( 4, 1, x1, 2 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js index fa2e93cce0bd..d2aa02592f05 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js @@ -21,8 +21,8 @@ // MODULES // var tape = require( 'tape' ); -var floor = require( '@stdlib/math/base/special/floor' ); var isnan = require( '@stdlib/math/base/assert/is-nan' ); +var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' ); var variancetk = require( './../lib/ndarray.js' ); @@ -77,6 +77,25 @@ tape( 'the function calculates the sample variance of a strided array', function t.end(); }); +tape( 'the function calculates the sample variance of a strided array (accessors)', function test( t ) { + var x; + var v; + + x = [ 1.0, -2.0, -4.0, 5.0, 0.0, 3.0 ]; + v = variancetk( x.length, 1, toAccessorArray( x ), 1, 0 ); + t.strictEqual( v, 53.5/(x.length-1), 'returns expected value' ); + + x = [ -4.0, -4.0 ]; + v = variancetk( x.length, 1, toAccessorArray( x ), 1, 0 ); + t.strictEqual( v, 0.0, 'returns expected value' ); + + x = [ NaN, 4.0 ]; + v = variancetk( x.length, 1, toAccessorArray( x ), 1, 0 ); + t.strictEqual( isnan( v ), true, 'returns expected value' ); + + t.end(); +}); + tape( 'if provided an `N` parameter less than or equal to `0`, the function returns `NaN`', function test( t ) { var x; var v; @@ -120,7 +139,6 @@ tape( 'if provided a `correction` parameter yielding `N-correction` less than or }); tape( 'the function supports a `stride` parameter', function test( t ) { - var N; var x; var v; @@ -135,15 +153,34 @@ tape( 'the function supports a `stride` parameter', function test( t ) { 2.0 ]; - N = floor( x.length / 2 ); - v = variancetk( N, 1, x, 2, 0 ); + v = variancetk( 4, 1, x, 2, 0 ); + + t.strictEqual( v, 6.25, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a `stride` parameter (accessors)', function test( t ) { + var x; + var v; + + x = [ + 1.0, // 0 + 2.0, + 2.0, // 1 + -7.0, + -2.0, // 2 + 3.0, + 4.0, // 3 + 2.0 + ]; + + v = variancetk( 4, 1, toAccessorArray( x ), 2, 0 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); }); tape( 'the function supports a negative `stride` parameter', function test( t ) { - var N; var x; var v; @@ -158,8 +195,28 @@ tape( 'the function supports a negative `stride` parameter', function test( t ) 2.0 ]; - N = floor( x.length / 2 ); - v = variancetk( N, 1, x, -2, 6 ); + v = variancetk( 4, 1, x, -2, 6 ); + + t.strictEqual( v, 6.25, 'returns expected value' ); + t.end(); +}); + +tape( 'the function supports a negative `stride` parameter (accessors)', function test( t ) { + var x; + var v; + + x = [ + 1.0, // 3 + 2.0, + 2.0, // 2 + -7.0, + -2.0, // 1 + 3.0, + 4.0, // 0 + 2.0 + ]; + + v = variancetk( 4, 1, toAccessorArray( x ), -2, 6 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); @@ -177,8 +234,19 @@ tape( 'if provided a `stride` parameter equal to `0`, the function returns `0`', t.end(); }); +tape( 'if provided a `stride` parameter equal to `0`, the function returns `0` (accessors)', function test( t ) { + var x; + var v; + + x = [ 1.0, -2.0, -4.0, 5.0, 3.0 ]; + + v = variancetk( x.length, 1, toAccessorArray( x ), 0, 0 ); + t.strictEqual( v, 0.0, 'returns expected value' ); + + t.end(); +}); + tape( 'the function supports an `offset` parameter', function test( t ) { - var N; var x; var v; @@ -192,9 +260,29 @@ tape( 'the function supports an `offset` parameter', function test( t ) { 3.0, 4.0 // 3 ]; - N = floor( x.length / 2 ); - v = variancetk( N, 1, x, 2, 1 ); + v = variancetk( 4, 1, x, 2, 1 ); + t.strictEqual( v, 6.25, 'returns expected value' ); + + t.end(); +}); + +tape( 'the function supports an `offset` parameter (accessors)', function test( t ) { + var x; + var v; + + x = [ + 2.0, + 1.0, // 0 + 2.0, + -2.0, // 1 + -2.0, + 2.0, // 2 + 3.0, + 4.0 // 3 + ]; + + v = variancetk( 4, 1, toAccessorArray( x ), 2, 1 ); t.strictEqual( v, 6.25, 'returns expected value' ); t.end(); From ad2fa4dd8d56fc9ff29084ee19a1f680f0fd1510 Mon Sep 17 00:00:00 2001 From: prajjwalbajpai Date: Sun, 9 Mar 2025 17:46:39 +0530 Subject: [PATCH 2/5] accessor.js example offset to 0 --- lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js index 6927e4a28341..b10d9d48ab15 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js @@ -39,7 +39,7 @@ * * var x = toAccessorArray( [ 1.0, -2.0, 2.0 ] ); * -* var v = variancetk( x.length, 1, arraylike2object( x ), 1, 1 ); +* var v = variancetk( x.length, 1, arraylike2object( x ), 1, 0 ); * // returns ~4.3333 */ function variancetk( N, correction, x, strideX, offsetX ) { From 6f0c01c427b6d020030ef5891990b37eb326af0f Mon Sep 17 00:00:00 2001 From: prajjwalbajpai Date: Sun, 9 Mar 2025 18:19:57 +0530 Subject: [PATCH 3/5] updated readme --- .../@stdlib/stats/base/variancetk/README.md | 44 +++++++------------ .../stats/base/variancetk/lib/accessors.js | 5 ++- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/README.md b/lib/node_modules/@stdlib/stats/base/variancetk/README.md index 6d7e2c24e243..e7c67690eed6 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/README.md +++ b/lib/node_modules/@stdlib/stats/base/variancetk/README.md @@ -98,7 +98,7 @@ The use of the term `n-1` is commonly referred to as Bessel's correction. Note, var variancetk = require( '@stdlib/stats/base/variancetk' ); ``` -#### variancetk( N, correction, x, stride ) +#### variancetk( N, correction, x, strideX ) Computes the [variance][variance] of a strided array `x` using a one-pass textbook algorithm. @@ -114,17 +114,14 @@ The function has the following parameters: - **N**: number of indexed elements. - **correction**: degrees of freedom adjustment. Setting this parameter to a value other than `0` has the effect of adjusting the divisor during the calculation of the [variance][variance] according to `N-c` where `c` corresponds to the provided degrees of freedom adjustment. When computing the [variance][variance] of a population, setting this parameter to `0` is the standard choice (i.e., the provided array contains data constituting an entire population). When computing the unbiased sample [variance][variance], setting this parameter to `1` is the standard choice (i.e., the provided array contains data sampled from a larger population; this is commonly referred to as Bessel's correction). - **x**: input [`Array`][mdn-array] or [`typed array`][mdn-typed-array]. -- **stride**: index increment for `x`. +- **strideX**: stride length for `x`. -The `N` and `stride` parameters determine which elements in `x` are accessed at runtime. For example, to compute the [variance][variance] of every other element in `x`, +The `N` and stride parameters determine which elements in the strided array are accessed at runtime. For example, to compute the [variance][variance] of every other element in `x`, ```javascript -var floor = require( '@stdlib/math/base/special/floor' ); - var x = [ 1.0, 2.0, 2.0, -7.0, -2.0, 3.0, 4.0, 2.0 ]; -var N = floor( x.length / 2 ); -var v = variancetk( N, 1, x, 2 ); +var v = variancetk( 4, 1, x, 2 ); // returns 6.25 ``` @@ -134,18 +131,15 @@ Note that indexing is relative to the first index. To introduce an offset, use [ ```javascript var Float64Array = require( '@stdlib/array/float64' ); -var floor = require( '@stdlib/math/base/special/floor' ); var x0 = new Float64Array( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] ); var x1 = new Float64Array( x0.buffer, x0.BYTES_PER_ELEMENT*1 ); // start at 2nd element -var N = floor( x0.length / 2 ); - -var v = variancetk( N, 1, x1, 2 ); +var v = variancetk( 4, 1, x1, 2 ); // returns 6.25 ``` -#### variancetk.ndarray( N, correction, x, stride, offset ) +#### variancetk.ndarray( N, correction, x, strideX, offsetX ) Computes the [variance][variance] of a strided array using a one-pass textbook algorithm and alternative indexing semantics. @@ -158,17 +152,14 @@ var v = variancetk.ndarray( x.length, 1, x, 1, 0 ); The function has the following additional parameters: -- **offset**: starting index for `x`. +- **offsetX**: starting index for `x`. -While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying `buffer`, the `offset` parameter supports indexing semantics based on a starting index. For example, to calculate the [variance][variance] for every other value in `x` starting from the second value +While [`typed array`][mdn-typed-array] views mandate a view offset based on the underlying buffer, the offset parameter supports indexing semantics based on a starting index. For example, to calculate the [variance][variance] for every element value in the strided array starting from the second element ```javascript -var floor = require( '@stdlib/math/base/special/floor' ); - var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ]; -var N = floor( x.length / 2 ); -var v = variancetk.ndarray( N, 1, x, 2, 1 ); +var v = variancetk.ndarray( 4, 1, x, 2, 1 ); // returns 6.25 ``` @@ -181,6 +172,7 @@ var v = variancetk.ndarray( N, 1, x, 2, 1 ); ## Notes - If `N <= 0`, both functions return `NaN`. +- Both functions support array-like objects having getter and setter accessors for array element access (e.g., [`@stdlib/array/base/accessor`][@stdlib/array/base/accessor]). - If `N - c` is less than or equal to `0` (where `c` corresponds to the provided degrees of freedom adjustment), both functions return `NaN`. - Some caution should be exercised when using the one-pass textbook algorithm. Literature overwhelmingly discourages the algorithm's use for two reasons: 1) the lack of safeguards against underflow and overflow and 2) the risk of catastrophic cancellation when subtracting the two sums if the sums are large and the variance small. These concerns have merit; however, the one-pass textbook algorithm should not be dismissed outright. For data distributions with a moderately large standard deviation to mean ratio (i.e., **coefficient of variation**), the one-pass textbook algorithm may be acceptable, especially when performance is paramount and some precision loss is acceptable (including a risk of returning a negative variance due to floating-point rounding errors!). In short, no single "best" algorithm for computing the variance exists. The "best" algorithm depends on the underlying data distribution, your performance requirements, and your minimum precision requirements. When evaluating which algorithm to use, consider the relative pros and cons, and choose the algorithm which best serves your needs. - Depending on the environment, the typed versions ([`dvariancetk`][@stdlib/stats/base/dvariancetk], [`svariancetk`][@stdlib/stats/base/svariancetk], etc.) are likely to be significantly more performant. @@ -196,18 +188,12 @@ var v = variancetk.ndarray( N, 1, x, 2, 1 ); ```javascript -var randu = require( '@stdlib/random/base/randu' ); -var round = require( '@stdlib/math/base/special/round' ); -var Float64Array = require( '@stdlib/array/float64' ); +var discreteUniform = require( '@stdlib/random/array/discrete-uniform' ); var variancetk = require( '@stdlib/stats/base/variancetk' ); -var x; -var i; - -x = new Float64Array( 10 ); -for ( i = 0; i < x.length; i++ ) { - x[ i ] = round( (randu()*100.0) - 50.0 ); -} +var x = discreteUniform( 10, -50, 50, { + 'dtype': 'float64' +}); console.log( x ); var v = variancetk( x.length, 1, x, 1 ); @@ -257,6 +243,8 @@ console.log( v ); [mdn-typed-array]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray +[@stdlib/array/base/accessor]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/array/base/accessor + [@stdlib/stats/base/svariancetk]: https://github.com/stdlib-js/stdlib/tree/develop/lib/node_modules/%40stdlib/stats/base/svariancetk [@ling:1974a]: https://doi.org/10.2307/2286154 diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js index b10d9d48ab15..b87f53931c13 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/accessors.js @@ -53,6 +53,9 @@ function variancetk( N, correction, x, strideX, offsetX ) { var i; n = N - correction; + if ( N <= 0 || n <= 0.0 ) { + return NaN; + } // Cache reference to array data: xbuf = x.data; @@ -64,7 +67,7 @@ function variancetk( N, correction, x, strideX, offsetX ) { return get( xbuf, offsetX ); } ix = offsetX; - S2 = get( xbuf, ix ); + S2 = 0.0; S = 0.0; for ( i = 0; i < N; i++ ) { v = get( xbuf, ix ); From 75983243b1c8db50b07a9ca9d2480f3b2a27a215 Mon Sep 17 00:00:00 2001 From: prajjwalbajpai Date: Sun, 9 Mar 2025 19:44:18 +0530 Subject: [PATCH 4/5] fixed issues --- .../@stdlib/stats/base/variancetk/lib/main.js | 4 ++-- .../@stdlib/stats/base/variancetk/lib/ndarray.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js index e0786697d4ca..8b1e9aa89281 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/main.js @@ -33,14 +33,14 @@ var ndarray = require( './ndarray.js' ); * @param {PositiveInteger} correction - degrees of freedom adjustment * @param {NumericArray} x - input array * @param {integer} strideX - stride length -* @returns {number} minimum value +* @returns {number} variance * * @example * var x = [ 1.0, -2.0, 2.0 ]; * var N = x.length; * * var v = variancetk( N, 1, x, 1 ); -* // returns +* // returns ~4.3333 */ function variancetk( N, correction, x, strideX ) { return ndarray( N, correction, x, strideX, stride2offset( N, strideX ) ); diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js b/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js index ac44b892dce4..0d7439b12c84 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/lib/ndarray.js @@ -56,11 +56,11 @@ function variancetk( N, correction, x, strideX, offsetX ) { return NaN; } o = arraylike2object( x ); - if ( o.accessorProtocol ) { - return accessors( N, o, strideX, offsetX ); - } if ( N === 1 || strideX === 0 ) { - return x[ offsetX ]; + return 0.0; + } + if ( o.accessorProtocol ) { + return accessors( N, correction, o, strideX, offsetX ); } ix = offsetX; S2 = 0.0; From 2d2e97dab00bcee0b4072b1311125b3390257d85 Mon Sep 17 00:00:00 2001 From: prajjwalbajpai Date: Thu, 13 Mar 2025 00:45:19 +0530 Subject: [PATCH 5/5] chore: fixed test cases for variancetk refactoring Added accessor tests for refactoring variancetk Fixes: #5690 Co-authored-by: Prajjwal Bajpai --- 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: na - 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: 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: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed --- --- .../stats/base/variancetk/test/test.main.js | 4 ++-- .../base/variancetk/test/test.ndarray.js | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js index 0c78ee435c82..b2bbc12157a6 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.main.js @@ -68,11 +68,11 @@ tape( 'the function calculates the sample variance of a strided array (accessors t.strictEqual( v, 53.5/(x.length-1), 'returns expected value' ); x = [ -4.0, -4.0 ]; - v = variancetk( x.length, 1, x, 1 ); + v = variancetk( x.length, 1, toAccessorArray( x ), 1 ); t.strictEqual( v, 0.0, 'returns expected value' ); x = [ NaN, 4.0 ]; - v = variancetk( x.length, 1, x, 1 ); + v = variancetk( x.length, 1, toAccessorArray( x ), 1 ); t.strictEqual( isnan( v ), true, 'returns expected value' ); t.end(); diff --git a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js index d2aa02592f05..cd1527fa6ea8 100644 --- a/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js +++ b/lib/node_modules/@stdlib/stats/base/variancetk/test/test.ndarray.js @@ -58,6 +58,25 @@ tape( 'the function calculates the population variance of a strided array', func t.end(); }); +tape( 'the function calculates the population variance of a strided array (accessors)', function test( t ) { + var x; + var v; + + x = [ 1.0, -2.0, -4.0, 5.0, 0.0, 3.0 ]; + v = variancetk( x.length, 0, toAccessorArray( x ), 1, 0 ); + t.strictEqual( v, 53.5/x.length, 'returns expected value' ); + + x = [ -4.0, -4.0 ]; + v = variancetk( x.length, 0, toAccessorArray( x ), 1, 0 ); + t.strictEqual( v, 0.0, 'returns expected value' ); + + x = [ NaN, 4.0 ]; + v = variancetk( x.length, 0, toAccessorArray( x ), 1, 0 ); + t.strictEqual( isnan( v ), true, 'returns expected value' ); + + t.end(); +}); + tape( 'the function calculates the sample variance of a strided array', function test( t ) { var x; var v;