1   /*
2    * Copyright 2003-2004 The Apache Software Foundation.
3    * 
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.apache.commons.math.stat;
17  
18  import junit.framework.Test;
19  import junit.framework.TestCase;
20  import junit.framework.TestSuite;
21  
22  import org.apache.commons.math.TestUtils;
23  
24  /***
25   * Test cases for the {@link StatUtils} class.
26   * @version $Revision: 1.19 $ $Date: 2004/07/17 22:01:39 $
27   */
28  
29  public final class StatUtilsTest extends TestCase {
30  
31      private double one = 1;
32      private float two = 2;
33      private int three = 3;
34      private double mean = 2;
35      private double sumSq = 18;
36      private double sum = 8;
37      private double var = 0.666666666666666666667;
38      private double std = Math.sqrt(var);
39      private double n = 4;
40      private double min = 1;
41      private double max = 3;
42      private double skewness = 0;
43      private double kurtosis = 0.5;
44      private double tolerance = 10E-15;
45  
46      public StatUtilsTest(String name) {
47          super(name);
48      }
49  
50      public void setUp() {
51      }
52  
53      public static Test suite() {
54          TestSuite suite = new TestSuite(StatUtilsTest.class);
55          suite.setName("StatUtil Tests");
56          return suite;
57      }
58  
59      /*** test stats */
60      public void testStats() {
61          double[] values = new double[] { one, two, two, three };
62          assertEquals("sum", sum, StatUtils.sum(values), tolerance);
63          assertEquals("sumsq", sumSq, StatUtils.sumSq(values), tolerance);
64          assertEquals("var", var, StatUtils.variance(values), tolerance);
65          assertEquals("var with mean", var, StatUtils.variance(values, mean), tolerance);
66          assertEquals("mean", mean, StatUtils.mean(values), tolerance);
67          assertEquals("min", min, StatUtils.min(values), tolerance);
68          assertEquals("max", max, StatUtils.max(values), tolerance);
69      }
70  
71      public void testN0andN1Conditions() throws Exception {
72          double[] values = new double[0];
73  
74          assertTrue(
75              "Mean of n = 0 set should be NaN",
76              Double.isNaN(StatUtils.mean(values)));
77          assertTrue(
78              "Variance of n = 0 set should be NaN",
79              Double.isNaN(StatUtils.variance(values)));
80  
81          values = new double[] { one };
82  
83          assertTrue(
84              "Mean of n = 1 set should be value of single item n1",
85              StatUtils.mean(values) == one);
86          assertTrue(
87              "Variance of n = 1 set should be zero",
88              StatUtils.variance(values) == 0);
89      }
90  
91      public void testArrayIndexConditions() throws Exception {
92          double[] values = { 1.0, 2.0, 3.0, 4.0 };
93  
94          assertEquals(
95              "Sum not expected",
96              5.0,
97              StatUtils.sum(values, 1, 2),
98              Double.MIN_VALUE);
99          assertEquals(
100             "Sum not expected",
101             3.0,
102             StatUtils.sum(values, 0, 2),
103             Double.MIN_VALUE);
104         assertEquals(
105             "Sum not expected",
106             7.0,
107             StatUtils.sum(values, 2, 2),
108             Double.MIN_VALUE);
109 
110         try {
111             StatUtils.sum(values, 2, 3);
112             assertTrue("Didn't throw exception", false);
113         } catch (Exception e) {
114             assertTrue(true);
115         }
116 
117         try {
118             StatUtils.sum(values, -1, 2);
119             assertTrue("Didn't throw exception", false);
120         } catch (Exception e) {
121             assertTrue(true);
122         }
123 
124     }
125     
126     public void testSumSq() {
127         double[] x = null;
128         
129         // test null
130         try {
131             StatUtils.sumSq(x);
132             fail("null is not a valid data array.");
133         } catch (IllegalArgumentException ex) {
134             // success
135         }
136         
137         try {
138             StatUtils.sumSq(x, 0, 4);
139             fail("null is not a valid data array.");
140         } catch (IllegalArgumentException ex) {
141             // success
142         }
143         
144         // test empty
145         x = new double[] {};
146         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance);
147         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance);
148         
149         // test one
150         x = new double[] {two};
151         TestUtils.assertEquals(4, StatUtils.sumSq(x), tolerance);
152         TestUtils.assertEquals(4, StatUtils.sumSq(x, 0, 1), tolerance);
153         
154         // test many
155         x = new double[] {one, two, two, three};
156         TestUtils.assertEquals(18, StatUtils.sumSq(x), tolerance);
157         TestUtils.assertEquals(8, StatUtils.sumSq(x, 1, 2), tolerance);
158     }
159     
160     public void testProduct() {
161         double[] x = null;
162         
163         // test null
164         try {
165             StatUtils.product(x);
166             fail("null is not a valid data array.");
167         } catch (IllegalArgumentException ex) {
168             // success
169         }
170         
171         try {
172             StatUtils.product(x, 0, 4);
173             fail("null is not a valid data array.");
174         } catch (IllegalArgumentException ex) {
175             // success
176         }
177         
178         // test empty
179         x = new double[] {};
180         TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance);
181         TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance);
182         
183         // test one
184         x = new double[] {two};
185         TestUtils.assertEquals(two, StatUtils.product(x), tolerance);
186         TestUtils.assertEquals(two, StatUtils.product(x, 0, 1), tolerance);
187         
188         // test many
189         x = new double[] {one, two, two, three};
190         TestUtils.assertEquals(12, StatUtils.product(x), tolerance);
191         TestUtils.assertEquals(4, StatUtils.product(x, 1, 2), tolerance);
192     }
193     
194     public void testSumLog() {
195         double[] x = null;
196         
197         // test null
198         try {
199             StatUtils.sumLog(x);
200             fail("null is not a valid data array.");
201         } catch (IllegalArgumentException ex) {
202             // success
203         }
204         
205         try {
206             StatUtils.sumLog(x, 0, 4);
207             fail("null is not a valid data array.");
208         } catch (IllegalArgumentException ex) {
209             // success
210         }
211         
212         // test empty
213         x = new double[] {};
214         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance);
215         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance);
216         
217         // test one
218         x = new double[] {two};
219         TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x), tolerance);
220         TestUtils.assertEquals(Math.log(two), 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) + Math.log(three), StatUtils.sumLog(x), tolerance);
225         TestUtils.assertEquals(2.0 * Math.log(two), StatUtils.sumLog(x, 1, 2), tolerance);
226     }
227     
228     public void testMean() {
229         double[] x = null;
230         
231         try {
232             StatUtils.mean(x, 0, 4);
233             fail("null is not a valid data array.");
234         } catch (IllegalArgumentException ex) {
235             // success
236         }
237         
238         // test empty
239         x = new double[] {};
240         TestUtils.assertEquals(Double.NaN, StatUtils.mean(x, 0, 0), tolerance);
241         
242         // test one
243         x = new double[] {two};
244         TestUtils.assertEquals(two, StatUtils.mean(x, 0, 1), tolerance);
245         
246         // test many
247         x = new double[] {one, two, two, three};
248         TestUtils.assertEquals(2.5, StatUtils.mean(x, 2, 2), tolerance);
249     }
250     
251     public void testVariance() {
252         double[] x = null;
253         
254         try {
255             StatUtils.variance(x, 0, 4);
256             fail("null is not a valid data array.");
257         } catch (IllegalArgumentException ex) {
258             // success
259         }
260         
261         // test empty
262         x = new double[] {};
263         TestUtils.assertEquals(Double.NaN, StatUtils.variance(x, 0, 0), tolerance);
264         
265         // test one
266         x = new double[] {two};
267         TestUtils.assertEquals(0.0, StatUtils.variance(x, 0, 1), tolerance);
268         
269         // test many
270         x = new double[] {one, two, two, three};
271         TestUtils.assertEquals(0.5, StatUtils.variance(x, 2, 2), tolerance);
272         
273         // test precomputed mean
274         x = new double[] {one, two, two, three};
275         TestUtils.assertEquals(0.5, StatUtils.variance(x,2.5, 2, 2), tolerance);
276     }
277     
278     public void testMax() {
279         double[] x = null;
280         
281         try {
282             StatUtils.max(x, 0, 4);
283             fail("null is not a valid data array.");
284         } catch (IllegalArgumentException ex) {
285             // success
286         }
287         
288         // test empty
289         x = new double[] {};
290         TestUtils.assertEquals(Double.NaN, StatUtils.max(x, 0, 0), tolerance);
291         
292         // test one
293         x = new double[] {two};
294         TestUtils.assertEquals(two, StatUtils.max(x, 0, 1), tolerance);
295         
296         // test many
297         x = new double[] {one, two, two, three};
298         TestUtils.assertEquals(three, StatUtils.max(x, 1, 3), tolerance);
299     }
300     
301     public void testMin() {
302         double[] x = null;
303         
304         try {
305             StatUtils.min(x, 0, 4);
306             fail("null is not a valid data array.");
307         } catch (IllegalArgumentException ex) {
308             // success
309         }
310         
311         // test empty
312         x = new double[] {};
313         TestUtils.assertEquals(Double.NaN, StatUtils.min(x, 0, 0), tolerance);
314         
315         // test one
316         x = new double[] {two};
317         TestUtils.assertEquals(two, StatUtils.min(x, 0, 1), tolerance);
318         
319         // test many
320         x = new double[] {one, two, two, three};
321         TestUtils.assertEquals(two, StatUtils.min(x, 1, 3), tolerance);
322     }
323     
324     public void testPercentile() {
325         double[] x = null;
326         
327         // test null
328         try {
329             StatUtils.percentile(x, .25);
330             fail("null is not a valid data array.");
331         } catch (IllegalArgumentException ex) {
332             // success
333         }
334         
335         try {
336             StatUtils.percentile(x, 0, 4, 0.25);
337             fail("null is not a valid data array.");
338         } catch (IllegalArgumentException ex) {
339             // success
340         }
341         
342         // test empty
343         x = new double[] {};
344         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 25), tolerance);
345         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), tolerance);
346         
347         // test one
348         x = new double[] {two};
349         TestUtils.assertEquals(two, StatUtils.percentile(x, 25), tolerance);
350         TestUtils.assertEquals(two, StatUtils.percentile(x, 0, 1, 25), tolerance);
351         
352         // test many
353         x = new double[] {one, two, two, three};
354         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 70), tolerance);
355         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), tolerance);
356     }
357     
358     public void testDifferenceStats() throws Exception {
359         double sample1[] = {1d, 2d, 3d, 4d};
360         double sample2[] = {1d, 3d, 4d, 2d};
361         double diff[] = {0d, -1d, -1d, 2d};
362         double small[] = {1d, 4d};
363         double meanDifference = StatUtils.meanDifference(sample1, sample2);
364         assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), tolerance);
365         assertEquals(meanDifference, StatUtils.mean(diff), tolerance);
366         assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference), 
367                 StatUtils.variance(diff), tolerance);
368         try {
369             StatUtils.meanDifference(sample1, small);
370             fail("Expecting IllegalArgumentException");
371         } catch (IllegalArgumentException ex) {
372             // expected
373         }
374     }
375     
376     public void testGeometricMean() throws Exception {
377         double[] test = null;
378         try {
379             double x = StatUtils.geometricMean(test);
380             fail("Expecting IllegalArgumentException");
381         } catch (IllegalArgumentException ex) {
382             // expected
383         }
384         test = new double[] {2, 4, 6, 8};
385         assertEquals(Math.exp(0.25d * StatUtils.sumLog(test)), 
386                 StatUtils.geometricMean(test), Double.MIN_VALUE);
387     }
388 }