View Javadoc
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  package org.apache.commons.math4.legacy.stat.descriptive.moment;
18  
19  import org.apache.commons.math4.legacy.exception.NullArgumentException;
20  
21  
22  /**
23   * Computes a statistic related to the Third Central Moment.  Specifically,
24   * what is computed is the sum of cubed deviations from the sample mean.
25   * <p>
26   * The following recursive updating formula is used:</p>
27   * <p>
28   * Let <ul>
29   * <li> dev = (current obs - previous mean) </li>
30   * <li> m2 = previous value of {@link SecondMoment} </li>
31   * <li> n = number of observations (including current obs) </li>
32   * </ul>
33   * Then
34   * <p>
35   * new value = old value - 3 * (dev/n) * m2 + (n-1) * (n -2) * (dev^3/n^2)</p>
36   * <p>
37   * Returns <code>Double.NaN</code> if no data values have been added and
38   * returns <code>0</code> if there is just one value in the data set.
39   * Note that Double.NaN may also be returned if the input includes NaN
40   * and / or infinite values.</p>
41   * <p>
42   * <strong>Note that this implementation is not synchronized.</strong> If
43   * multiple threads access an instance of this class concurrently, and at least
44   * one of the threads invokes the <code>increment()</code> or
45   * <code>clear()</code> method, it must be synchronized externally.</p>
46   *
47   */
48  class ThirdMoment extends SecondMoment {
49      /** third moment of values that have been added. */
50      protected double m3;
51  
52      /**
53       * Square of deviation of most recently added value from previous first
54       * moment, normalized by previous sample size.  Retained to prevent
55       * repeated computation in higher order moments.  nDevSq = nDev * nDev.
56       */
57      protected double nDevSq;
58  
59      /**
60       * Create a FourthMoment instance.
61       */
62      ThirdMoment() {
63          super();
64          m3 = Double.NaN;
65          nDevSq = Double.NaN;
66      }
67  
68      /**
69       * Copy constructor, creates a new {@code ThirdMoment} identical
70       * to the {@code original}.
71       *
72       * @param original the {@code ThirdMoment} instance to copy
73       * @throws NullArgumentException if original is null
74       */
75      ThirdMoment(ThirdMoment original) throws NullArgumentException {
76          copy(original, this);
77      }
78  
79      /**
80       * {@inheritDoc}
81       */
82      @Override
83      public void increment(final double d) {
84          if (n < 1) {
85              m3 = m2 = m1 = 0.0;
86          }
87  
88          double prevM2 = m2;
89          super.increment(d);
90          nDevSq = nDev * nDev;
91          double n0 = n;
92          m3 = m3 - 3.0 * nDev * prevM2 + (n0 - 1) * (n0 - 2) * nDevSq * dev;
93      }
94  
95      /**
96       * {@inheritDoc}
97       */
98      @Override
99      public double getResult() {
100         return m3;
101     }
102 
103     /**
104      * {@inheritDoc}
105      */
106     @Override
107     public void clear() {
108         super.clear();
109         m3 = Double.NaN;
110         nDevSq = Double.NaN;
111     }
112 
113     /**
114      * {@inheritDoc}
115      */
116     @Override
117     public ThirdMoment copy() {
118         ThirdMoment result = new ThirdMoment();
119         // No try-catch or advertised exception because args are guaranteed non-null
120         copy(this, result);
121         return result;
122     }
123 
124     /**
125      * Copies source to dest.
126      * <p>Neither source nor dest can be null.</p>
127      *
128      * @param source ThirdMoment to copy
129      * @param dest ThirdMoment to copy to
130      * @throws NullArgumentException if either source or dest is null
131      */
132     public static void copy(ThirdMoment source, ThirdMoment dest)
133         throws NullArgumentException {
134         NullArgumentException.check(source);
135         NullArgumentException.check(dest);
136         SecondMoment.copy(source, dest);
137         dest.m3 = source.m3;
138         dest.nDevSq = source.nDevSq;
139     }
140 }