    1   /*
    2    * Copyright 2003-2004 The Apache Software Foundation.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *      http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.math.stat;
    17
    18  import junit.framework.Test;
    19  import junit.framework.TestCase;
    20  import junit.framework.TestSuite;
    21
    22  import org.apache.commons.math.TestUtils;
    23
    24  /***
    25   * Test cases for the {@link StatUtils} class.
    26   * @version $Revision: 1.19 $ $Date: 2004/07/17 22:01:39 $
    27   */
    28
    29  public final class StatUtilsTest extends TestCase {
    30
    31      private double one = 1;
    32      private float two = 2;
    33      private int three = 3;
    34      private double mean = 2;
    35      private double sumSq = 18;
    36      private double sum = 8;
    37      private double var = 0.666666666666666666667;
    38      private double std = Math.sqrt(var);
    39      private double n = 4;
    40      private double min = 1;
    41      private double max = 3;
    42      private double skewness = 0;
    43      private double kurtosis = 0.5;
    44      private double tolerance = 10E-15;
    45
    46      public StatUtilsTest(String name) {
    47          super(name);
    48      }
    49
    50      public void setUp() {
    51      }
    52
    53      public static Test suite() {
    54          TestSuite suite = new TestSuite(StatUtilsTest.class);
    55          suite.setName("StatUtil Tests");
    56          return suite;
    57      }
    58
    59      /*** test stats */
    60      public void testStats() {
    61          double[] values = new double[] { one, two, two, three };
    62          assertEquals("sum", sum, StatUtils.sum(values), tolerance);
    63          assertEquals("sumsq", sumSq, StatUtils.sumSq(values), tolerance);
    64          assertEquals("var", var, StatUtils.variance(values), tolerance);
    65          assertEquals("var with mean", var, StatUtils.variance(values, mean), tolerance);
    66          assertEquals("mean", mean, StatUtils.mean(values), tolerance);
    67          assertEquals("min", min, StatUtils.min(values), tolerance);
    68          assertEquals("max", max, StatUtils.max(values), tolerance);
    69      }
    70
    71      public void testN0andN1Conditions() throws Exception {
    72          double[] values = new double[0];
    73
    74          assertTrue(
    75              "Mean of n = 0 set should be NaN",
    76              Double.isNaN(StatUtils.mean(values)));
    77          assertTrue(
    78              "Variance of n = 0 set should be NaN",
    79              Double.isNaN(StatUtils.variance(values)));
    80
    81          values = new double[] { one };
    82
    83          assertTrue(
    84              "Mean of n = 1 set should be value of single item n1",
    85              StatUtils.mean(values) == one);
    86          assertTrue(
    87              "Variance of n = 1 set should be zero",
    88              StatUtils.variance(values) == 0);
    89      }
    90
    91      public void testArrayIndexConditions() throws Exception {
    92          double[] values = { 1.0, 2.0, 3.0, 4.0 };
    93
    94          assertEquals(
    95              "Sum not expected",
    96              5.0,
    97              StatUtils.sum(values, 1, 2),
    98              Double.MIN_VALUE);
    99          assertEquals(
    100             "Sum not expected",
    101             3.0,
    102             StatUtils.sum(values, 0, 2),
    103             Double.MIN_VALUE);
    104         assertEquals(
    105             "Sum not expected",
    106             7.0,
    107             StatUtils.sum(values, 2, 2),
    108             Double.MIN_VALUE);
    109
    110         try {
    111             StatUtils.sum(values, 2, 3);
    112             assertTrue("Didn't throw exception", false);
    113         } catch (Exception e) {
    114             assertTrue(true);
    115         }
    116
    117         try {
    118             StatUtils.sum(values, -1, 2);
    119             assertTrue("Didn't throw exception", false);
    120         } catch (Exception e) {
    121             assertTrue(true);
    122         }
    123
    124     }
    125
    126     public void testSumSq() {
    127         double[] x = null;
    128
    129         // test null
    130         try {
    131             StatUtils.sumSq(x);
    132             fail("null is not a valid data array.");
    133         } catch (IllegalArgumentException ex) {
    134             // success
    135         }
    136
    137         try {
    138             StatUtils.sumSq(x, 0, 4);
    139             fail("null is not a valid data array.");
    140         } catch (IllegalArgumentException ex) {
    141             // success
    142         }
    143
    144         // test empty
    145         x = new double[] {};
    146         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance);
    147         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance);
    148
    149         // test one
    150         x = new double[] {two};
    151         TestUtils.assertEquals(4, StatUtils.sumSq(x), tolerance);
    152         TestUtils.assertEquals(4, StatUtils.sumSq(x, 0, 1), tolerance);
    153
    154         // test many
    155         x = new double[] {one, two, two, three};
    156         TestUtils.assertEquals(18, StatUtils.sumSq(x), tolerance);
    157         TestUtils.assertEquals(8, StatUtils.sumSq(x, 1, 2), tolerance);
    158     }
    159
    160     public void testProduct() {
    161         double[] x = null;
    162
    163         // test null
    164         try {
    165             StatUtils.product(x);
    166             fail("null is not a valid data array.");
    167         } catch (IllegalArgumentException ex) {
    168             // success
    169         }
    170
    171         try {
    172             StatUtils.product(x, 0, 4);
    173             fail("null is not a valid data array.");
    174         } catch (IllegalArgumentException ex) {
    175             // success
    176         }
    177
    178         // test empty
    179         x = new double[] {};
    180         TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance);
    181         TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance);
    182
    183         // test one
    184         x = new double[] {two};
    185         TestUtils.assertEquals(two, StatUtils.product(x), tolerance);
    186         TestUtils.assertEquals(two, StatUtils.product(x, 0, 1), tolerance);
    187
    188         // test many
    189         x = new double[] {one, two, two, three};
    190         TestUtils.assertEquals(12, StatUtils.product(x), tolerance);
    191         TestUtils.assertEquals(4, StatUtils.product(x, 1, 2), tolerance);
    192     }
    193
    194     public void testSumLog() {
    195         double[] x = null;
    196
    197         // test null
    198         try {
    199             StatUtils.sumLog(x);
    200             fail("null is not a valid data array.");
    201         } catch (IllegalArgumentException ex) {
    202             // success
    203         }
    204
    205         try {
    206             StatUtils.sumLog(x, 0, 4);
    207             fail("null is not a valid data array.");
    208         } catch (IllegalArgumentException ex) {
    209             // success
    210         }
    211
    212         // test empty
    213         x = new double[] {};
    214         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance);
    215         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance);
    216
    217         // test one
    218         x = new double[] {two};
    219         TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x), tolerance);
    220         TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x, 0, 1), tolerance);
    221
    222         // test many
    223         x = new double[] {one, two, two, three};
    224         TestUtils.assertEquals(Math.log(one) + 2.0 * Math.log(two) + Math.log(three), StatUtils.sumLog(x), tolerance);
    225         TestUtils.assertEquals(2.0 * Math.log(two), StatUtils.sumLog(x, 1, 2), tolerance);
    226     }
    227
    228     public void testMean() {
    229         double[] x = null;
    230
    231         try {
    232             StatUtils.mean(x, 0, 4);
    233             fail("null is not a valid data array.");
    234         } catch (IllegalArgumentException ex) {
    235             // success
    236         }
    237
    238         // test empty
    239         x = new double[] {};
    240         TestUtils.assertEquals(Double.NaN, StatUtils.mean(x, 0, 0), tolerance);
    241
    242         // test one
    243         x = new double[] {two};
    244         TestUtils.assertEquals(two, StatUtils.mean(x, 0, 1), tolerance);
    245
    246         // test many
    247         x = new double[] {one, two, two, three};
    248         TestUtils.assertEquals(2.5, StatUtils.mean(x, 2, 2), tolerance);
    249     }
    250
    251     public void testVariance() {
    252         double[] x = null;
    253
    254         try {
    255             StatUtils.variance(x, 0, 4);
    256             fail("null is not a valid data array.");
    257         } catch (IllegalArgumentException ex) {
    258             // success
    259         }
    260
    261         // test empty
    262         x = new double[] {};
    263         TestUtils.assertEquals(Double.NaN, StatUtils.variance(x, 0, 0), tolerance);
    264
    265         // test one
    266         x = new double[] {two};
    267         TestUtils.assertEquals(0.0, StatUtils.variance(x, 0, 1), tolerance);
    268
    269         // test many
    270         x = new double[] {one, two, two, three};
    271         TestUtils.assertEquals(0.5, StatUtils.variance(x, 2, 2), tolerance);
    272
    273         // test precomputed mean
    274         x = new double[] {one, two, two, three};
    275         TestUtils.assertEquals(0.5, StatUtils.variance(x,2.5, 2, 2), tolerance);
    276     }
    277
    278     public void testMax() {
    279         double[] x = null;
    280
    281         try {
    282             StatUtils.max(x, 0, 4);
    283             fail("null is not a valid data array.");
    284         } catch (IllegalArgumentException ex) {
    285             // success
    286         }
    287
    288         // test empty
    289         x = new double[] {};
    290         TestUtils.assertEquals(Double.NaN, StatUtils.max(x, 0, 0), tolerance);
    291
    292         // test one
    293         x = new double[] {two};
    294         TestUtils.assertEquals(two, StatUtils.max(x, 0, 1), tolerance);
    295
    296         // test many
    297         x = new double[] {one, two, two, three};
    298         TestUtils.assertEquals(three, StatUtils.max(x, 1, 3), tolerance);
    299     }
    300
    301     public void testMin() {
    302         double[] x = null;
    303
    304         try {
    305             StatUtils.min(x, 0, 4);
    306             fail("null is not a valid data array.");
    307         } catch (IllegalArgumentException ex) {
    308             // success
    309         }
    310
    311         // test empty
    312         x = new double[] {};
    313         TestUtils.assertEquals(Double.NaN, StatUtils.min(x, 0, 0), tolerance);
    314
    315         // test one
    316         x = new double[] {two};
    317         TestUtils.assertEquals(two, StatUtils.min(x, 0, 1), tolerance);
    318
    319         // test many
    320         x = new double[] {one, two, two, three};
    321         TestUtils.assertEquals(two, StatUtils.min(x, 1, 3), tolerance);
    322     }
    323
    324     public void testPercentile() {
    325         double[] x = null;
    326
    327         // test null
    328         try {
    329             StatUtils.percentile(x, .25);
    330             fail("null is not a valid data array.");
    331         } catch (IllegalArgumentException ex) {
    332             // success
    333         }
    334
    335         try {
    336             StatUtils.percentile(x, 0, 4, 0.25);
    337             fail("null is not a valid data array.");
    338         } catch (IllegalArgumentException ex) {
    339             // success
    340         }
    341
    342         // test empty
    343         x = new double[] {};
    344         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 25), tolerance);
    345         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), tolerance);
    346
    347         // test one
    348         x = new double[] {two};
    349         TestUtils.assertEquals(two, StatUtils.percentile(x, 25), tolerance);
    350         TestUtils.assertEquals(two, StatUtils.percentile(x, 0, 1, 25), tolerance);
    351
    352         // test many
    353         x = new double[] {one, two, two, three};
    354         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 70), tolerance);
    355         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), tolerance);
    356     }
    357
    358     public void testDifferenceStats() throws Exception {
    359         double sample1[] = {1d, 2d, 3d, 4d};
    360         double sample2[] = {1d, 3d, 4d, 2d};
    361         double diff[] = {0d, -1d, -1d, 2d};
    362         double small[] = {1d, 4d};
    363         double meanDifference = StatUtils.meanDifference(sample1, sample2);
    364         assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), tolerance);
    365         assertEquals(meanDifference, StatUtils.mean(diff), tolerance);
    366         assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference),
    367                 StatUtils.variance(diff), tolerance);
    368         try {
    369             StatUtils.meanDifference(sample1, small);
    370             fail("Expecting IllegalArgumentException");
    371         } catch (IllegalArgumentException ex) {
    372             // expected
    373         }
    374     }
    375
    376     public void testGeometricMean() throws Exception {
    377         double[] test = null;
    378         try {
    379             double x = StatUtils.geometricMean(test);
    380             fail("Expecting IllegalArgumentException");
    381         } catch (IllegalArgumentException ex) {
    382             // expected
    383         }
    384         test = new double[] {2, 4, 6, 8};
    385         assertEquals(Math.exp(0.25d * StatUtils.sumLog(test)),
    386                 StatUtils.geometricMean(test), Double.MIN_VALUE);
    387     }
    388 }