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