001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math.stat;
018
019 import junit.framework.Test;
020 import junit.framework.TestCase;
021 import junit.framework.TestSuite;
022
023 import org.apache.commons.math.TestUtils;
024
025 /**
026 * Test cases for the {@link StatUtils} class.
027 * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
028 */
029
030 public final class StatUtilsTest extends TestCase {
031
032 private double one = 1;
033 private float two = 2;
034 private int three = 3;
035 private double mean = 2;
036 private double sumSq = 18;
037 private double sum = 8;
038 private double var = 0.666666666666666666667;
039 private double min = 1;
040 private double max = 3;
041 private double tolerance = 10E-15;
042 private double nan = Double.NaN;
043
044 public StatUtilsTest(String name) {
045 super(name);
046 }
047
048 public static Test suite() {
049 TestSuite suite = new TestSuite(StatUtilsTest.class);
050 suite.setName("StatUtil Tests");
051 return suite;
052 }
053
054 /** test stats */
055 public void testStats() {
056 double[] values = new double[] { one, two, two, three };
057 assertEquals("sum", sum, StatUtils.sum(values), tolerance);
058 assertEquals("sumsq", sumSq, StatUtils.sumSq(values), tolerance);
059 assertEquals("var", var, StatUtils.variance(values), tolerance);
060 assertEquals("var with mean", var, StatUtils.variance(values, mean), tolerance);
061 assertEquals("mean", mean, StatUtils.mean(values), tolerance);
062 assertEquals("min", min, StatUtils.min(values), tolerance);
063 assertEquals("max", max, StatUtils.max(values), tolerance);
064 }
065
066 public void testN0andN1Conditions() throws Exception {
067 double[] values = new double[0];
068
069 assertTrue(
070 "Mean of n = 0 set should be NaN",
071 Double.isNaN(StatUtils.mean(values)));
072 assertTrue(
073 "Variance of n = 0 set should be NaN",
074 Double.isNaN(StatUtils.variance(values)));
075
076 values = new double[] { one };
077
078 assertTrue(
079 "Mean of n = 1 set should be value of single item n1",
080 StatUtils.mean(values) == one);
081 assertTrue(
082 "Variance of n = 1 set should be zero",
083 StatUtils.variance(values) == 0);
084 }
085
086 public void testArrayIndexConditions() throws Exception {
087 double[] values = { 1.0, 2.0, 3.0, 4.0 };
088
089 assertEquals(
090 "Sum not expected",
091 5.0,
092 StatUtils.sum(values, 1, 2),
093 Double.MIN_VALUE);
094 assertEquals(
095 "Sum not expected",
096 3.0,
097 StatUtils.sum(values, 0, 2),
098 Double.MIN_VALUE);
099 assertEquals(
100 "Sum not expected",
101 7.0,
102 StatUtils.sum(values, 2, 2),
103 Double.MIN_VALUE);
104
105 try {
106 StatUtils.sum(values, 2, 3);
107 assertTrue("Didn't throw exception", false);
108 } catch (Exception e) {
109 assertTrue(true);
110 }
111
112 try {
113 StatUtils.sum(values, -1, 2);
114 assertTrue("Didn't throw exception", false);
115 } catch (Exception e) {
116 assertTrue(true);
117 }
118
119 }
120
121 public void testSumSq() {
122 double[] x = null;
123
124 // test null
125 try {
126 StatUtils.sumSq(x);
127 fail("null is not a valid data array.");
128 } catch (IllegalArgumentException ex) {
129 // success
130 }
131
132 try {
133 StatUtils.sumSq(x, 0, 4);
134 fail("null is not a valid data array.");
135 } catch (IllegalArgumentException ex) {
136 // success
137 }
138
139 // test empty
140 x = new double[] {};
141 TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance);
142 TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance);
143
144 // test one
145 x = new double[] {two};
146 TestUtils.assertEquals(4, StatUtils.sumSq(x), tolerance);
147 TestUtils.assertEquals(4, StatUtils.sumSq(x, 0, 1), tolerance);
148
149 // test many
150 x = new double[] {one, two, two, three};
151 TestUtils.assertEquals(18, StatUtils.sumSq(x), tolerance);
152 TestUtils.assertEquals(8, StatUtils.sumSq(x, 1, 2), tolerance);
153 }
154
155 public void testProduct() {
156 double[] x = null;
157
158 // test null
159 try {
160 StatUtils.product(x);
161 fail("null is not a valid data array.");
162 } catch (IllegalArgumentException ex) {
163 // success
164 }
165
166 try {
167 StatUtils.product(x, 0, 4);
168 fail("null is not a valid data array.");
169 } catch (IllegalArgumentException ex) {
170 // success
171 }
172
173 // test empty
174 x = new double[] {};
175 TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance);
176 TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance);
177
178 // test one
179 x = new double[] {two};
180 TestUtils.assertEquals(two, StatUtils.product(x), tolerance);
181 TestUtils.assertEquals(two, StatUtils.product(x, 0, 1), tolerance);
182
183 // test many
184 x = new double[] {one, two, two, three};
185 TestUtils.assertEquals(12, StatUtils.product(x), tolerance);
186 TestUtils.assertEquals(4, StatUtils.product(x, 1, 2), tolerance);
187 }
188
189 public void testSumLog() {
190 double[] x = null;
191
192 // test null
193 try {
194 StatUtils.sumLog(x);
195 fail("null is not a valid data array.");
196 } catch (IllegalArgumentException ex) {
197 // success
198 }
199
200 try {
201 StatUtils.sumLog(x, 0, 4);
202 fail("null is not a valid data array.");
203 } catch (IllegalArgumentException ex) {
204 // success
205 }
206
207 // test empty
208 x = new double[] {};
209 TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance);
210 TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance);
211
212 // test one
213 x = new double[] {two};
214 TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x), tolerance);
215 TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x, 0, 1), tolerance);
216
217 // test many
218 x = new double[] {one, two, two, three};
219 TestUtils.assertEquals(Math.log(one) + 2.0 * Math.log(two) + Math.log(three), StatUtils.sumLog(x), tolerance);
220 TestUtils.assertEquals(2.0 * Math.log(two), StatUtils.sumLog(x, 1, 2), tolerance);
221 }
222
223 public void testMean() {
224 double[] x = null;
225
226 try {
227 StatUtils.mean(x, 0, 4);
228 fail("null is not a valid data array.");
229 } catch (IllegalArgumentException ex) {
230 // success
231 }
232
233 // test empty
234 x = new double[] {};
235 TestUtils.assertEquals(Double.NaN, StatUtils.mean(x, 0, 0), tolerance);
236
237 // test one
238 x = new double[] {two};
239 TestUtils.assertEquals(two, StatUtils.mean(x, 0, 1), tolerance);
240
241 // test many
242 x = new double[] {one, two, two, three};
243 TestUtils.assertEquals(2.5, StatUtils.mean(x, 2, 2), tolerance);
244 }
245
246 public void testVariance() {
247 double[] x = null;
248
249 try {
250 StatUtils.variance(x, 0, 4);
251 fail("null is not a valid data array.");
252 } catch (IllegalArgumentException ex) {
253 // success
254 }
255
256 // test empty
257 x = new double[] {};
258 TestUtils.assertEquals(Double.NaN, StatUtils.variance(x, 0, 0), tolerance);
259
260 // test one
261 x = new double[] {two};
262 TestUtils.assertEquals(0.0, StatUtils.variance(x, 0, 1), tolerance);
263
264 // test many
265 x = new double[] {one, two, two, three};
266 TestUtils.assertEquals(0.5, StatUtils.variance(x, 2, 2), tolerance);
267
268 // test precomputed mean
269 x = new double[] {one, two, two, three};
270 TestUtils.assertEquals(0.5, StatUtils.variance(x,2.5, 2, 2), tolerance);
271 }
272
273 public void testMax() {
274 double[] x = null;
275
276 try {
277 StatUtils.max(x, 0, 4);
278 fail("null is not a valid data array.");
279 } catch (IllegalArgumentException ex) {
280 // success
281 }
282
283 // test empty
284 x = new double[] {};
285 TestUtils.assertEquals(Double.NaN, StatUtils.max(x, 0, 0), tolerance);
286
287 // test one
288 x = new double[] {two};
289 TestUtils.assertEquals(two, StatUtils.max(x, 0, 1), tolerance);
290
291 // test many
292 x = new double[] {one, two, two, three};
293 TestUtils.assertEquals(three, StatUtils.max(x, 1, 3), tolerance);
294
295 // test first nan is ignored
296 x = new double[] {nan, two, three};
297 TestUtils.assertEquals(three, StatUtils.max(x), tolerance);
298
299 // test middle nan is ignored
300 x = new double[] {one, nan, three};
301 TestUtils.assertEquals(three, StatUtils.max(x), tolerance);
302
303 // test last nan is ignored
304 x = new double[] {one, two, nan};
305 TestUtils.assertEquals(two, StatUtils.max(x), tolerance);
306
307 // test all nan returns nan
308 x = new double[] {nan, nan, nan};
309 TestUtils.assertEquals(nan, StatUtils.max(x), tolerance);
310 }
311
312 public void testMin() {
313 double[] x = null;
314
315 try {
316 StatUtils.min(x, 0, 4);
317 fail("null is not a valid data array.");
318 } catch (IllegalArgumentException ex) {
319 // success
320 }
321
322 // test empty
323 x = new double[] {};
324 TestUtils.assertEquals(Double.NaN, StatUtils.min(x, 0, 0), tolerance);
325
326 // test one
327 x = new double[] {two};
328 TestUtils.assertEquals(two, StatUtils.min(x, 0, 1), tolerance);
329
330 // test many
331 x = new double[] {one, two, two, three};
332 TestUtils.assertEquals(two, StatUtils.min(x, 1, 3), tolerance);
333
334 // test first nan is ignored
335 x = new double[] {nan, two, three};
336 TestUtils.assertEquals(two, StatUtils.min(x), tolerance);
337
338 // test middle nan is ignored
339 x = new double[] {one, nan, three};
340 TestUtils.assertEquals(one, StatUtils.min(x), tolerance);
341
342 // test last nan is ignored
343 x = new double[] {one, two, nan};
344 TestUtils.assertEquals(one, StatUtils.min(x), tolerance);
345
346 // test all nan returns nan
347 x = new double[] {nan, nan, nan};
348 TestUtils.assertEquals(nan, StatUtils.min(x), tolerance);
349 }
350
351 public void testPercentile() {
352 double[] x = null;
353
354 // test null
355 try {
356 StatUtils.percentile(x, .25);
357 fail("null is not a valid data array.");
358 } catch (IllegalArgumentException ex) {
359 // success
360 }
361
362 try {
363 StatUtils.percentile(x, 0, 4, 0.25);
364 fail("null is not a valid data array.");
365 } catch (IllegalArgumentException ex) {
366 // success
367 }
368
369 // test empty
370 x = new double[] {};
371 TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 25), tolerance);
372 TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), tolerance);
373
374 // test one
375 x = new double[] {two};
376 TestUtils.assertEquals(two, StatUtils.percentile(x, 25), tolerance);
377 TestUtils.assertEquals(two, StatUtils.percentile(x, 0, 1, 25), tolerance);
378
379 // test many
380 x = new double[] {one, two, two, three};
381 TestUtils.assertEquals(2.5, StatUtils.percentile(x, 70), tolerance);
382 TestUtils.assertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), tolerance);
383 }
384
385 public void testDifferenceStats() throws Exception {
386 double sample1[] = {1d, 2d, 3d, 4d};
387 double sample2[] = {1d, 3d, 4d, 2d};
388 double diff[] = {0d, -1d, -1d, 2d};
389 double small[] = {1d, 4d};
390 double meanDifference = StatUtils.meanDifference(sample1, sample2);
391 assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), tolerance);
392 assertEquals(meanDifference, StatUtils.mean(diff), tolerance);
393 assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference),
394 StatUtils.variance(diff), tolerance);
395 try {
396 StatUtils.meanDifference(sample1, small);
397 fail("Expecting IllegalArgumentException");
398 } catch (IllegalArgumentException ex) {
399 // expected
400 }
401 try {
402 StatUtils.varianceDifference(sample1, small, meanDifference);
403 fail("Expecting IllegalArgumentException");
404 } catch (IllegalArgumentException ex) {
405 // expected
406 }
407 try {
408 double[] single = {1.0};
409 StatUtils.varianceDifference(single, single, meanDifference);
410 fail("Expecting IllegalArgumentException");
411 } catch (IllegalArgumentException ex) {
412 // expected
413 }
414 }
415
416 public void testGeometricMean() throws Exception {
417 double[] test = null;
418 try {
419 StatUtils.geometricMean(test);
420 fail("Expecting IllegalArgumentException");
421 } catch (IllegalArgumentException ex) {
422 // expected
423 }
424 test = new double[] {2, 4, 6, 8};
425 assertEquals(Math.exp(0.25d * StatUtils.sumLog(test)),
426 StatUtils.geometricMean(test), Double.MIN_VALUE);
427 assertEquals(Math.exp(0.5 * StatUtils.sumLog(test, 0, 2)),
428 StatUtils.geometricMean(test, 0, 2), Double.MIN_VALUE);
429 }
430 }