Skip to content

Commit 37f1b4d

Browse files
committed
feat: add the JS test, benchmarks, examples
--- 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: 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: na - task: lint_typescript_tests status: na - task: lint_license_headers status: passed ---
1 parent 1b4cbcf commit 37f1b4d

File tree

3 files changed

+346
-0
lines changed

3 files changed

+346
-0
lines changed
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var bench = require( '@stdlib/bench' );
24+
var Float64Array = require( '@stdlib/array/float64' );
25+
var uniform = require( '@stdlib/random/base/uniform' );
26+
var pkg = require( './../package.json' ).name;
27+
var incrwstdev = require( './../lib' );
28+
29+
30+
// MAIN //
31+
32+
bench( pkg, function benchmark( b ) {
33+
var f;
34+
var i;
35+
b.tic();
36+
for ( i = 0; i < b.iterations; i++ ) {
37+
f = incrwstdev();
38+
if ( typeof f !== 'function' ) {
39+
b.fail( 'should return a function' );
40+
}
41+
}
42+
b.toc();
43+
if ( typeof f !== 'function' ) {
44+
b.fail( 'should return a function' );
45+
}
46+
b.pass( 'benchmark finished' );
47+
b.end();
48+
});
49+
50+
bench( pkg+'::accumulator', function benchmark( b ) {
51+
var acc;
52+
var len;
53+
var x;
54+
var v;
55+
var i;
56+
57+
acc = incrwstdev();
58+
len = 100;
59+
x = new Float64Array( len );
60+
for ( i = 0; i < len; i++ ) {
61+
x[ i ] = uniform( 0.0, 1.0 );
62+
}
63+
64+
b.tic();
65+
for ( i = 0; i < b.iterations; i++ ) {
66+
v = acc( x[ i % len ], 1.0 );
67+
if ( v !== v ) {
68+
b.fail( 'should not return NaN' );
69+
}
70+
}
71+
b.toc();
72+
if ( v !== v ) {
73+
b.fail( 'should not return NaN' );
74+
}
75+
b.pass( 'benchmark finished' );
76+
b.end();
77+
});
78+
79+
bench( pkg+'::accumulator,known_mean', function benchmark( b ) {
80+
var acc;
81+
var len;
82+
var x;
83+
var v;
84+
var i;
85+
86+
acc = incrwstdev( 3.0 );
87+
len = 100;
88+
x = new Float64Array( len );
89+
for ( i = 0; i < len; i++ ) {
90+
x[ i ] = uniform( 0.0, 1.0 );
91+
}
92+
93+
b.tic();
94+
for ( i = 0; i < b.iterations; i++ ) {
95+
v = acc( x[ i % len ], 1.0 );
96+
if ( v !== v ) {
97+
b.fail( 'should not return NaN' );
98+
}
99+
}
100+
b.toc();
101+
if ( v !== v ) {
102+
b.fail( 'should not return NaN' );
103+
}
104+
b.pass( 'benchmark finished' );
105+
b.end();
106+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var uniform = require( '@stdlib/random/base/uniform' );
22+
var incrwstdev = require( './../lib' );
23+
24+
var accumulator;
25+
var stdev;
26+
var x;
27+
var w;
28+
var i;
29+
30+
// Initialize an accumulator:
31+
accumulator = incrwstdev();
32+
33+
// For each simulated datum, update the weighted standard deviation...
34+
console.log( '\nValue\tWeight\tWeighted Standard Deviation\n' );
35+
for ( i = 0; i < 100; i++ ) {
36+
x = uniform( 0.0, 100.0 );
37+
w = uniform( 0.0, 100.0 );
38+
stdev = accumulator( x, w );
39+
console.log( '%d\t%d\t%d', x.toFixed( 4 ), w.toFixed( 4 ), stdev.toFixed( 4 ) );
40+
}
41+
console.log( '\nFinal weighted standard deviation: %d\n', accumulator() );
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2025 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// MODULES //
22+
23+
var tape = require( 'tape' );
24+
var EPS = require( '@stdlib/constants/float64/eps' );
25+
var abs = require( '@stdlib/math/base/special/abs' );
26+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
27+
var sqrt = require( '@stdlib/math/base/special/sqrt' );
28+
var incrwstdev = require( './../lib' );
29+
30+
31+
// TESTS //
32+
33+
tape( 'main export is a function', function test( t ) {
34+
t.ok( true, __filename );
35+
t.strictEqual( typeof incrwstdev, 'function', 'main export is a function' );
36+
t.end();
37+
});
38+
39+
tape( 'the function returns an accumulator function', function test( t ) {
40+
t.equal( typeof incrwstdev(), 'function', 'returns a function' );
41+
t.end();
42+
});
43+
44+
tape( 'the function returns an accumulator function (known mean)', function test( t ) {
45+
t.equal( typeof incrwstdev( 3.0 ), 'function', 'returns a function' );
46+
t.end();
47+
});
48+
49+
tape( 'the function throws an error if provided a non-numeric value', function test( t ) {
50+
var values;
51+
var i;
52+
53+
values = [
54+
'5',
55+
true,
56+
false,
57+
null,
58+
void 0,
59+
[],
60+
{},
61+
function noop() {}
62+
];
63+
for ( i = 0; i < values.length; i++ ) {
64+
t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
65+
}
66+
t.end();
67+
68+
function badValue( value ) {
69+
return function badValue() {
70+
incrwstdev( value );
71+
};
72+
}
73+
});
74+
75+
tape( 'the weighted corrected sample standard deviation is `null` until at least 1 datum has been provided (known mean)', function test( t ) {
76+
var acc;
77+
var s;
78+
79+
acc = incrwstdev( 3.0 );
80+
81+
s = acc();
82+
t.equal( s, null, 'returns null' );
83+
84+
s = acc( 3.0 );
85+
t.notEqual( s, null, 'does not return null' );
86+
87+
s = acc();
88+
t.notEqual( s, null, 'does not return null' );
89+
90+
t.end();
91+
});
92+
93+
tape( 'the accumulator function incrementally computes a weighted standard deviation', function test( t ) {
94+
var wMeanPrev;
95+
var expected;
96+
var wVarSum;
97+
var actual;
98+
var delta;
99+
var dataX;
100+
var dataW;
101+
var xwSum;
102+
var wMean;
103+
var wSum;
104+
var acc;
105+
var tol;
106+
var N;
107+
var x;
108+
var w;
109+
var i;
110+
111+
dataX = [ 2.0, 3.0, 2.0, 4.0, 3.0, 4.0 ];
112+
dataW = [ 1.0, 2.0, 0.1, 1.8, 9.9, 3.6 ];
113+
N = dataX.length;
114+
115+
acc = incrwstdev();
116+
117+
wMeanPrev = 0.0;
118+
wVarSum = 0.0;
119+
xwSum = 0.0;
120+
wMean = 0.0;
121+
wSum = 0.0;
122+
for ( i = 0; i < N; i++ ) {
123+
x = dataX[ i ];
124+
w = dataW[ i ];
125+
xwSum += x * w;
126+
wSum += w;
127+
wMean = xwSum / wSum;
128+
wVarSum += w * (x - wMeanPrev) * (x - wMean);
129+
wMeanPrev = wMean;
130+
expected = sqrt( wVarSum / wSum );
131+
actual = acc( x, w );
132+
delta = abs( actual - expected );
133+
tol = EPS * abs( expected );
134+
t.ok( delta <= tol, 'within tolerance. x: ' + x + '. Value: ' + actual + '. Expected: ' + expected + '. Tolerance: ' + tol + '.' );
135+
}
136+
t.end();
137+
});
138+
139+
tape( 'if not provided arguments, the accumulator function returns the current weighted standard deviation', function test( t ) {
140+
var expected;
141+
var actual;
142+
var delta;
143+
var dataX;
144+
var dataW;
145+
var tol;
146+
var acc;
147+
var i;
148+
149+
expected = 2.0;
150+
dataX = [ 2.0, 4.0, 6.0, 8.0 ];
151+
dataW = [ 1.0, 2.0, 3.0, 4.0 ];
152+
acc = incrwstdev();
153+
for ( i = 0; i < dataX.length; i++ ) {
154+
acc( dataX[ i ], dataW[ i ] );
155+
}
156+
actual = acc();
157+
delta = abs( actual - expected );
158+
tol = EPS * abs( expected );
159+
t.ok( delta <= tol, 'returns the current accumulated standard deviation within tolerance' );
160+
t.end();
161+
});
162+
163+
tape( 'if not provided an input value, the accumulator function returns the current weighted corrected sample standard deviation (known mean)', function test( t ) {
164+
var dataX;
165+
var dataW;
166+
var acc;
167+
var i;
168+
169+
dataX = [ 2.0, 4.0, 6.0, 8.0 ];
170+
dataW = [ 1.0, 2.0, 3.0, 4.0 ];
171+
acc = incrwstdev( 6.0 );
172+
for ( i = 0; i < dataX.length; i++ ) {
173+
acc( dataX[ i ], dataW[ i ] );
174+
}
175+
t.equal( acc(), 2.0, 'returns the current accumulated weighted corrected sample standard deviation' );
176+
t.end();
177+
});
178+
179+
tape( 'if not provided a weight, the accumulator function returns `NaN`', function test( t ) {
180+
var acc = incrwstdev();
181+
t.equal( isnan( acc( 2.0 ) ), true, 'returns NaN' );
182+
t.equal( isnan( acc( 3.14 ) ), true, 'returns NaN' );
183+
t.end();
184+
});
185+
186+
tape( 'if provided `NaN` for either a value or a weight, the accumulator function returns `NaN`', function test( t ) {
187+
var acc = incrwstdev();
188+
t.equal( isnan( acc( 2.0, NaN ) ), true, 'returns NaN' );
189+
t.equal( isnan( acc( 3.14, NaN ) ), true, 'returns NaN' );
190+
191+
acc = incrwstdev();
192+
t.equal( isnan( acc( NaN, 1.0 ) ), true, 'returns NaN' );
193+
t.equal( isnan( acc( NaN, 1.0 ) ), true, 'returns NaN' );
194+
195+
acc = incrwstdev();
196+
t.equal( isnan( acc( NaN, NaN ) ), true, 'returns NaN' );
197+
t.equal( isnan( acc( NaN, NaN ) ), true, 'returns NaN' );
198+
t.end();
199+
});

0 commit comments

Comments
 (0)