1+ /**
2+ * @license Apache-2.0
3+ *
4+ * Copyright (c) 2018 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 isPositiveZero = require ( '@stdlib/math/base/assert/is-positive-zero' ) ;
25+ var isNegativeZero = require ( '@stdlib/math/base/assert/is-negative-zero' ) ;
26+ var isnan = require ( '@stdlib/math/base/assert/is-nan' ) ;
27+ var incrnanmmin = require ( './../lib' ) ;
28+
29+
30+ // TESTS //
31+
32+ tape ( 'main export is a function' , function test ( t ) {
33+ t . ok ( true , __filename ) ;
34+ t . strictEqual ( typeof incrnanmmin , 'function' , 'main export is a function' ) ;
35+ t . end ( ) ;
36+ } ) ;
37+
38+ tape ( 'the function throws an error if not provided a positive integer' , function test ( t ) {
39+ var values = [
40+ '5' ,
41+ - 5.0 ,
42+ 0.0 ,
43+ 3.14 ,
44+ true ,
45+ false ,
46+ null ,
47+ void 0 ,
48+ NaN ,
49+ [ ] ,
50+ { } ,
51+ function noop ( ) { }
52+ ] ;
53+
54+ values . forEach ( function ( value ) {
55+ t . throws ( function ( ) { incrnanmmin ( value ) ; } , TypeError , 'throws an error when provided ' + value ) ;
56+ } ) ;
57+ t . end ( ) ;
58+ } ) ;
59+
60+ tape ( 'the function returns an accumulator function' , function test ( t ) {
61+ t . equal ( typeof incrnanmmin ( 3 ) , 'function' , 'returns a function' ) ;
62+ t . end ( ) ;
63+ } ) ;
64+
65+ tape ( 'the accumulator function computes a moving minimum incrementally, ignoring NaN values' , function test ( t ) {
66+ var expected ;
67+ var actual ;
68+ var data ;
69+ var acc ;
70+ var N ;
71+ var i ;
72+
73+ data = [ 2.0 , NaN , 3.0 , 2.0 , NaN , 4.0 , 3.0 , 4.0 , 2.0 , NaN , 2.0 , 2.0 , 2.0 , 1.0 , 4.0 ] ;
74+ N = data . length ;
75+
76+ acc = incrnanmmin ( 3 ) ;
77+
78+ actual = [ ] ;
79+ for ( i = 0 ; i < N ; i ++ ) {
80+ actual . push ( acc ( data [ i ] ) ) ;
81+ }
82+ expected = [ 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 3.0 , 3.0 , 2.0 , 2.0 , 2.0 , 2.0 , 2.0 , 1.0 , 1.0 ] ;
83+
84+ t . deepEqual ( actual , expected , 'returns expected incremental results while ignoring NaN values' ) ;
85+ t . end ( ) ;
86+ } ) ;
87+
88+ tape ( 'if not provided an input value, the accumulator function returns the current minimum value while ignoring NaN values' , function test ( t ) {
89+ var data ;
90+ var acc ;
91+ var i ;
92+
93+ data = [ 2.0 , NaN , 3.0 , NaN , 5.0 , 4.0 ] ;
94+ acc = incrnanmmin ( 2 ) ;
95+ for ( i = 0 ; i < data . length ; i ++ ) {
96+ acc ( data [ i ] ) ;
97+ }
98+ t . equal ( acc ( ) , 4.0 , 'returns expected value while ignoring NaN values' ) ;
99+ t . end ( ) ;
100+ } ) ;
101+
102+ tape ( 'if data has yet to be provided, the accumulator function returns `null`' , function test ( t ) {
103+ var acc = incrnanmmin ( 3 ) ;
104+ t . equal ( acc ( ) , null , 'returns null' ) ;
105+ t . end ( ) ;
106+ } ) ;
107+
108+ tape ( 'the accumulator function correctly handles signed zeros while ignoring NaNs' , function test ( t ) {
109+ var expected ;
110+ var data ;
111+ var acc ;
112+ var v ;
113+ var i ;
114+
115+ acc = incrnanmmin ( 3 ) ;
116+
117+ data = [
118+ 0.0 , // 0
119+ - 0.0 , // 0, -0
120+ NaN , // ignored
121+ 0.0 , // 0, -0, 0
122+ NaN , // ignored
123+ - 0.0 , // -0, 0, -0
124+ 0.0 , // 0, -0, 0
125+ NaN , // ignored
126+ - 0.0 , // -0, 0, -0
127+ 0.0 , // 0, -0, 0
128+ - 0.0 , // -0, 0, -0
129+ - 0.0 , // -0, -0, -0
130+ 0.0 // -0, -0, 0
131+ ] ;
132+
133+ expected = [
134+ 0.0 ,
135+ - 0.0 ,
136+ - 0.0 , // NaN ignored
137+ - 0.0 ,
138+ - 0.0 , // NaN ignored
139+ - 0.0 ,
140+ - 0.0 ,
141+ - 0.0 , // NaN ignored
142+ - 0.0 ,
143+ - 0.0 ,
144+ - 0.0 ,
145+ - 0.0 ,
146+ - 0.0
147+ ] ;
148+
149+ for ( i = 0 ; i < data . length ; i ++ ) {
150+ v = acc ( data [ i ] ) ;
151+ if ( isnan ( data [ i ] ) ) {
152+ continue ;
153+ }
154+ if ( isNegativeZero ( expected [ i ] ) ) {
155+ t . equal ( isNegativeZero ( v ) , true , 'returns expected value for window ' + i ) ;
156+ } else {
157+ t . equal ( isPositiveZero ( v ) , true , 'returns expected value for window ' + i ) ;
158+ }
159+ }
160+ t . end ( ) ;
161+ } ) ;
162+
163+ tape ( 'if provided `NaN`, the accumulated value ignores `NaN` and computes the minimum over valid values' , function test ( t ) {
164+ var expected ;
165+ var data ;
166+ var acc ;
167+ var v ;
168+ var i ;
169+
170+ acc = incrnanmmin ( 3 ) ;
171+
172+ data = [
173+ NaN , // ignored
174+ 3.14 , // 3.14
175+ 3.14 , // 3.14, 3.14
176+ NaN , // 3.14, 3.14 (NaN ignored)
177+ 3.14 , // 3.14, 3.14, 3.14
178+ 3.14 , // 3.14, 3.14, 3.14
179+ 3.14 , // 3.14, 3.14, 3.14
180+ NaN , // 3.14, 3.14 (NaN ignored)
181+ 3.14 , // 3.14, 3.14, 3.14
182+ 3.14 , // 3.14, 3.14, 3.14
183+ 3.14 , // 3.14, 3.14, 3.14
184+ NaN , // 3.14, 3.14 (NaN ignored)
185+ 3.14 , // 3.14, 3.14, 3.14
186+ 3.14 , // 3.14, 3.14, 3.14
187+ NaN , // 3.14, 3.14 (NaN ignored)
188+ NaN , // 3.14 (NaN ignored)
189+ NaN , // (NaN ignored)
190+ NaN , // (NaN ignored)
191+ 3.14 // 3.14
192+ ] ;
193+
194+ expected = [
195+ null , // No valid numbers yet
196+ 3.14 ,
197+ 3.14 ,
198+ 3.14 ,
199+ 3.14 ,
200+ 3.14 ,
201+ 3.14 ,
202+ 3.14 ,
203+ 3.14 ,
204+ 3.14 ,
205+ 3.14 ,
206+ 3.14 ,
207+ 3.14 ,
208+ 3.14 ,
209+ 3.14 ,
210+ 3.14 ,
211+ 3.14 ,
212+ 3.14 ,
213+ 3.14
214+ ] ;
215+
216+ for ( i = 0 ; i < data . length ; i ++ ) {
217+ v = acc ( data [ i ] ) ;
218+ if ( expected [ i ] === null ) {
219+ t . equal ( v , null , 'returns expected value for window ' + i ) ;
220+ } else {
221+ t . equal ( v , expected [ i ] , 'returns expected value for window ' + i ) ;
222+ }
223+ }
224+ t . end ( ) ;
225+ } ) ;
0 commit comments