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 }