Skip to content

Commit a6f440a

Browse files
committed
feat: refactor variancepn implementation
--- 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: na - 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: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent cb54def commit a6f440a

File tree

5 files changed

+93
-128
lines changed

5 files changed

+93
-128
lines changed

lib/node_modules/@stdlib/stats/base/variancepn/lib/accessors.js

Lines changed: 28 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020

2121
// MODULES //
2222

23+
var gsumpw = require( '@stdlib/blas/ext/base/gsumpw' ).ndarray;
24+
25+
2326
// MAIN //
2427

2528
/**
@@ -37,68 +40,62 @@
3740
* @param {PositiveInteger} N - number of indexed elements
3841
* @param {number} correction - degrees of freedom adjustment
3942
* @param {Object} x - input array object
43+
* @param {Collection} x.data - input array data
4044
* @param {Array<Function>} x.accessors - array element accessors
41-
* @param {integer} stride - stride length
42-
* @param {integer} offset - starting index
45+
* @param {integer} strideX - stride length
46+
* @param {NonNegativeInteger} offsetX - starting index
4347
* @returns {number} variance
4448
*
4549
* @example
4650
* var toAccessorArray = require( '@stdlib/array/base/to-accessor-array' );
4751
* var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
4852
*
49-
* var x = toAccessorArray( [ 1.0, -2.0, 2.0 ] );
53+
* var x = toAccessorArray( [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ] );
5054
*
51-
* var v = variancepn( 3, 1, arraylike2object( x ), 1, 0 );
52-
* // returns ~4.3333
55+
* var v = variancepn( 4, 1, arraylike2object( x ), 2, 1 );
56+
* // returns 6.25
5357
*/
54-
function variancepn( N, correction, x, stride, offset ) {
58+
function variancepn( N, correction, x, strideX, offsetX ) {
5559
var xbuf;
5660
var get;
57-
var sum;
5861
var mu;
59-
var M2;
6062
var ix;
63+
var M2;
6164
var M;
6265
var d;
6366
var n;
6467
var i;
6568

66-
// Cache references to array data:
69+
// Cache reference to array data:
6770
xbuf = x.data;
6871

69-
// Cache references to element accessors:
72+
// Cache a reference to the element accessor:
7073
get = x.accessors[ 0 ];
7174

72-
sum = 0.0;
73-
M2 = 0.0;
74-
M = 0.0;
75-
ix = offset;
76-
n = N - correction;
77-
78-
if ( N <= 0 || n <= 0 ) {
79-
return NaN;
80-
}
81-
if ( N === 1 || stride === 0 ) {
75+
if ( N === 1 || strideX === 0 ) {
8276
return 0.0;
8377
}
8478

85-
// Compute the mean:
86-
for ( i = 0; i < N; i++ ) {
87-
sum += get( xbuf, ix );
88-
ix += stride;
89-
}
90-
mu = sum / N;
79+
// Compute an estimate for the mean:
80+
mu = gsumpw( N, xbuf, strideX, offsetX ) / N;
81+
82+
n = N - correction;
83+
ix = offsetX;
84+
85+
// Compute the variance...
86+
M2 = 0.0;
87+
M = 0.0;
9188

92-
// Compute the variance:
93-
ix = offset;
9489
for ( i = 0; i < N; i++ ) {
9590
d = get( xbuf, ix ) - mu;
9691
M2 += d * d;
9792
M += d;
98-
ix += stride;
93+
ix += strideX;
9994
}
100-
101-
return ( M2 / n ) - ( ( M / N ) * ( M / n ) );
95+
return (M2/n) - ((M/N)*(M/n));
10296
}
10397

98+
99+
// EXPORTS //
100+
104101
module.exports = variancepn;

lib/node_modules/@stdlib/stats/base/variancepn/lib/index.js

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,25 +27,29 @@
2727
* var variancepn = require( '@stdlib/stats/base/variancepn' );
2828
*
2929
* var x = [ 1.0, -2.0, 2.0 ];
30-
* var N = x.length;
3130
*
32-
* var v = variancepn( N, 1, x, 1 );
31+
* var v = variancepn( x.length, 1, x, 1 );
3332
* // returns ~4.3333
3433
*
3534
* @example
36-
* var floor = require( '@stdlib/math/base/special/floor' );
3735
* var variancepn = require( '@stdlib/stats/base/variancepn' );
3836
*
3937
* var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ];
40-
* var N = floor( x.length / 2 );
4138
*
42-
* var v = variancepn.ndarray( N, 1, x, 2, 1 );
39+
* var v = variancepn.ndarray( 4, 1, x, 2, 1 );
4340
* // returns 6.25
4441
*/
4542

4643
// MODULES //
4744

45+
var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
4846
var main = require( './main.js' );
47+
var ndarray = require( './ndarray.js' );
48+
49+
50+
// MAIN //
51+
52+
setReadOnly( main, 'ndarray', ndarray );
4953

5054

5155
// EXPORTS //

lib/node_modules/@stdlib/stats/base/variancepn/lib/main.js

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,41 @@
2020

2121
// MODULES //
2222

23-
var setReadOnly = require( '@stdlib/utils/define-nonenumerable-read-only-property' );
24-
var variancepn = require( './variancepn.js' );
23+
var stride2offset = require( '@stdlib/strided/base/stride2offset' );
2524
var ndarray = require( './ndarray.js' );
2625

2726

2827
// MAIN //
2928

30-
setReadOnly( variancepn, 'ndarray', ndarray );
29+
/**
30+
* Computes the variance of a strided array using a two-pass algorithm.
31+
*
32+
* ## Method
33+
*
34+
* - This implementation uses a two-pass approach, as suggested by Neely (1966).
35+
*
36+
* ## References
37+
*
38+
* - Neely, Peter M. 1966. "Comparison of Several Algorithms for Computation of Means, Standard Deviations and Correlation Coefficients." _Communications of the ACM_ 9 (7). Association for Computing Machinery: 496–99. doi:[10.1145/365719.365958](https://doi.org/10.1145/365719.365958).
39+
* - Schubert, Erich, and Michael Gertz. 2018. "Numerically Stable Parallel Computation of (Co-)Variance." In _Proceedings of the 30th International Conference on Scientific and Statistical Database Management_. New York, NY, USA: Association for Computing Machinery. doi:[10.1145/3221269.3223036](https://doi.org/10.1145/3221269.3223036).
40+
*
41+
* @param {PositiveInteger} N - number of indexed elements
42+
* @param {number} correction - degrees of freedom adjustment
43+
* @param {Object} x - input array object
44+
* @param {Array<Function>} x.accessors - array element accessors
45+
* @param {integer} strideX - stride length
46+
* @param {integer} offsetX - starting index
47+
* @returns {number} variance
48+
*
49+
* @example
50+
* var x = [ 1.0, -2.0, 2.0 ];
51+
*
52+
* var v = variancepn( x.length, 1, x, 1);
53+
* // returns ~4.3333
54+
*/
55+
function variancepn( N, correction, x, strideX ) {
56+
return ndarray( N, correction, x, strideX, stride2offset( N, strideX ) );
57+
}
3158

3259

3360
// EXPORTS //
Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/**
22
* @license Apache-2.0
33
*
4-
* Copyright (c) 2025 The Stdlib Authors.
4+
* Copyright (c) 2020 The Stdlib Authors.
55
*
66
* Licensed under the Apache License, Version 2.0 (the "License");
77
* you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@
2020

2121
// MODULES //
2222

23-
var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
2423
var gsumpw = require( '@stdlib/blas/ext/base/gsumpw' ).ndarray;
24+
var arraylike2object = require( '@stdlib/array/base/arraylike2object' );
2525
var accessors = require( './accessors.js' );
2626

2727

@@ -41,58 +41,56 @@ var accessors = require( './accessors.js' );
4141
*
4242
* @param {PositiveInteger} N - number of indexed elements
4343
* @param {number} correction - degrees of freedom adjustment
44-
* @param {Object} x - input array object
45-
* @param {Array<Function>} x.accessors - array element accessors
46-
* @param {integer} stride - stride length
47-
* @param {integer} offset - starting index
44+
* @param {NumericArray} x - input array
45+
* @param {integer} strideX - stride length
46+
* @param {NonNegativeInteger} offsetX - starting index
4847
* @returns {number} variance
4948
*
5049
* @example
51-
* var x = [ 1.0, -2.0, 2.0 ];
52-
* var N = x.length;
50+
* var x = [ 2.0, 1.0, 2.0, -2.0, -2.0, 2.0, 3.0, 4.0 ];
5351
*
54-
* var v = variancepn( N, 1, x, 1, 0 );
55-
* // returns ~4.3333
52+
* var v = variancepn( 4, 1, x, 2, 1 );
53+
* // returns 6.25
5654
*/
57-
function variancepn( N, correction, x, stride, offset ) {
58-
var xobj;
55+
function variancepn( N, correction, x, strideX, offsetX ) {
5956
var mu;
60-
var M2;
6157
var ix;
58+
var M2;
59+
var o;
6260
var M;
6361
var d;
6462
var n;
6563
var i;
6664

67-
xobj = arraylike2object( x );
68-
69-
if ( xobj.accessorProtocol ) {
70-
return accessors( N, correction, xobj, stride, offset );
71-
}
72-
7365
n = N - correction;
74-
if ( N <= 0 || n <= 0 ) {
66+
if ( N <= 0 || n <= 0.0 ) {
7567
return NaN;
7668
}
77-
if ( N === 1 || stride === 0 ) {
69+
o = arraylike2object( x );
70+
if ( o.accessorProtocol ) {
71+
return accessors( N, correction, o, strideX, offsetX );
72+
}
73+
if ( N === 1 || strideX === 0 ) {
7874
return 0.0;
7975
}
8076

81-
// Compute the mean:
82-
mu = gsumpw( N, x, stride, offset ) / N;
77+
// Compute an estimate for the mean:
78+
mu = gsumpw( N, x, strideX, offsetX ) / N;
8379

84-
// Compute the variance:
85-
ix = offset;
80+
// Compute the variance...
81+
ix = offsetX;
8682
M2 = 0.0;
8783
M = 0.0;
8884
for ( i = 0; i < N; i++ ) {
8985
d = x[ ix ] - mu;
9086
M2 += d * d;
9187
M += d;
92-
ix += stride;
88+
ix += strideX;
9389
}
94-
95-
return ( M2 / n ) - ( ( M / N ) * ( M / n ) );
90+
return (M2/n) - ((M/N)*(M/n));
9691
}
9792

93+
94+
// EXPORTS //
95+
9896
module.exports = variancepn;

lib/node_modules/@stdlib/stats/base/variancepn/lib/variancepn.js

Lines changed: 0 additions & 61 deletions
This file was deleted.

0 commit comments

Comments
 (0)