Skip to content

Commit 975c96e

Browse files
committed
Add tests and fix variable reset bug
1 parent 2dd625c commit 975c96e

File tree

2 files changed

+138
-3
lines changed

2 files changed

+138
-3
lines changed

lib/node_modules/@stdlib/stats/incr/mstdev/lib/main.js

+13-3
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,15 @@ function incrmstdev( W, mean ) {
124124

125125
// Case: incoming value is NaN, the sliding second moment is automatically NaN...
126126
if ( isnan( x ) ) {
127+
N = W; // explicitly set to avoid `N < W` branch
127128
M2 = NaN;
128129
}
129130
// Case: initial window...
130131
else if ( N < W ) {
131132
buf[ i ] = x; // update buffer
133+
if ( isnan( M2 ) ) {
134+
return NaN;
135+
}
132136
N += 1;
133137
delta = x - mu;
134138
mu += delta / N;
@@ -139,18 +143,19 @@ function incrmstdev( W, mean ) {
139143
return sqrt( M2 / (N-1) );
140144
}
141145
// Case: N = W = 1
142-
if ( N === 1 ) {
146+
else if ( N === 1 ) {
143147
return 0.0;
144148
}
145149
// Case: outgoing value is NaN, and, thus, we need to compute the accumulated values...
146-
if ( isnan( buf[ i ] ) ) {
150+
else if ( isnan( buf[ i ] ) ) {
147151
N = 1;
148152
mu = x;
149153
M2 = 0.0;
150154
for ( k = 0; k < W; k++ ) {
151155
if ( k !== i ) {
152156
v = buf[ k ];
153157
if ( isnan( v ) ) {
158+
N = W; // explicitly set to avoid `N < W` branch
154159
M2 = NaN;
155160
break; // second moment is automatically NaN, so no need to continue
156161
}
@@ -199,22 +204,27 @@ function incrmstdev( W, mean ) {
199204

200205
// Case: incoming value is NaN, the sliding second moment is automatically NaN...
201206
if ( isnan( x ) ) {
207+
N = W; // explicitly set to avoid `N < W` branch
202208
M2 = NaN;
203209
}
204210
// Case: initial window...
205211
else if ( N < W ) {
206212
buf[ i ] = x; // update buffer
213+
if ( isnan( M2 ) ) {
214+
return NaN;
215+
}
207216
N += 1;
208217
delta = x - mu;
209218
M2 += delta * delta;
210219
return sqrt( M2 / N );
211220
}
212221
// Case: outgoing value is NaN, and, thus, we need to compute the accumulated values...
213-
if ( isnan( buf[ i ] ) ) {
222+
else if ( isnan( buf[ i ] ) ) {
214223
M2 = 0.0;
215224
for ( k = 0; k < W; k++ ) {
216225
if ( k !== i ) {
217226
if ( isnan( buf[ k ] ) ) {
227+
N = W; // explicitly set to avoid `N < W` branch
218228
M2 = NaN;
219229
break; // second moment is automatically NaN, so no need to continue
220230
}

lib/node_modules/@stdlib/stats/incr/mstdev/test/test.js

+125
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
var tape = require( 'tape' );
2424
var abs = require( '@stdlib/math/base/special/abs' );
2525
var sqrt = require( '@stdlib/math/base/special/sqrt' );
26+
var isnan = require( '@stdlib/math/base/assert/is-nan' );
2627
var randu = require( '@stdlib/random/base/randu' );
2728
var EPS = require( '@stdlib/constants/math/float64-eps' );
2829
var incrmstdev = require( './../lib' );
@@ -298,3 +299,127 @@ tape( 'if the window size is `1` and the mean is known, the accumulator function
298299
}
299300
t.end();
300301
});
302+
303+
tape( 'if provided `NaN`, the accumulated value is `NaN` for at least `W` invocations (unknown mean)', function test( t ) {
304+
var expected;
305+
var data;
306+
var acc;
307+
var v;
308+
var i;
309+
310+
acc = incrmstdev( 3 );
311+
312+
data = [
313+
NaN, // NaN
314+
3.14, // NaN, 3.14
315+
3.14, // NaN, 3.14, 3.14
316+
NaN, // 3.14, 3.14, NaN
317+
3.14, // 3.14, NaN, 3.14
318+
3.14, // NaN, 3.14, 3.14
319+
3.14, // 3.14, 3.14, 3.14
320+
NaN, // 3.14, 3.14, NaN
321+
3.14, // 3.14, NaN, 3.14
322+
3.14, // NaN, 3.14, 3.14
323+
3.14, // 3.14, 3.14, 3.14
324+
NaN, // 3.14, 3.14, NaN
325+
3.14, // 3.14, NaN, 3.14
326+
3.14, // NaN, 3.14, 3.14
327+
NaN, // 3.14, 3.14, NaN
328+
NaN, // 3.14, NaN, NaN
329+
NaN, // NaN, NaN, NaN
330+
NaN, // NaN, NaN, NaN
331+
3.14 // NaN, NaN, 3.14
332+
];
333+
expected = [
334+
NaN,
335+
NaN,
336+
NaN,
337+
NaN,
338+
NaN,
339+
NaN,
340+
0.0,
341+
NaN,
342+
NaN,
343+
NaN,
344+
0.0,
345+
NaN,
346+
NaN,
347+
NaN,
348+
NaN,
349+
NaN,
350+
NaN,
351+
NaN,
352+
NaN
353+
];
354+
for ( i = 0; i < data.length; i++ ) {
355+
v = acc( data[ i ] );
356+
if ( isnan( expected[ i ] ) ) {
357+
t.equal( isnan( v ), true, 'returns expected value for window '+i );
358+
} else {
359+
t.equal( v, expected[ i ], 'returns expected value for window '+i );
360+
}
361+
}
362+
t.end();
363+
});
364+
365+
tape( 'if provided `NaN`, the accumulated value is `NaN` for at least `W` invocations (known mean)', function test( t ) {
366+
var expected;
367+
var data;
368+
var acc;
369+
var v;
370+
var i;
371+
372+
acc = incrmstdev( 3, 3.14 );
373+
374+
data = [
375+
NaN, // NaN
376+
3.14, // NaN, 3.14
377+
3.14, // NaN, 3.14, 3.14
378+
NaN, // 3.14, 3.14, NaN
379+
3.14, // 3.14, NaN, 3.14
380+
3.14, // NaN, 3.14, 3.14
381+
3.14, // 3.14, 3.14, 3.14
382+
NaN, // 3.14, 3.14, NaN
383+
3.14, // 3.14, NaN, 3.14
384+
3.14, // NaN, 3.14, 3.14
385+
3.14, // 3.14, 3.14, 3.14
386+
NaN, // 3.14, 3.14, NaN
387+
3.14, // 3.14, NaN, 3.14
388+
3.14, // NaN, 3.14, 3.14
389+
NaN, // 3.14, 3.14, NaN
390+
NaN, // 3.14, NaN, NaN
391+
NaN, // NaN, NaN, NaN
392+
NaN, // NaN, NaN, NaN
393+
3.14 // NaN, NaN, 3.14
394+
];
395+
expected = [
396+
NaN,
397+
NaN,
398+
NaN,
399+
NaN,
400+
NaN,
401+
NaN,
402+
0.0,
403+
NaN,
404+
NaN,
405+
NaN,
406+
0.0,
407+
NaN,
408+
NaN,
409+
NaN,
410+
NaN,
411+
NaN,
412+
NaN,
413+
NaN,
414+
NaN
415+
];
416+
for ( i = 0; i < data.length; i++ ) {
417+
v = acc( data[ i ] );
418+
if ( isnan( expected[ i ] ) ) {
419+
t.equal( isnan( v ), true, 'returns expected value for window '+i );
420+
} else {
421+
t.equal( v, expected[ i ], 'returns expected value for window '+i );
422+
}
423+
}
424+
t.end();
425+
});

0 commit comments

Comments
 (0)