added SynchronizedSummaryStatistics class (and tests)

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@608839 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Luc Maisonobe 2008-01-04 13:49:14 +00:00
parent 91f0d2a12c
commit dc2a102e3c
5 changed files with 428 additions and 204 deletions

View File

@ -0,0 +1,149 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.stat.descriptive;
/**
* Implementation of
* {@link org.apache.commons.math.stat.descriptive.SummaryStatistics} that
* is safe to use in a multithreaded environment. Multiple threads can safely
* operate on a single instance without causing runtime exceptions due to race
* conditions. In effect, this implementation makes modification and access
* methods atomic operations for a single instance. That is to say, as one
* thread is computing a statistic from the instance, no other thread can modify
* the instance nor compute another statistic.
*
* @since 1.2
* @version $Revision: 602304 $ $Date: 2007-12-08 03:48:39 +0100 (sam., 08 déc. 2007) $
*/
public class SynchronizedSummaryStatistics extends SummaryStatistics {
/** Serialization UID */
private static final long serialVersionUID = 1909861009042253704L;
/**
* Construct a SynchronizedSummaryStatistics instance
*/
public SynchronizedSummaryStatistics() {
super();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getSummary()
*/
public synchronized StatisticalSummary getSummary() {
return super.getSummary();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#addValue(double)
*/
public synchronized void addValue(double value) {
super.addValue(value);
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getN()
*/
public synchronized long getN() {
return super.getN();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getSum()
*/
public synchronized double getSum() {
return super.getSum();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getSumsq()
*/
public synchronized double getSumsq() {
return super.getSumsq();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getMean()
*/
public synchronized double getMean() {
return super.getMean();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getStandardDeviation()
*/
public synchronized double getStandardDeviation() {
return super.getStandardDeviation();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getVariance()
*/
public synchronized double getVariance() {
return super.getVariance();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getMax()
*/
public synchronized double getMax() {
return super.getMax();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getMin()
*/
public synchronized double getMin() {
return super.getMin();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#getGeometricMean()
*/
public synchronized double getGeometricMean() {
return super.getGeometricMean();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#toString()
*/
public synchronized String toString() {
return super.toString();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#clear()
*/
public synchronized void clear() {
super.clear();
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#equals(Object)
*/
public synchronized boolean equals(Object object) {
return super.equals(object);
}
/**
* @see org.apache.commons.math.stat.descriptive.SummaryStatistics#hashCode()
*/
public synchronized int hashCode() {
return super.hashCode();
}
}

View File

@ -0,0 +1,227 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.math.stat.descriptive;
import junit.framework.TestCase;
import org.apache.commons.math.TestUtils;
/**
* Test cases for the {@link SummaryStatisticsImpl} class.
*
* @version $Revision: 602305 $ $Date: 2007-12-08 03:51:23 +0100 (sam., 08 déc. 2007) $
* @deprecated should be moved down into SummaryStatisticsTest
* when SummaryStatisticsImpl is removed in 2.0
*/
public abstract class SummaryStatisticsAbstractTest extends TestCase {
private double one = 1;
private float twoF = 2;
private long twoL = 2;
private int three = 3;
private double mean = 2;
private double sumSq = 18;
private double sum = 8;
private double var = 0.666666666666666666667;
private double std = Math.sqrt(var);
private double n = 4;
private double min = 1;
private double max = 3;
private double tolerance = 10E-15;
protected SummaryStatistics u = null;
public SummaryStatisticsAbstractTest(String name) {
super(name);
}
protected abstract SummaryStatistics createSummaryStatistics();
public void setUp() {
u = createSummaryStatistics();
}
/** test stats */
public void testStats() {
assertEquals("total count",0,u.getN(),tolerance);
u.addValue(one);
u.addValue(twoF);
u.addValue(twoL);
u.addValue(three);
assertEquals("N",n,u.getN(),tolerance);
assertEquals("sum",sum,u.getSum(),tolerance);
assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
assertEquals("var",var,u.getVariance(),tolerance);
assertEquals("std",std,u.getStandardDeviation(),tolerance);
assertEquals("mean",mean,u.getMean(),tolerance);
assertEquals("min",min,u.getMin(),tolerance);
assertEquals("max",max,u.getMax(),tolerance);
u.clear();
assertEquals("total count",0,u.getN(),tolerance);
}
public void testN0andN1Conditions() throws Exception {
assertTrue("Mean of n = 0 set should be NaN",
Double.isNaN( u.getMean() ) );
assertTrue("Standard Deviation of n = 0 set should be NaN",
Double.isNaN( u.getStandardDeviation() ) );
assertTrue("Variance of n = 0 set should be NaN",
Double.isNaN(u.getVariance() ) );
/* n=1 */
u.addValue(one);
assertTrue("mean should be one (n = 1)",
u.getMean() == one);
assertTrue("geometric should be one (n = 1) instead it is " + u.getGeometricMean(),
u.getGeometricMean() == one);
assertTrue("Std should be zero (n = 1)",
u.getStandardDeviation() == 0.0);
assertTrue("variance should be zero (n = 1)",
u.getVariance() == 0.0);
/* n=2 */
u.addValue(twoF);
assertTrue("Std should not be zero (n = 2)",
u.getStandardDeviation() != 0.0);
assertTrue("variance should not be zero (n = 2)",
u.getVariance() != 0.0);
}
public void testProductAndGeometricMean() throws Exception {
u.addValue( 1.0 );
u.addValue( 2.0 );
u.addValue( 3.0 );
u.addValue( 4.0 );
assertEquals( "Geometric mean not expected", 2.213364,
u.getGeometricMean(), 0.00001 );
}
public void testNaNContracts() {
assertTrue("mean not NaN",Double.isNaN(u.getMean()));
assertTrue("min not NaN",Double.isNaN(u.getMin()));
assertTrue("std dev not NaN",Double.isNaN(u.getStandardDeviation()));
assertTrue("var not NaN",Double.isNaN(u.getVariance()));
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
u.addValue(1.0);
assertEquals( "mean not expected", 1.0,
u.getMean(), Double.MIN_VALUE);
assertEquals( "variance not expected", 0.0,
u.getVariance(), Double.MIN_VALUE);
assertEquals( "geometric mean not expected", 1.0,
u.getGeometricMean(), Double.MIN_VALUE);
u.addValue(-1.0);
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
u.addValue(0.0);
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
//FiXME: test all other NaN contract specs
}
public void testGetSummary() {
StatisticalSummary summary = u.getSummary();
verifySummary(summary);
u.addValue(1d);
summary = u.getSummary();
verifySummary(summary);
u.addValue(2d);
summary = u.getSummary();
verifySummary(summary);
u.addValue(2d);
summary = u.getSummary();
verifySummary(summary);
}
public void testSerialization() {
// Empty test
TestUtils.checkSerializedEquality(u);
SummaryStatistics s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
StatisticalSummary summary = s.getSummary();
verifySummary(summary);
// Add some data
u.addValue(2d);
u.addValue(1d);
u.addValue(3d);
u.addValue(4d);
u.addValue(5d);
// Test again
TestUtils.checkSerializedEquality(u);
s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
summary = s.getSummary();
verifySummary(summary);
}
public void testEqualsAndHashCode() {
SummaryStatistics t = null;
int emptyHash = u.hashCode();
assertTrue("reflexive", u.equals(u));
assertFalse("non-null compared to null", u.equals(t));
assertFalse("wrong type", u.equals(new Double(0)));
t = createSummaryStatistics();
assertTrue("empty instances should be equal", t.equals(u));
assertTrue("empty instances should be equal", u.equals(t));
assertEquals("empty hash code", emptyHash, t.hashCode());
// Add some data to u
u.addValue(2d);
u.addValue(1d);
u.addValue(3d);
u.addValue(4d);
assertFalse("different n's should make instances not equal", t.equals(u));
assertFalse("different n's should make instances not equal", u.equals(t));
assertTrue("different n's should make hashcodes different",
u.hashCode() != t.hashCode());
//Add data in different order to t, should not affect identity or hashcode
t.addValue(4d);
t.addValue(2d);
t.addValue(3d);
t.addValue(1d);
assertTrue("summaries based on same data should be equal", t.equals(u));
assertTrue("summaries based on same data should be equal", u.equals(t));
assertEquals("summaries based on same data should have same hashcodes",
u.hashCode(), t.hashCode());
// Clear and make sure summaries are indistinguishable from empty summary
u.clear();
t.clear();
assertTrue("empty instances should be equal", t.equals(u));
assertTrue("empty instances should be equal", u.equals(t));
assertEquals("empty hash code", emptyHash, t.hashCode());
assertEquals("empty hash code", emptyHash, u.hashCode());
}
private void verifySummary(StatisticalSummary s) {
assertEquals("N",s.getN(),u.getN());
TestUtils.assertEquals("sum",s.getSum(),u.getSum(),tolerance);
TestUtils.assertEquals("var",s.getVariance(),u.getVariance(),tolerance);
TestUtils.assertEquals("std",s.getStandardDeviation(),u.getStandardDeviation(),tolerance);
TestUtils.assertEquals("mean",s.getMean(),u.getMean(),tolerance);
TestUtils.assertEquals("min",s.getMin(),u.getMin(),tolerance);
TestUtils.assertEquals("max",s.getMax(),u.getMax(),tolerance);
}
}

View File

@ -18,214 +18,26 @@ package org.apache.commons.math.stat.descriptive;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.math.TestUtils;
/**
* Test cases for the {@link SummaryStatisticsImpl} class.
*
* @deprecated - to be removed in 2.0 with SummaryStatisticsImpl
* @version $Revision$ $Date$
*/
public final class SummaryStatisticsImplTest extends TestCase {
private double one = 1;
private float twoF = 2;
private long twoL = 2;
private int three = 3;
private double mean = 2;
private double sumSq = 18;
private double sum = 8;
private double var = 0.666666666666666666667;
private double std = Math.sqrt(var);
private double n = 4;
private double min = 1;
private double max = 3;
private double tolerance = 10E-15;
protected SummaryStatistics u = null;
public final class SummaryStatisticsImplTest extends SummaryStatisticsAbstractTest {
public SummaryStatisticsImplTest(String name) {
super(name);
}
public void setUp() {
u = SummaryStatistics.newInstance();
}
public static Test suite() {
TestSuite suite = new TestSuite(SummaryStatisticsImplTest.class);
suite.setName("Frequency Tests");
suite.setName("SummaryStatisticsImpl Tests");
return suite;
}
/** test stats */
public void testStats() {
assertEquals("total count",0,u.getN(),tolerance);
u.addValue(one);
u.addValue(twoF);
u.addValue(twoL);
u.addValue(three);
assertEquals("N",n,u.getN(),tolerance);
assertEquals("sum",sum,u.getSum(),tolerance);
assertEquals("sumsq",sumSq,u.getSumsq(),tolerance);
assertEquals("var",var,u.getVariance(),tolerance);
assertEquals("std",std,u.getStandardDeviation(),tolerance);
assertEquals("mean",mean,u.getMean(),tolerance);
assertEquals("min",min,u.getMin(),tolerance);
assertEquals("max",max,u.getMax(),tolerance);
u.clear();
assertEquals("total count",0,u.getN(),tolerance);
}
public void testN0andN1Conditions() throws Exception {
assertTrue("Mean of n = 0 set should be NaN",
Double.isNaN( u.getMean() ) );
assertTrue("Standard Deviation of n = 0 set should be NaN",
Double.isNaN( u.getStandardDeviation() ) );
assertTrue("Variance of n = 0 set should be NaN",
Double.isNaN(u.getVariance() ) );
/* n=1 */
u.addValue(one);
assertTrue("mean should be one (n = 1)",
u.getMean() == one);
assertTrue("geometric should be one (n = 1) instead it is " + u.getGeometricMean(),
u.getGeometricMean() == one);
assertTrue("Std should be zero (n = 1)",
u.getStandardDeviation() == 0.0);
assertTrue("variance should be zero (n = 1)",
u.getVariance() == 0.0);
/* n=2 */
u.addValue(twoF);
assertTrue("Std should not be zero (n = 2)",
u.getStandardDeviation() != 0.0);
assertTrue("variance should not be zero (n = 2)",
u.getVariance() != 0.0);
}
public void testProductAndGeometricMean() throws Exception {
u.addValue( 1.0 );
u.addValue( 2.0 );
u.addValue( 3.0 );
u.addValue( 4.0 );
assertEquals( "Geometric mean not expected", 2.213364,
u.getGeometricMean(), 0.00001 );
}
public void testNaNContracts() {
assertTrue("mean not NaN",Double.isNaN(u.getMean()));
assertTrue("min not NaN",Double.isNaN(u.getMin()));
assertTrue("std dev not NaN",Double.isNaN(u.getStandardDeviation()));
assertTrue("var not NaN",Double.isNaN(u.getVariance()));
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
u.addValue(1.0);
assertEquals( "mean not expected", 1.0,
u.getMean(), Double.MIN_VALUE);
assertEquals( "variance not expected", 0.0,
u.getVariance(), Double.MIN_VALUE);
assertEquals( "geometric mean not expected", 1.0,
u.getGeometricMean(), Double.MIN_VALUE);
u.addValue(-1.0);
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
u.addValue(0.0);
assertTrue("geom mean not NaN",Double.isNaN(u.getGeometricMean()));
//FiXME: test all other NaN contract specs
}
public void testGetSummary() {
StatisticalSummary summary = u.getSummary();
verifySummary(summary);
u.addValue(1d);
summary = u.getSummary();
verifySummary(summary);
u.addValue(2d);
summary = u.getSummary();
verifySummary(summary);
u.addValue(2d);
summary = u.getSummary();
verifySummary(summary);
}
public void testSerialization() {
// Empty test
TestUtils.checkSerializedEquality(u);
SummaryStatistics s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
StatisticalSummary summary = s.getSummary();
verifySummary(summary);
// Add some data
u.addValue(2d);
u.addValue(1d);
u.addValue(3d);
u.addValue(4d);
u.addValue(5d);
// Test again
TestUtils.checkSerializedEquality(u);
s = (SummaryStatistics) TestUtils.serializeAndRecover(u);
summary = s.getSummary();
verifySummary(summary);
}
public void testEqualsAndHashCode() {
SummaryStatistics t = null;
int emptyHash = u.hashCode();
assertTrue("reflexive", u.equals(u));
assertFalse("non-null compared to null", u.equals(t));
assertFalse("wrong type", u.equals(new Double(0)));
t = SummaryStatistics.newInstance();
assertTrue("empty instances should be equal", t.equals(u));
assertTrue("empty instances should be equal", u.equals(t));
assertEquals("empty hash code", emptyHash, t.hashCode());
// Add some data to u
u.addValue(2d);
u.addValue(1d);
u.addValue(3d);
u.addValue(4d);
assertFalse("different n's should make instances not equal", t.equals(u));
assertFalse("different n's should make instances not equal", u.equals(t));
assertTrue("different n's should make hashcodes different",
u.hashCode() != t.hashCode());
//Add data in different order to t, should not affect identity or hashcode
t.addValue(4d);
t.addValue(2d);
t.addValue(3d);
t.addValue(1d);
assertTrue("summaries based on same data should be equal", t.equals(u));
assertTrue("summaries based on same data should be equal", u.equals(t));
assertEquals("summaries based on same data should have same hashcodes",
u.hashCode(), t.hashCode());
// Clear and make sure summaries are indistinguishable from empty summary
u.clear();
t.clear();
assertTrue("empty instances should be equal", t.equals(u));
assertTrue("empty instances should be equal", u.equals(t));
assertEquals("empty hash code", emptyHash, t.hashCode());
assertEquals("empty hash code", emptyHash, u.hashCode());
}
private void verifySummary(StatisticalSummary s) {
assertEquals("N",s.getN(),u.getN());
TestUtils.assertEquals("sum",s.getSum(),u.getSum(),tolerance);
TestUtils.assertEquals("var",s.getVariance(),u.getVariance(),tolerance);
TestUtils.assertEquals("std",s.getStandardDeviation(),u.getStandardDeviation(),tolerance);
TestUtils.assertEquals("mean",s.getMean(),u.getMean(),tolerance);
TestUtils.assertEquals("min",s.getMin(),u.getMin(),tolerance);
TestUtils.assertEquals("max",s.getMax(),u.getMax(),tolerance);
protected SummaryStatistics createSummaryStatistics() {
return new SummaryStatisticsImpl();
}
}

View File

@ -21,7 +21,6 @@ import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.apache.commons.math.TestUtils;
import org.apache.commons.math.stat.descriptive.moment.Mean;
/**
* Test cases for the {@link SummaryStatistics} class.
@ -31,23 +30,21 @@ import org.apache.commons.math.stat.descriptive.moment.Mean;
* @version $Revision: 566833 $ $Date: 2007-08-16 13:36:33 -0700 (Thu, 16 Aug 2007) $
*/
public final class SummaryStatisticsTest extends TestCase {
protected SummaryStatistics u = null;
public final class SummaryStatisticsTest extends SummaryStatisticsAbstractTest {
public SummaryStatisticsTest(String name) {
super(name);
}
public void setUp() {
u = new SummaryStatistics();
}
public static Test suite() {
TestSuite suite = new TestSuite(SummaryStatisticsTest.class);
suite.setName("SummaryStatistics tests");
return suite;
}
protected SummaryStatistics createSummaryStatistics() {
return new SummaryStatistics();
}
public void testSetterInjection() throws Exception {
u.setMeanImpl(new sumMean());

View File

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law
* or agreed to in writing, software distributed under the License is
* distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.apache.commons.math.stat.descriptive;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Test cases for the {@link SynchronizedSummaryStatisticsTest} class.
* @version $Revision: 592121 $ $Date: 2007-08-16 15:36:33 -0500 (Thu, 16 Aug
* 2007) $
*/
public final class SynchronizedSummaryStatisticsTest extends SummaryStatisticsAbstractTest {
public SynchronizedSummaryStatisticsTest(String name) {
super(name);
}
public static Test suite() {
TestSuite suite = new TestSuite(SynchronizedSummaryStatisticsTest.class);
suite.setName("SynchronizedSummaryStatistics Tests");
return suite;
}
protected SummaryStatistics createSummaryStatistics() {
return new SynchronizedSummaryStatistics();
}
}