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.descriptive;
018    
019    
020    import junit.framework.Test;
021    import junit.framework.TestCase;
022    import junit.framework.TestSuite;
023    
024    import org.apache.commons.math.TestUtils;
025    import org.apache.commons.math.stat.descriptive.moment.Mean;
026    import org.apache.commons.math.stat.descriptive.summary.Sum;
027    /**
028     * Test cases for the {@link SummaryStatistics} class.
029     *
030     * @version $Revision: 720030 $ $Date: 2008-11-23 13:47:50 -0500 (Sun, 23 Nov 2008) $
031     */
032    
033    public class SummaryStatisticsTest extends TestCase {
034    
035        private double one = 1;
036        private float twoF = 2;
037        private long twoL = 2;
038        private int three = 3;
039        private double mean = 2;
040        private double sumSq = 18;
041        private double sum = 8;
042        private double var = 0.666666666666666666667;
043        private double std = Math.sqrt(var);
044        private double n = 4;
045        private double min = 1;
046        private double max = 3;
047        private double tolerance = 10E-15;
048    
049        public static Test suite() {
050            TestSuite suite = new TestSuite(SummaryStatisticsTest.class);
051            suite.setName("SummaryStatistics tests");
052            return suite;
053        }
054    
055        public SummaryStatisticsTest(String name) {
056            super(name);
057        }
058        
059        protected SummaryStatistics createSummaryStatistics() {
060            return new SummaryStatistics();
061        }
062    
063        /** test stats */
064        public void testStats() {
065            SummaryStatistics u = createSummaryStatistics();
066            assertEquals("total count",0,u.getN(),tolerance);
067            u.addValue(one);
068            u.addValue(twoF);
069            u.addValue(twoL);
070            u.addValue(three);
071            assertEquals("N",n,u.getN(),tolerance);
072            assertEquals("sum",sum,u.getSum(),tolerance);
073            assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
074            assertEquals("var",var,u.getVariance(),tolerance);
075            assertEquals("std",std,u.getStandardDeviation(),tolerance);
076            assertEquals("mean",mean,u.getMean(),tolerance);
077            assertEquals("min",min,u.getMin(),tolerance);
078            assertEquals("max",max,u.getMax(),tolerance);
079            u.clear();
080            assertEquals("total count",0,u.getN(),tolerance);    
081        }     
082    
083        public void testN0andN1Conditions() throws Exception {
084            SummaryStatistics u = createSummaryStatistics();
085            assertTrue("Mean of n = 0 set should be NaN", 
086                    Double.isNaN( u.getMean() ) );
087            assertTrue("Standard Deviation of n = 0 set should be NaN", 
088                    Double.isNaN( u.getStandardDeviation() ) );
089            assertTrue("Variance of n = 0 set should be NaN", 
090                    Double.isNaN(u.getVariance() ) );
091    
092            /* n=1 */
093            u.addValue(one);
094            assertTrue("mean should be one (n = 1)", 
095                    u.getMean() == one);
096            assertTrue("geometric should be one (n = 1) instead it is " + u.getGeometricMean(), 
097                    u.getGeometricMean() == one);
098            assertTrue("Std should be zero (n = 1)", 
099                    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    }