001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.math.stat.descriptive.moment;
018    
019    import java.io.Serializable;
020    
021    import org.apache.commons.math.exception.NullArgumentException;
022    import org.apache.commons.math.util.MathUtils;
023    
024    
025    /**
026     * Computes a statistic related to the Third Central Moment.  Specifically,
027     * what is computed is the sum of cubed deviations from the sample mean.
028     * <p>
029     * The following recursive updating formula is used:</p>
030     * <p>
031     * Let <ul>
032     * <li> dev = (current obs - previous mean) </li>
033     * <li> m2 = previous value of {@link SecondMoment} </li>
034     * <li> n = number of observations (including current obs) </li>
035     * </ul>
036     * Then</p>
037     * <p>
038     * new value = old value - 3 * (dev/n) * m2 + (n-1) * (n -2) * (dev^3/n^2)</p>
039     * <p>
040     * Returns <code>Double.NaN</code> if no data values have been added and
041     * returns <code>0</code> if there is just one value in the data set.</p>
042     * <p>
043     * <strong>Note that this implementation is not synchronized.</strong> If
044     * multiple threads access an instance of this class concurrently, and at least
045     * one of the threads invokes the <code>increment()</code> or
046     * <code>clear()</code> method, it must be synchronized externally.</p>
047     *
048     * @version $Id: ThirdMoment.java 1132432 2011-06-05 14:59:29Z luc $
049     */
050    public class ThirdMoment extends SecondMoment implements Serializable {
051    
052        /** Serializable version identifier */
053        private static final long serialVersionUID = -7818711964045118679L;
054    
055        /** third moment of values that have been added */
056        protected double m3;
057    
058         /**
059         * Square of deviation of most recently added value from previous first
060         * moment, normalized by previous sample size.  Retained to prevent
061         * repeated computation in higher order moments.  nDevSq = nDev * nDev.
062         */
063        protected double nDevSq;
064    
065        /**
066         * Create a FourthMoment instance
067         */
068        public ThirdMoment() {
069            super();
070            m3 = Double.NaN;
071            nDevSq = Double.NaN;
072        }
073    
074        /**
075         * Copy constructor, creates a new {@code ThirdMoment} identical
076         * to the {@code original}
077         *
078         * @param original the {@code ThirdMoment} instance to copy
079         */
080        public ThirdMoment(ThirdMoment original) {
081            copy(original, this);
082        }
083    
084        /**
085         * {@inheritDoc}
086         */
087        @Override
088        public void increment(final double d) {
089            if (n < 1) {
090                m3 = m2 = m1 = 0.0;
091            }
092    
093            double prevM2 = m2;
094            super.increment(d);
095            nDevSq = nDev * nDev;
096            double n0 = n;
097            m3 = m3 - 3.0 * nDev * prevM2 + (n0 - 1) * (n0 - 2) * nDevSq * dev;
098        }
099    
100        /**
101         * {@inheritDoc}
102         */
103        @Override
104        public double getResult() {
105            return m3;
106        }
107    
108        /**
109         * {@inheritDoc}
110         */
111        @Override
112        public void clear() {
113            super.clear();
114            m3 = Double.NaN;
115            nDevSq = Double.NaN;
116        }
117    
118        /**
119         * {@inheritDoc}
120         */
121        @Override
122        public ThirdMoment copy() {
123            ThirdMoment result = new ThirdMoment();
124            copy(this, result);
125            return result;
126        }
127    
128        /**
129         * Copies source to dest.
130         * <p>Neither source nor dest can be null.</p>
131         *
132         * @param source ThirdMoment to copy
133         * @param dest ThirdMoment to copy to
134         * @throws NullArgumentException if either source or dest is null
135         */
136        public static void copy(ThirdMoment source, ThirdMoment dest)
137            throws NullArgumentException {
138            MathUtils.checkNotNull(source);
139            MathUtils.checkNotNull(dest);
140            SecondMoment.copy(source, dest);
141            dest.m3 = source.m3;
142            dest.nDevSq = source.nDevSq;
143        }
144    
145    }