1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.math.distribution;
19  
20  import org.apache.commons.math.MathException;
21  
22  /**
23   * Test cases for NormalDistribution.
24   * Extends ContinuousDistributionAbstractTest.  See class javadoc for
25   * ContinuousDistributionAbstractTest for details.
26   * 
27   * @version $Revision: 791766 $ $Date: 2009-07-07 05:19:46 -0400 (Tue, 07 Jul 2009) $
28   */
29  public class NormalDistributionTest extends ContinuousDistributionAbstractTest  {
30      
31      /**
32       * Constructor for NormalDistributionTest.
33       * @param arg0
34       */
35      public NormalDistributionTest(String arg0) {
36          super(arg0);
37      }
38      
39      //-------------- Implementations for abstract methods -----------------------
40      
41      /** Creates the default continuous distribution instance to use in tests. */
42      @Override
43      public ContinuousDistribution makeDistribution() {
44          return new NormalDistributionImpl(2.1, 1.4);
45      }   
46      
47      /** Creates the default cumulative probability distribution test input values */
48      @Override
49      public double[] makeCumulativeTestPoints() {
50          // quantiles computed using R 
51          return new double[] {-2.226325d, -1.156887d, -0.6439496d, -0.2027951d, 0.3058278d, 
52                  6.426325d, 5.356887d, 4.84395d, 4.402795d, 3.894172d};
53      }
54      
55      /** Creates the default cumulative probability density test expected values */
56      @Override
57      public double[] makeCumulativeTestValues() {
58          return new double[] {0.001d, 0.01d, 0.025d, 0.05d, 0.1d, 0.999d,
59                  0.990d, 0.975d, 0.950d, 0.900d}; 
60      }
61      
62      // --------------------- Override tolerance  --------------
63      @Override
64      protected void setUp() throws Exception {
65          super.setUp();
66          setTolerance(1E-6);
67      }
68      
69      //---------------------------- Additional test cases -------------------------
70      
71      private void verifyQuantiles() throws Exception {
72          NormalDistribution distribution = (NormalDistribution) getDistribution();
73          double mu = distribution.getMean();
74          double sigma = distribution.getStandardDeviation();
75          setCumulativeTestPoints( new double[] {mu - 2 *sigma, mu - sigma, 
76                  mu, mu + sigma, mu +2 * sigma,  mu +3 * sigma, mu + 4 * sigma,
77                  mu + 5 * sigma});
78          // Quantiles computed using R (same as Mathematica)
79          setCumulativeTestValues(new double[] {0.02275013, 0.1586553, 0.5, 0.8413447, 
80                  0.9772499, 0.9986501, 0.9999683,  0.9999997});
81          verifyCumulativeProbabilities();       
82      }
83      
84      public void testQuantiles() throws Exception {
85          verifyQuantiles();
86          setDistribution(new NormalDistributionImpl(0, 1));
87          verifyQuantiles();
88          setDistribution(new NormalDistributionImpl(0, 0.1));
89          verifyQuantiles();
90      }
91      
92      public void testInverseCumulativeProbabilityExtremes() throws Exception {
93          setInverseCumulativeTestPoints(new double[] {0, 1});
94          setInverseCumulativeTestValues(
95                  new double[] {Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY});
96          verifyInverseCumulativeProbabilities();
97      }
98      
99      public void testGetMean() {
100         NormalDistribution distribution = (NormalDistribution) getDistribution();
101         assertEquals(2.1, distribution.getMean(), 0);
102     }
103     
104     public void testSetMean() throws Exception {
105         double mu = Math.random();
106         NormalDistribution distribution = (NormalDistribution) getDistribution();
107         distribution.setMean(mu);
108         verifyQuantiles();
109     }
110     
111     public void testGetStandardDeviation() {
112         NormalDistribution distribution = (NormalDistribution) getDistribution();
113         assertEquals(1.4, distribution.getStandardDeviation(), 0);  
114     }
115     
116     public void testSetStandardDeviation() throws Exception {
117         double sigma = 0.1d + Math.random();
118         NormalDistribution distribution = (NormalDistribution) getDistribution();
119         distribution.setStandardDeviation(sigma);
120         assertEquals(sigma, distribution.getStandardDeviation(), 0);
121         verifyQuantiles();
122         try {
123             distribution.setStandardDeviation(0);
124             fail("Expecting IllegalArgumentException for sd = 0");
125         } catch (IllegalArgumentException ex) {
126             // Expected
127         }
128     }
129 
130     public void testDensity() {
131         double [] x = new double[]{-2, -1, 0, 1, 2};
132         // R 2.5: print(dnorm(c(-2,-1,0,1,2)), digits=10)
133         checkDensity(0, 1, x, new double[]{0.05399096651, 0.24197072452, 0.39894228040, 0.24197072452, 0.05399096651});
134         // R 2.5: print(dnorm(c(-2,-1,0,1,2), mean=1.1), digits=10) 
135         checkDensity(1.1, 1, x, new double[]{0.003266819056,0.043983595980,0.217852177033,0.396952547477,0.266085249899});
136     }
137 
138     private void checkDensity(double mean, double sd, double[] x, double[] expected) {
139         NormalDistribution d = new NormalDistributionImpl(mean, sd);
140         for (int i = 0; i < x.length; i++) {
141             assertEquals(expected[i], d.density(x[i]), 1e-9);
142         }
143     }
144 
145     /**
146      * Check to make sure top-coding of extreme values works correctly.
147      * Verifies fix for JIRA MATH-167
148      */
149     public void testExtremeValues() throws Exception {
150         NormalDistribution distribution = (NormalDistribution) getDistribution();
151         distribution.setMean(0);
152         distribution.setStandardDeviation(1);
153         for (int i = 0; i < 100; i+=5) { // make sure no convergence exception
154             double lowerTail = distribution.cumulativeProbability(-i);
155             double upperTail = distribution.cumulativeProbability(i);
156             if (i < 10) { // make sure not top-coded
157                 assertTrue(lowerTail > 0.0d);
158                 assertTrue(upperTail < 1.0d);
159             }
160             else { // make sure top coding not reversed
161                 assertTrue(lowerTail < 0.00001);
162                 assertTrue(upperTail > 0.99999);
163             }
164         } 
165    }
166 
167     public void testMath280() throws MathException {
168         NormalDistribution normal = new NormalDistributionImpl(0,1);
169         double result = normal.inverseCumulativeProbability(0.9772498680518209);
170         assertEquals(2.0, result, 1.0e-12);
171     }
172 
173 }