Change the default value for those UnivariateStatistics that have a conventional value on the empty set.

JIRA: MATH-373



git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/trunk@991812 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
William Barker 2010-09-02 04:49:11 +00:00
parent 495f04bcda
commit bfe4623c65
12 changed files with 150 additions and 75 deletions

View File

@ -79,29 +79,54 @@ public abstract class AbstractUnivariateStatistic
final double[] values,
final int begin,
final int length) {
return test(values, begin, length, false);
}
/**
* This method is used by <code>evaluate(double[], int, int)</code> methods
* to verify that the input parameters designate a subarray of positive length.
* <p>
* <ul>
* <li>returns <code>true</code> iff the parameters designate a subarray of
* non-negative length</li>
* <li>throws <code>IllegalArgumentException</code> if the array is null or
* or the indices are invalid</li>
* <li>returns <code>false</li> if the array is non-null, but
* <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code>
* </ul></p>
*
* @param values the input array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @param allowEmpty if <code>true</code> then zero length arrays are allowed
* @return true if the parameters are valid
* @throws IllegalArgumentException if the indices are invalid or the array is null
* @since 3.0
*/
protected boolean test(final double[] values, final int begin, final int length, final boolean allowEmpty){
if (values == null) {
throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
}
if (values == null) {
throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
}
if (begin < 0) {
throw new NotPositiveException(LocalizedFormats.START_POSITION, begin);
}
if (begin < 0) {
throw new NotPositiveException(LocalizedFormats.START_POSITION, begin);
}
if (length < 0) {
throw new NotPositiveException(LocalizedFormats.LENGTH, length);
}
if (length < 0) {
throw new NotPositiveException(LocalizedFormats.LENGTH, length);
}
if (begin + length > values.length) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.SUBARRAY_ENDS_AFTER_ARRAY_END);
}
if (begin + length > values.length) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.SUBARRAY_ENDS_AFTER_ARRAY_END);
}
if (length == 0) {
return false;
}
if (length == 0 && !allowEmpty) {
return false;
}
return true;
return true;
}
@ -139,6 +164,40 @@ public abstract class AbstractUnivariateStatistic
final double[] weights,
final int begin,
final int length) {
return test(values, weights, begin, length, false);
}
/**
* This method is used by <code>evaluate(double[], double[], int, int)</code> methods
* to verify that the begin and length parameters designate a subarray of positive length
* and the weights are all non-negative, non-NaN, finite, and not all zero.
* <p>
* <ul>
* <li>returns <code>true</code> iff the parameters designate a subarray of
* non-negative length and the weights array contains legitimate values.</li>
* <li>throws <code>IllegalArgumentException</code> if any of the following are true:
* <ul><li>the values array is null</li>
* <li>the weights array is null</li>
* <li>the weights array does not have the same length as the values array</li>
* <li>the weights array contains one or more infinite values</li>
* <li>the weights array contains one or more NaN values</li>
* <li>the weights array contains negative values</li>
* <li>the start and length arguments do not determine a valid array</li></ul>
* </li>
* <li>returns <code>false</li> if the array is non-null, but
* <code>length</code> is 0 unless <code>allowEmpty</code> is <code>true</code>.
* </ul></p>
*
* @param values the input array
* @param weights the weights array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @param allowEmpty if <code>true</code> than allow zero length arrays to pass
* @return true if the parameters are valid
* @throws IllegalArgumentException if the indices are invalid or the array is null
* @since 3.0
*/
protected boolean test(final double[] values, final double[] weights, final int begin, final int length, final boolean allowEmpty){
if (weights == null) {
throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
@ -172,7 +231,7 @@ public abstract class AbstractUnivariateStatistic
LocalizedFormats.WEIGHT_AT_LEAST_ONE_NON_ZERO);
}
return test(values, begin, length);
return test(values, begin, length, allowEmpty);
}
}

View File

@ -25,7 +25,8 @@ import org.apache.commons.math.util.FastMath;
/**
* Returns the product of the available values.
* <p>
* If there are no values in the dataset, or any of the values are
* If there are no values in the dataset, then 1 is returned.
* If any of the values are
* <code>NaN</code>, then <code>NaN</code> is returned.</p>
* <p>
* <strong>Note that this implementation is not synchronized.</strong> If
@ -53,7 +54,7 @@ public class Product extends AbstractStorelessUnivariateStatistic implements Ser
*/
public Product() {
n = 0;
value = Double.NaN;
value = 1;
}
/**
@ -71,11 +72,7 @@ public class Product extends AbstractStorelessUnivariateStatistic implements Ser
*/
@Override
public void increment(final double d) {
if (n == 0) {
value = d;
} else {
value *= d;
}
value *= d;
n++;
}
@ -99,7 +96,7 @@ public class Product extends AbstractStorelessUnivariateStatistic implements Ser
*/
@Override
public void clear() {
value = Double.NaN;
value = 1;
n = 0;
}
@ -113,14 +110,14 @@ public class Product extends AbstractStorelessUnivariateStatistic implements Ser
* @param values the input array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the product of the values or Double.NaN if length = 0
* @return the product of the values or 1 if length = 0
* @throws IllegalArgumentException if the array is null or the array index
* parameters are not valid
*/
@Override
public double evaluate(final double[] values, final int begin, final int length) {
double product = Double.NaN;
if (test(values, begin, length)) {
if (test(values, begin, length, true)) {
product = 1.0;
for (int i = begin; i < begin + length; i++) {
product *= values[i];
@ -153,14 +150,14 @@ public class Product extends AbstractStorelessUnivariateStatistic implements Ser
* @param weights the weights array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the product of the values or Double.NaN if length = 0
* @return the product of the values or 1 if length = 0
* @throws IllegalArgumentException if the parameters are not valid
* @since 2.1
*/
public double evaluate(final double[] values, final double[] weights,
final int begin, final int length) {
double product = Double.NaN;
if (test(values, weights, begin, length)) {
if (test(values, weights, begin, length, true)) {
product = 1.0;
for (int i = begin; i < begin + length; i++) {
product *= FastMath.pow(values[i], weights[i]);

View File

@ -24,7 +24,8 @@ import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStati
/**
* Returns the sum of the available values.
* <p>
* If there are no values in the dataset, or any of the values are
* If there are no values in the dataset, then 0 is returned.
* If any of the values are
* <code>NaN</code>, then <code>NaN</code> is returned.</p>
* <p>
* <strong>Note that this implementation is not synchronized.</strong> If
@ -52,7 +53,7 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
*/
public Sum() {
n = 0;
value = Double.NaN;
value = 0;
}
/**
@ -70,11 +71,7 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
*/
@Override
public void increment(final double d) {
if (n == 0) {
value = d;
} else {
value += d;
}
value += d;
n++;
}
@ -98,13 +95,13 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
*/
@Override
public void clear() {
value = Double.NaN;
value = 0;
n = 0;
}
/**
* The sum of the entries in the specified portion of
* the input array, or <code>Double.NaN</code> if the designated subarray
* the input array, or 0 if the designated subarray
* is empty.
* <p>
* Throws <code>IllegalArgumentException</code> if the array is null.</p>
@ -112,14 +109,14 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
* @param values the input array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the sum of the values or Double.NaN if length = 0
* @return the sum of the values or 0 if length = 0
* @throws IllegalArgumentException if the array is null or the array index
* parameters are not valid
*/
@Override
public double evaluate(final double[] values, final int begin, final int length) {
double sum = Double.NaN;
if (test(values, begin, length)) {
if (test(values, begin, length, true)) {
sum = 0.0;
for (int i = begin; i < begin + length; i++) {
sum += values[i];
@ -130,7 +127,7 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
/**
* The weighted sum of the entries in the specified portion of
* the input array, or <code>Double.NaN</code> if the designated subarray
* the input array, or 0 if the designated subarray
* is empty.
* <p>
* Throws <code>IllegalArgumentException</code> if any of the following are true:
@ -151,14 +148,14 @@ public class Sum extends AbstractStorelessUnivariateStatistic implements Seriali
* @param weights the weights array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the sum of the values or Double.NaN if length = 0
* @return the sum of the values or 0 if length = 0
* @throws IllegalArgumentException if the parameters are not valid
* @since 2.1
*/
public double evaluate(final double[] values, final double[] weights,
final int begin, final int length) {
double sum = Double.NaN;
if (test(values, weights, begin, length)) {
if (test(values, weights, begin, length, true)) {
sum = 0.0;
for (int i = begin; i < begin + length; i++) {
sum += values[i] * weights[i];

View File

@ -24,7 +24,7 @@ import org.apache.commons.math.util.FastMath;
/**
* Returns the sum of the natural logs for this collection of values.
* <p>
* Uses {@link java.lang.Math#log(double)} to compute the logs. Therefore,
* Uses {@link org.apache.commons.Math.util.FastMath#log(double)} to compute the logs. Therefore,
* <ul>
* <li>If any of values are < 0, the result is <code>NaN.</code></li>
* <li>If all values are non-negative and less than
@ -87,11 +87,7 @@ public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements S
*/
@Override
public double getResult() {
if (n > 0) {
return value;
} else {
return Double.NaN;
}
return value;
}
/**
@ -122,7 +118,7 @@ public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements S
* @param values the input array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the sum of the natural logs of the values or Double.NaN if
* @return the sum of the natural logs of the values or 0 if
* length = 0
* @throws IllegalArgumentException if the array is null or the array index
* parameters are not valid
@ -130,7 +126,7 @@ public class SumOfLogs extends AbstractStorelessUnivariateStatistic implements S
@Override
public double evaluate(final double[] values, final int begin, final int length) {
double sumLog = Double.NaN;
if (test(values, begin, length)) {
if (test(values, begin, length, true)) {
sumLog = 0.0;
for (int i = begin; i < begin + length; i++) {
sumLog += FastMath.log(values[i]);

View File

@ -23,7 +23,8 @@ import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStati
/**
* Returns the sum of the squares of the available values.
* <p>
* If there are no values in the dataset, or any of the values are
* If there are no values in the dataset, then 0 is returned.
* If any of the values are
* <code>NaN</code>, then <code>NaN</code> is returned.</p>
* <p>
* <strong>Note that this implementation is not synchronized.</strong> If
@ -51,7 +52,7 @@ public class SumOfSquares extends AbstractStorelessUnivariateStatistic implement
*/
public SumOfSquares() {
n = 0;
value = Double.NaN;
value = 0;
}
/**
@ -69,11 +70,7 @@ public class SumOfSquares extends AbstractStorelessUnivariateStatistic implement
*/
@Override
public void increment(final double d) {
if (n == 0) {
value = d * d;
} else {
value += d * d;
}
value += d * d;
n++;
}
@ -97,7 +94,7 @@ public class SumOfSquares extends AbstractStorelessUnivariateStatistic implement
*/
@Override
public void clear() {
value = Double.NaN;
value = 0;
n = 0;
}
@ -111,14 +108,14 @@ public class SumOfSquares extends AbstractStorelessUnivariateStatistic implement
* @param values the input array
* @param begin index of the first array element to include
* @param length the number of elements to include
* @return the sum of the squares of the values or Double.NaN if length = 0
* @return the sum of the squares of the values or 0 if length = 0
* @throws IllegalArgumentException if the array is null or the array index
* parameters are not valid
*/
@Override
public double evaluate(final double[] values,final int begin, final int length) {
double sumSq = Double.NaN;
if (test(values, begin, length)) {
if (test(values, begin, length, true)) {
sumSq = 0.0;
for (int i = begin; i < begin + length; i++) {
sumSq += values[i] * values[i];

View File

@ -131,8 +131,8 @@ public final class StatUtilsTest extends TestCase {
// test empty
x = new double[] {};
TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance);
TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance);
TestUtils.assertEquals(0, StatUtils.sumSq(x), tolerance);
TestUtils.assertEquals(0, StatUtils.sumSq(x, 0, 0), tolerance);
// test one
x = new double[] {two};
@ -165,8 +165,8 @@ public final class StatUtilsTest extends TestCase {
// test empty
x = new double[] {};
TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance);
TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance);
TestUtils.assertEquals(1, StatUtils.product(x), tolerance);
TestUtils.assertEquals(1, StatUtils.product(x, 0, 0), tolerance);
// test one
x = new double[] {two};
@ -199,8 +199,8 @@ public final class StatUtilsTest extends TestCase {
// test empty
x = new double[] {};
TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance);
TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance);
TestUtils.assertEquals(0, StatUtils.sumLog(x), tolerance);
TestUtils.assertEquals(0, StatUtils.sumLog(x, 0, 0), tolerance);
// test one
x = new double[] {two};

View File

@ -45,6 +45,7 @@ public class AbstractUnivariateStatisticTest extends TestCase {
}
}
assertTrue(testStatistic.test(singletonArray, 0, 1));
assertTrue(testStatistic.test(singletonArray, 0, 0, true));
}
public void testTestNegative() {

View File

@ -68,11 +68,15 @@ public abstract class StorelessUnivariateStatisticAbstractTest
statistic.clear();
// Cleared
assertTrue(Double.isNaN(statistic.getResult()));
checkClearValue(statistic);
assertEquals(0, statistic.getN());
}
protected void checkClearValue(StorelessUnivariateStatistic statistic){
assertTrue(Double.isNaN(statistic.getResult()));
}
public void testSerialization() throws Exception {
StorelessUnivariateStatistic statistic =
@ -94,7 +98,7 @@ public abstract class StorelessUnivariateStatisticAbstractTest
statistic.clear();
assertTrue(Double.isNaN(statistic.getResult()));
checkClearValue(statistic);
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.commons.math.stat.descriptive.summary;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
@ -65,7 +66,7 @@ public class ProductTest extends StorelessUnivariateStatisticAbstractTest{
public void testSpecialValues() {
Product product = new Product();
assertTrue(Double.isNaN(product.getResult()));
assertEquals(1, product.getResult(), 0);
product.increment(1);
assertEquals(1, product.getResult(), 0);
product.increment(Double.POSITIVE_INFINITY);
@ -83,5 +84,10 @@ public class ProductTest extends StorelessUnivariateStatisticAbstractTest{
assertEquals(expectedWeightedValue(), product.evaluate(testArray, testWeightsArray, 0, testArray.length),getTolerance());
assertEquals(expectedValue(), product.evaluate(testArray, unitWeightsArray, 0, testArray.length), getTolerance());
}
protected void checkClearValue(StorelessUnivariateStatistic statistic){
assertEquals(1, statistic.getResult(), 0);
}
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.commons.math.stat.descriptive.summary;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
@ -53,7 +54,7 @@ public class SumLogTest extends StorelessUnivariateStatisticAbstractTest{
public void testSpecialValues() {
SumOfLogs sum = new SumOfLogs();
// empty
assertTrue(Double.isNaN(sum.getResult()));
assertEquals(0, sum.getResult(), 0);
// finite data
sum.increment(1d);
@ -69,7 +70,7 @@ public class SumLogTest extends StorelessUnivariateStatisticAbstractTest{
// clear
sum.clear();
assertTrue(Double.isNaN(sum.getResult()));
assertEquals(0, sum.getResult(), 0);
// positive infinity by itself
sum.increment(Double.POSITIVE_INFINITY);
@ -79,5 +80,10 @@ public class SumLogTest extends StorelessUnivariateStatisticAbstractTest{
sum.increment(-2d);
assertTrue(Double.isNaN(sum.getResult()));
}
protected void checkClearValue(StorelessUnivariateStatistic statistic){
assertEquals(0, statistic.getResult(), 0);
}
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.commons.math.stat.descriptive.summary;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
@ -53,7 +54,7 @@ public class SumSqTest extends StorelessUnivariateStatisticAbstractTest{
public void testSpecialValues() {
SumOfSquares sumSq = new SumOfSquares();
assertTrue(Double.isNaN(sumSq.getResult()));
assertEquals(0, sumSq.getResult(), 0);
sumSq.increment(2d);
assertEquals(4d, sumSq.getResult(), 0);
sumSq.increment(Double.POSITIVE_INFINITY);
@ -65,5 +66,10 @@ public class SumSqTest extends StorelessUnivariateStatisticAbstractTest{
sumSq.increment(1);
assertTrue(Double.isNaN(sumSq.getResult()));
}
protected void checkClearValue(StorelessUnivariateStatistic statistic){
assertEquals(0, statistic.getResult(), 0);
}
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.commons.math.stat.descriptive.summary;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatistic;
import org.apache.commons.math.stat.descriptive.StorelessUnivariateStatisticAbstractTest;
import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
@ -57,7 +58,7 @@ public class SumTest extends StorelessUnivariateStatisticAbstractTest{
public void testSpecialValues() {
Sum sum = new Sum();
assertTrue(Double.isNaN(sum.getResult()));
assertEquals(0, sum.getResult(), 0);
sum.increment(1);
assertEquals(1, sum.getResult(), 0);
sum.increment(Double.POSITIVE_INFINITY);
@ -73,5 +74,10 @@ public class SumTest extends StorelessUnivariateStatisticAbstractTest{
assertEquals(expectedWeightedValue(), sum.evaluate(testArray, testWeightsArray, 0, testArray.length), getTolerance());
assertEquals(expectedValue(), sum.evaluate(testArray, unitWeightsArray, 0, testArray.length), getTolerance());
}
protected void checkClearValue(StorelessUnivariateStatistic statistic){
assertEquals(0, statistic.getResult(), 0);
}
}