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