    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: 348888 $ $Date: 2005-11-24 23:21:25 -0700 (Thu, 24 Nov 2005) $
    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      private double nan = Double.NaN;
    46
    47      public StatUtilsTest(String name) {
    48          super(name);
    49      }
    50
    51      public void setUp() {
    52      }
    53
    54      public static Test suite() {
    55          TestSuite suite = new TestSuite(StatUtilsTest.class);
    56          suite.setName("StatUtil Tests");
    57          return suite;
    58      }
    59
    60      /*** test stats */
    61      public void testStats() {
    62          double[] values = new double[] { one, two, two, three };
    63          assertEquals("sum", sum, StatUtils.sum(values), tolerance);
    64          assertEquals("sumsq", sumSq, StatUtils.sumSq(values), tolerance);
    65          assertEquals("var", var, StatUtils.variance(values), tolerance);
    66          assertEquals("var with mean", var, StatUtils.variance(values, mean), tolerance);
    67          assertEquals("mean", mean, StatUtils.mean(values), tolerance);
    68          assertEquals("min", min, StatUtils.min(values), tolerance);
    69          assertEquals("max", max, StatUtils.max(values), tolerance);
    70      }
    71
    72      public void testN0andN1Conditions() throws Exception {
    73          double[] values = new double[0];
    74
    75          assertTrue(
    76              "Mean of n = 0 set should be NaN",
    77              Double.isNaN(StatUtils.mean(values)));
    78          assertTrue(
    79              "Variance of n = 0 set should be NaN",
    80              Double.isNaN(StatUtils.variance(values)));
    81
    82          values = new double[] { one };
    83
    84          assertTrue(
    85              "Mean of n = 1 set should be value of single item n1",
    86              StatUtils.mean(values) == one);
    87          assertTrue(
    88              "Variance of n = 1 set should be zero",
    89              StatUtils.variance(values) == 0);
    90      }
    91
    92      public void testArrayIndexConditions() throws Exception {
    93          double[] values = { 1.0, 2.0, 3.0, 4.0 };
    94
    95          assertEquals(
    96              "Sum not expected",
    97              5.0,
    98              StatUtils.sum(values, 1, 2),
    99              Double.MIN_VALUE);
    100         assertEquals(
    101             "Sum not expected",
    102             3.0,
    103             StatUtils.sum(values, 0, 2),
    104             Double.MIN_VALUE);
    105         assertEquals(
    106             "Sum not expected",
    107             7.0,
    108             StatUtils.sum(values, 2, 2),
    109             Double.MIN_VALUE);
    110
    111         try {
    112             StatUtils.sum(values, 2, 3);
    113             assertTrue("Didn't throw exception", false);
    114         } catch (Exception e) {
    115             assertTrue(true);
    116         }
    117
    118         try {
    119             StatUtils.sum(values, -1, 2);
    120             assertTrue("Didn't throw exception", false);
    121         } catch (Exception e) {
    122             assertTrue(true);
    123         }
    124
    125     }
    126
    127     public void testSumSq() {
    128         double[] x = null;
    129
    130         // test null
    131         try {
    132             StatUtils.sumSq(x);
    133             fail("null is not a valid data array.");
    134         } catch (IllegalArgumentException ex) {
    135             // success
    136         }
    137
    138         try {
    139             StatUtils.sumSq(x, 0, 4);
    140             fail("null is not a valid data array.");
    141         } catch (IllegalArgumentException ex) {
    142             // success
    143         }
    144
    145         // test empty
    146         x = new double[] {};
    147         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x), tolerance);
    148         TestUtils.assertEquals(Double.NaN, StatUtils.sumSq(x, 0, 0), tolerance);
    149
    150         // test one
    151         x = new double[] {two};
    152         TestUtils.assertEquals(4, StatUtils.sumSq(x), tolerance);
    153         TestUtils.assertEquals(4, StatUtils.sumSq(x, 0, 1), tolerance);
    154
    155         // test many
    156         x = new double[] {one, two, two, three};
    157         TestUtils.assertEquals(18, StatUtils.sumSq(x), tolerance);
    158         TestUtils.assertEquals(8, StatUtils.sumSq(x, 1, 2), tolerance);
    159     }
    160
    161     public void testProduct() {
    162         double[] x = null;
    163
    164         // test null
    165         try {
    166             StatUtils.product(x);
    167             fail("null is not a valid data array.");
    168         } catch (IllegalArgumentException ex) {
    169             // success
    170         }
    171
    172         try {
    173             StatUtils.product(x, 0, 4);
    174             fail("null is not a valid data array.");
    175         } catch (IllegalArgumentException ex) {
    176             // success
    177         }
    178
    179         // test empty
    180         x = new double[] {};
    181         TestUtils.assertEquals(Double.NaN, StatUtils.product(x), tolerance);
    182         TestUtils.assertEquals(Double.NaN, StatUtils.product(x, 0, 0), tolerance);
    183
    184         // test one
    185         x = new double[] {two};
    186         TestUtils.assertEquals(two, StatUtils.product(x), tolerance);
    187         TestUtils.assertEquals(two, StatUtils.product(x, 0, 1), tolerance);
    188
    189         // test many
    190         x = new double[] {one, two, two, three};
    191         TestUtils.assertEquals(12, StatUtils.product(x), tolerance);
    192         TestUtils.assertEquals(4, StatUtils.product(x, 1, 2), tolerance);
    193     }
    194
    195     public void testSumLog() {
    196         double[] x = null;
    197
    198         // test null
    199         try {
    200             StatUtils.sumLog(x);
    201             fail("null is not a valid data array.");
    202         } catch (IllegalArgumentException ex) {
    203             // success
    204         }
    205
    206         try {
    207             StatUtils.sumLog(x, 0, 4);
    208             fail("null is not a valid data array.");
    209         } catch (IllegalArgumentException ex) {
    210             // success
    211         }
    212
    213         // test empty
    214         x = new double[] {};
    215         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x), tolerance);
    216         TestUtils.assertEquals(Double.NaN, StatUtils.sumLog(x, 0, 0), tolerance);
    217
    218         // test one
    219         x = new double[] {two};
    220         TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x), tolerance);
    221         TestUtils.assertEquals(Math.log(two), StatUtils.sumLog(x, 0, 1), tolerance);
    222
    223         // test many
    224         x = new double[] {one, two, two, three};
    225         TestUtils.assertEquals(Math.log(one) + 2.0 * Math.log(two) + Math.log(three), StatUtils.sumLog(x), tolerance);
    226         TestUtils.assertEquals(2.0 * Math.log(two), StatUtils.sumLog(x, 1, 2), tolerance);
    227     }
    228
    229     public void testMean() {
    230         double[] x = null;
    231
    232         try {
    233             StatUtils.mean(x, 0, 4);
    234             fail("null is not a valid data array.");
    235         } catch (IllegalArgumentException ex) {
    236             // success
    237         }
    238
    239         // test empty
    240         x = new double[] {};
    241         TestUtils.assertEquals(Double.NaN, StatUtils.mean(x, 0, 0), tolerance);
    242
    243         // test one
    244         x = new double[] {two};
    245         TestUtils.assertEquals(two, StatUtils.mean(x, 0, 1), tolerance);
    246
    247         // test many
    248         x = new double[] {one, two, two, three};
    249         TestUtils.assertEquals(2.5, StatUtils.mean(x, 2, 2), tolerance);
    250     }
    251
    252     public void testVariance() {
    253         double[] x = null;
    254
    255         try {
    256             StatUtils.variance(x, 0, 4);
    257             fail("null is not a valid data array.");
    258         } catch (IllegalArgumentException ex) {
    259             // success
    260         }
    261
    262         // test empty
    263         x = new double[] {};
    264         TestUtils.assertEquals(Double.NaN, StatUtils.variance(x, 0, 0), tolerance);
    265
    266         // test one
    267         x = new double[] {two};
    268         TestUtils.assertEquals(0.0, StatUtils.variance(x, 0, 1), tolerance);
    269
    270         // test many
    271         x = new double[] {one, two, two, three};
    272         TestUtils.assertEquals(0.5, StatUtils.variance(x, 2, 2), tolerance);
    273
    274         // test precomputed mean
    275         x = new double[] {one, two, two, three};
    276         TestUtils.assertEquals(0.5, StatUtils.variance(x,2.5, 2, 2), tolerance);
    277     }
    278
    279     public void testMax() {
    280         double[] x = null;
    281
    282         try {
    283             StatUtils.max(x, 0, 4);
    284             fail("null is not a valid data array.");
    285         } catch (IllegalArgumentException ex) {
    286             // success
    287         }
    288
    289         // test empty
    290         x = new double[] {};
    291         TestUtils.assertEquals(Double.NaN, StatUtils.max(x, 0, 0), tolerance);
    292
    293         // test one
    294         x = new double[] {two};
    295         TestUtils.assertEquals(two, StatUtils.max(x, 0, 1), tolerance);
    296
    297         // test many
    298         x = new double[] {one, two, two, three};
    299         TestUtils.assertEquals(three, StatUtils.max(x, 1, 3), tolerance);
    300
    301         // test first nan is ignored
    302         x = new double[] {nan, two, three};
    303         TestUtils.assertEquals(three, StatUtils.max(x), tolerance);
    304
    305         // test middle nan is ignored
    306         x = new double[] {one, nan, three};
    307         TestUtils.assertEquals(three, StatUtils.max(x), tolerance);
    308
    309         // test last nan is ignored
    310         x = new double[] {one, two, nan};
    311         TestUtils.assertEquals(two, StatUtils.max(x), tolerance);
    312
    313         // test all nan returns nan
    314         x = new double[] {nan, nan, nan};
    315         TestUtils.assertEquals(nan, StatUtils.max(x), tolerance);
    316     }
    317
    318     public void testMin() {
    319         double[] x = null;
    320
    321         try {
    322             StatUtils.min(x, 0, 4);
    323             fail("null is not a valid data array.");
    324         } catch (IllegalArgumentException ex) {
    325             // success
    326         }
    327
    328         // test empty
    329         x = new double[] {};
    330         TestUtils.assertEquals(Double.NaN, StatUtils.min(x, 0, 0), tolerance);
    331
    332         // test one
    333         x = new double[] {two};
    334         TestUtils.assertEquals(two, StatUtils.min(x, 0, 1), tolerance);
    335
    336         // test many
    337         x = new double[] {one, two, two, three};
    338         TestUtils.assertEquals(two, StatUtils.min(x, 1, 3), tolerance);
    339
    340         // test first nan is ignored
    341         x = new double[] {nan, two, three};
    342         TestUtils.assertEquals(two, StatUtils.min(x), tolerance);
    343
    344         // test middle nan is ignored
    345         x = new double[] {one, nan, three};
    346         TestUtils.assertEquals(one, StatUtils.min(x), tolerance);
    347
    348         // test last nan is ignored
    349         x = new double[] {one, two, nan};
    350         TestUtils.assertEquals(one, StatUtils.min(x), tolerance);
    351
    352         // test all nan returns nan
    353         x = new double[] {nan, nan, nan};
    354         TestUtils.assertEquals(nan, StatUtils.min(x), tolerance);
    355     }
    356
    357     public void testPercentile() {
    358         double[] x = null;
    359
    360         // test null
    361         try {
    362             StatUtils.percentile(x, .25);
    363             fail("null is not a valid data array.");
    364         } catch (IllegalArgumentException ex) {
    365             // success
    366         }
    367
    368         try {
    369             StatUtils.percentile(x, 0, 4, 0.25);
    370             fail("null is not a valid data array.");
    371         } catch (IllegalArgumentException ex) {
    372             // success
    373         }
    374
    375         // test empty
    376         x = new double[] {};
    377         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 25), tolerance);
    378         TestUtils.assertEquals(Double.NaN, StatUtils.percentile(x, 0, 0, 25), tolerance);
    379
    380         // test one
    381         x = new double[] {two};
    382         TestUtils.assertEquals(two, StatUtils.percentile(x, 25), tolerance);
    383         TestUtils.assertEquals(two, StatUtils.percentile(x, 0, 1, 25), tolerance);
    384
    385         // test many
    386         x = new double[] {one, two, two, three};
    387         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 70), tolerance);
    388         TestUtils.assertEquals(2.5, StatUtils.percentile(x, 1, 3, 62.5), tolerance);
    389     }
    390
    391     public void testDifferenceStats() throws Exception {
    392         double sample1[] = {1d, 2d, 3d, 4d};
    393         double sample2[] = {1d, 3d, 4d, 2d};
    394         double diff[] = {0d, -1d, -1d, 2d};
    395         double small[] = {1d, 4d};
    396         double meanDifference = StatUtils.meanDifference(sample1, sample2);
    397         assertEquals(StatUtils.sumDifference(sample1, sample2), StatUtils.sum(diff), tolerance);
    398         assertEquals(meanDifference, StatUtils.mean(diff), tolerance);
    399         assertEquals(StatUtils.varianceDifference(sample1, sample2, meanDifference),
    400                 StatUtils.variance(diff), tolerance);
    401         try {
    402             StatUtils.meanDifference(sample1, small);
    403             fail("Expecting IllegalArgumentException");
    404         } catch (IllegalArgumentException ex) {
    405             // expected
    406         }
    407         try {
    408             StatUtils.varianceDifference(sample1, small, meanDifference);
    409             fail("Expecting IllegalArgumentException");
    410         } catch (IllegalArgumentException ex) {
    411             // expected
    412         }
    413         try {
    414             double[] single = {1.0};
    415             StatUtils.varianceDifference(single, single, meanDifference);
    416             fail("Expecting IllegalArgumentException");
    417         } catch (IllegalArgumentException ex) {
    418             // expected
    419         }
    420     }
    421
    422     public void testGeometricMean() throws Exception {
    423         double[] test = null;
    424         try {
    425             double x = StatUtils.geometricMean(test);
    426             fail("Expecting IllegalArgumentException");
    427         } catch (IllegalArgumentException ex) {
    428             // expected
    429         }
    430         test = new double[] {2, 4, 6, 8};
    431         assertEquals(Math.exp(0.25d * StatUtils.sumLog(test)),
    432                 StatUtils.geometricMean(test), Double.MIN_VALUE);
    433         assertEquals(Math.exp(0.5 * StatUtils.sumLog(test, 0, 2)),
    434                 StatUtils.geometricMean(test, 0, 2), Double.MIN_VALUE);
    435     }
    436 }