1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.math.stat.descriptive;
18  
19  
20  import junit.framework.Test;
21  import junit.framework.TestCase;
22  import junit.framework.TestSuite;
23  
24  import org.apache.commons.math.TestUtils;
25  import org.apache.commons.math.stat.descriptive.moment.Mean;
26  import org.apache.commons.math.stat.descriptive.summary.Sum;
27  /**
28   * Test cases for the {@link SummaryStatistics} class.
29   *
30   * @version $Revision: 720030 $ $Date: 2008-11-23 13:47:50 -0500 (Sun, 23 Nov 2008) $
31   */
32  
33  public class SummaryStatisticsTest extends TestCase {
34  
35      private double one = 1;
36      private float twoF = 2;
37      private long twoL = 2;
38      private int three = 3;
39      private double mean = 2;
40      private double sumSq = 18;
41      private double sum = 8;
42      private double var = 0.666666666666666666667;
43      private double std = Math.sqrt(var);
44      private double n = 4;
45      private double min = 1;
46      private double max = 3;
47      private double tolerance = 10E-15;
48  
49      public static Test suite() {
50          TestSuite suite = new TestSuite(SummaryStatisticsTest.class);
51          suite.setName("SummaryStatistics tests");
52          return suite;
53      }
54  
55      public SummaryStatisticsTest(String name) {
56          super(name);
57      }
58      
59      protected SummaryStatistics createSummaryStatistics() {
60          return new SummaryStatistics();
61      }
62  
63      /** test stats */
64      public void testStats() {
65          SummaryStatistics u = createSummaryStatistics();
66          assertEquals("total count",0,u.getN(),tolerance);
67          u.addValue(one);
68          u.addValue(twoF);
69          u.addValue(twoL);
70          u.addValue(three);
71          assertEquals("N",n,u.getN(),tolerance);
72          assertEquals("sum",sum,u.getSum(),tolerance);
73          assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
74          assertEquals("var",var,u.getVariance(),tolerance);
75          assertEquals("std",std,u.getStandardDeviation(),tolerance);
76          assertEquals("mean",mean,u.getMean(),tolerance);
77          assertEquals("min",min,u.getMin(),tolerance);
78          assertEquals("max",max,u.getMax(),tolerance);
79          u.clear();
80          assertEquals("total count",0,u.getN(),tolerance);    
81      }     
82  
83      public void testN0andN1Conditions() throws Exception {
84          SummaryStatistics u = createSummaryStatistics();
85          assertTrue("Mean of n = 0 set should be NaN", 
86                  Double.isNaN( u.getMean() ) );
87          assertTrue("Standard Deviation of n = 0 set should be NaN", 
88                  Double.isNaN( u.getStandardDeviation() ) );
89          assertTrue("Variance of n = 0 set should be NaN", 
90                  Double.isNaN(u.getVariance() ) );
91  
92          /* n=1 */
93          u.addValue(one);
94          assertTrue("mean should be one (n = 1)", 
95                  u.getMean() == one);
96          assertTrue("geometric should be one (n = 1) instead it is " + u.getGeometricMean(), 
97                  u.getGeometricMean() == one);
98          assertTrue("Std should be zero (n = 1)", 
99                  u.getStandardDeviation() == 0.0);
100         assertTrue("variance should be zero (n = 1)", 
101                 u.getVariance() == 0.0);
102 
103         /* n=2 */               
104         u.addValue(twoF);
105         assertTrue("Std should not be zero (n = 2)", 
106                 u.getStandardDeviation() != 0.0);
107         assertTrue("variance should not be zero (n = 2)", 
108                 u.getVariance() != 0.0);
109 
110     }
111 
112     public void testProductAndGeometricMean() throws Exception {
113         SummaryStatistics u = createSummaryStatistics();
114         u.addValue( 1.0 );
115         u.addValue( 2.0 );
116         u.addValue( 3.0 );
117         u.addValue( 4.0 );
118 
119         assertEquals( "Geometric mean not expected", 2.213364, 
120                 u.getGeometricMean(), 0.00001 );
121     }
122 
123     public void testNaNContracts() {
124         SummaryStatistics u = createSummaryStatistics();
125         assertTrue("mean not NaN",Double.isNaN(u.getMean())); 
126         assertTrue("min not NaN",Double.isNaN(u.getMin())); 
127         assertTrue("std dev not NaN",Double.isNaN(u.getStandardDeviation())); 
128         assertTrue("var not NaN",Double.isNaN(u.getVariance())); 
129         assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
130 
131         u.addValue(1.0);
132 
133         assertEquals( "mean not expected", 1.0, 
134                 u.getMean(), Double.MIN_VALUE);
135         assertEquals( "variance not expected", 0.0, 
136                 u.getVariance(), Double.MIN_VALUE);
137         assertEquals( "geometric mean not expected", 1.0, 
138                 u.getGeometricMean(), Double.MIN_VALUE);
139 
140         u.addValue(-1.0);
141 
142         assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
143 
144         u.addValue(0.0);
145 
146         assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
147 
148         //FiXME: test all other NaN contract specs
149     }
150 
151     public void testGetSummary() {
152         SummaryStatistics u = createSummaryStatistics();
153         StatisticalSummary summary = u.getSummary();
154         verifySummary(u, summary);
155         u.addValue(1d);
156         summary = u.getSummary();
157         verifySummary(u, summary);
158         u.addValue(2d);
159         summary = u.getSummary();
160         verifySummary(u, summary);
161         u.addValue(2d);
162         summary = u.getSummary();
163         verifySummary(u, summary);     
164     }
165 
166     public void testSerialization() {
167         SummaryStatistics u = createSummaryStatistics();
168         // Empty test
169         TestUtils.checkSerializedEquality(u);
170         SummaryStatistics s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
171         StatisticalSummary summary = s.getSummary();
172         verifySummary(u, summary);
173 
174         // Add some data
175         u.addValue(2d);
176         u.addValue(1d);
177         u.addValue(3d);
178         u.addValue(4d);
179         u.addValue(5d);
180 
181         // Test again
182         TestUtils.checkSerializedEquality(u);
183         s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
184         summary = s.getSummary();
185         verifySummary(u, summary);
186 
187     }
188 
189     public void testEqualsAndHashCode() {
190         SummaryStatistics u = createSummaryStatistics();
191         SummaryStatistics t = null;
192         int emptyHash = u.hashCode();
193         assertTrue("reflexive", u.equals(u));
194         assertFalse("non-null compared to null", u.equals(t));
195         assertFalse("wrong type", u.equals(Double.valueOf(0)));
196         t = createSummaryStatistics();
197         assertTrue("empty instances should be equal", t.equals(u));
198         assertTrue("empty instances should be equal", u.equals(t));
199         assertEquals("empty hash code", emptyHash, t.hashCode());
200 
201         // Add some data to u
202         u.addValue(2d);
203         u.addValue(1d);
204         u.addValue(3d);
205         u.addValue(4d);
206         assertFalse("different n's should make instances not equal", t.equals(u));
207         assertFalse("different n's should make instances not equal", u.equals(t));
208         assertTrue("different n's should make hashcodes different", 
209                 u.hashCode() != t.hashCode());
210 
211         //Add data in same order to t
212         t.addValue(2d);
213         t.addValue(1d);
214         t.addValue(3d);
215         t.addValue(4d);
216         assertTrue("summaries based on same data should be equal", t.equals(u));
217         assertTrue("summaries based on same data should be equal", u.equals(t));
218         assertEquals("summaries based on same data should have same hashcodes", 
219                 u.hashCode(), t.hashCode());   
220 
221         // Clear and make sure summaries are indistinguishable from empty summary
222         u.clear();
223         t.clear();
224         assertTrue("empty instances should be equal", t.equals(u));
225         assertTrue("empty instances should be equal", u.equals(t));
226         assertEquals("empty hash code", emptyHash, t.hashCode());
227         assertEquals("empty hash code", emptyHash, u.hashCode());
228     }
229     
230     public void testCopy() throws Exception {
231         SummaryStatistics u = createSummaryStatistics();
232         u.addValue(2d);
233         u.addValue(1d);
234         u.addValue(3d);
235         u.addValue(4d);
236         SummaryStatistics v = new SummaryStatistics(u);
237         assertEquals(u, v);
238         assertEquals(v, u);
239         assertTrue(v.geoMean == v.getGeoMeanImpl());
240         assertTrue(v.mean == v.getMeanImpl());
241         assertTrue(v.min == v.getMinImpl());
242         assertTrue(v.max == v.getMaxImpl());
243         assertTrue(v.sum == v.getSumImpl());
244         assertTrue(v.sumsq == v.getSumsqImpl());
245         assertTrue(v.sumLog == v.getSumLogImpl());
246         assertTrue(v.variance == v.getVarianceImpl());
247         
248         // Make sure both behave the same with additional values added
249         u.addValue(7d);
250         u.addValue(9d);
251         u.addValue(11d);
252         u.addValue(23d);
253         v.addValue(7d);
254         v.addValue(9d);
255         v.addValue(11d);
256         v.addValue(23d);
257         assertEquals(u, v);
258         assertEquals(v, u);
259         
260         // Check implementation pointers are preserved
261         u.clear();
262         u.setSumImpl(new Sum());
263         SummaryStatistics.copy(u,v);
264         assertEquals(u.sum, v.sum);
265         assertEquals(u.getSumImpl(), v.getSumImpl());
266         
267     }
268 
269     private void verifySummary(SummaryStatistics u, StatisticalSummary s) {
270         assertEquals("N",s.getN(),u.getN());
271         TestUtils.assertEquals("sum",s.getSum(),u.getSum(),tolerance);
272         TestUtils.assertEquals("var",s.getVariance(),u.getVariance(),tolerance);
273         TestUtils.assertEquals("std",s.getStandardDeviation(),u.getStandardDeviation(),tolerance);
274         TestUtils.assertEquals("mean",s.getMean(),u.getMean(),tolerance);
275         TestUtils.assertEquals("min",s.getMin(),u.getMin(),tolerance);
276         TestUtils.assertEquals("max",s.getMax(),u.getMax(),tolerance);   
277     }
278 
279     public void testSetterInjection() throws Exception {
280         SummaryStatistics u = createSummaryStatistics();
281         u.setMeanImpl(new Sum());
282         u.setSumLogImpl(new Sum());
283         u.addValue(1);
284         u.addValue(3);
285         assertEquals(4, u.getMean(), 1E-14);
286         assertEquals(4, u.getSumOfLogs(), 1E-14);
287         assertEquals(Math.exp(2), u.getGeometricMean(), 1E-14);
288         u.clear();
289         u.addValue(1);
290         u.addValue(2);
291         assertEquals(3, u.getMean(), 1E-14);
292         u.clear();
293         u.setMeanImpl(new Mean()); // OK after clear
294     }
295     
296     public void testSetterIllegalState() throws Exception {
297         SummaryStatistics u = createSummaryStatistics();
298         u.addValue(1);
299         u.addValue(3);
300         try {
301             u.setMeanImpl(new Sum());
302             fail("Expecting IllegalStateException");
303         } catch (IllegalStateException ex) {
304             // expected
305         }
306     }
307 }