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.math3.stat.descriptive.moment;
018    
019    import java.io.Serializable;
020    
021    import org.apache.commons.math3.exception.NullArgumentException;
022    import org.apache.commons.math3.util.MathUtils;
023    
024    /**
025     * Computes a statistic related to the Second Central Moment.  Specifically,
026     * what is computed is the sum of squared deviations from the sample mean.
027     * <p>
028     * The following recursive updating formula is used:</p>
029     * <p>
030     * Let <ul>
031     * <li> dev = (current obs - previous mean) </li>
032     * <li> n = number of observations (including current obs) </li>
033     * </ul>
034     * Then</p>
035     * <p>
036     * new value = old value + dev^2 * (n -1) / n.</p>
037     * <p>
038     * Returns <code>Double.NaN</code> if no data values have been added and
039     * returns <code>0</code> if there is just one value in the data set.</p>
040     * <p>
041     * <strong>Note that this implementation is not synchronized.</strong> If
042     * multiple threads access an instance of this class concurrently, and at least
043     * one of the threads invokes the <code>increment()</code> or
044     * <code>clear()</code> method, it must be synchronized externally.</p>
045     *
046     * @version $Id: SecondMoment.java 1416643 2012-12-03 19:37:14Z tn $
047     */
048    public class SecondMoment extends FirstMoment implements Serializable {
049    
050        /** Serializable version identifier */
051        private static final long serialVersionUID = 3942403127395076445L;
052    
053        /** second moment of values that have been added */
054        protected double m2;
055    
056        /**
057         * Create a SecondMoment instance
058         */
059        public SecondMoment() {
060            super();
061            m2 = Double.NaN;
062        }
063    
064        /**
065         * Copy constructor, creates a new {@code SecondMoment} identical
066         * to the {@code original}
067         *
068         * @param original the {@code SecondMoment} instance to copy
069         * @throws NullArgumentException if original is null
070         */
071        public SecondMoment(SecondMoment original)
072        throws NullArgumentException {
073            super(original);
074            this.m2 = original.m2;
075        }
076    
077        /**
078         * {@inheritDoc}
079         */
080        @Override
081        public void increment(final double d) {
082            if (n < 1) {
083                m1 = m2 = 0.0;
084            }
085            super.increment(d);
086            m2 += ((double) n - 1) * dev * nDev;
087        }
088    
089        /**
090         * {@inheritDoc}
091         */
092        @Override
093        public void clear() {
094            super.clear();
095            m2 = Double.NaN;
096        }
097    
098        /**
099         * {@inheritDoc}
100         */
101        @Override
102        public double getResult() {
103            return m2;
104        }
105    
106        /**
107         * {@inheritDoc}
108         */
109        @Override
110        public SecondMoment copy() {
111            SecondMoment result = new SecondMoment();
112            // no try-catch or advertised NAE because args are guaranteed non-null
113            copy(this, result);
114            return result;
115        }
116    
117        /**
118         * Copies source to dest.
119         * <p>Neither source nor dest can be null.</p>
120         *
121         * @param source SecondMoment to copy
122         * @param dest SecondMoment to copy to
123         * @throws NullArgumentException if either source or dest is null
124         */
125        public static void copy(SecondMoment source, SecondMoment dest)
126            throws NullArgumentException {
127            MathUtils.checkNotNull(source);
128            MathUtils.checkNotNull(dest);
129            FirstMoment.copy(source, dest);
130            dest.m2 = source.m2;
131        }
132    
133    }