    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    }