SecondMoment.java

  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.  *      https://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. /*
  18.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.stat.descriptive.moment;

  22. import java.io.Serializable;

  23. import org.hipparchus.exception.NullArgumentException;
  24. import org.hipparchus.stat.descriptive.AggregatableStatistic;

  25. /**
  26.  * Computes a statistic related to the Second Central Moment.  Specifically,
  27.  * what is computed is the sum of squared deviations from the sample mean.
  28.  * <p>
  29.  * The following recursive updating formula is used:
  30.  * <p>
  31.  * Let <ul>
  32.  * <li> dev = (current obs - previous mean) </li>
  33.  * <li> n = number of observations (including current obs) </li>
  34.  * </ul>
  35.  * Then
  36.  * <p>
  37.  * new value = old value + dev^2 * (n - 1) / n.
  38.  * <p>
  39.  * Returns <code>Double.NaN</code> if no data values have been added and
  40.  * returns <code>0</code> if there is just one value in the data set.
  41.  * Note that Double.NaN may also be returned if the input includes NaN
  42.  * and / or infinite values.
  43.  * <p>
  44.  * <strong>Note that this implementation is not synchronized.</strong> If
  45.  * multiple threads access an instance of this class concurrently, and at least
  46.  * one of the threads invokes the <code>increment()</code> or
  47.  * <code>clear()</code> method, it must be synchronized externally.
  48.  */
  49. public class SecondMoment extends FirstMoment
  50.     implements AggregatableStatistic<SecondMoment>, Serializable {

  51.     /** Serializable version identifier */
  52.     private static final long serialVersionUID = 20150412L;

  53.     /** Second moment of values that have been added */
  54.     protected double m2;

  55.     /**
  56.      * Create a SecondMoment instance.
  57.      */
  58.     public SecondMoment() {
  59.         super();
  60.         m2 = Double.NaN;
  61.     }

  62.     /**
  63.      * Copy constructor, creates a new {@code SecondMoment} identical
  64.      * to the {@code original}.
  65.      *
  66.      * @param original the {@code SecondMoment} instance to copy
  67.      * @throws NullArgumentException if original is null
  68.      */
  69.     public SecondMoment(SecondMoment original) throws NullArgumentException {
  70.         super(original);
  71.         this.m2 = original.m2;
  72.     }

  73.     /** {@inheritDoc} */
  74.     @Override
  75.     public void increment(final double d) {
  76.         if (n < 1) {
  77.             m1 = m2 = 0.0;
  78.         }
  79.         super.increment(d);
  80.         m2 += ((double) n - 1) * dev * nDev;
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     public void clear() {
  85.         super.clear();
  86.         m2 = Double.NaN;
  87.     }

  88.     /** {@inheritDoc} */
  89.     @Override
  90.     public double getResult() {
  91.         return m2;
  92.     }

  93.     /** {@inheritDoc} */
  94.     @Override
  95.     public void aggregate(SecondMoment other) {
  96.         if (other.n > 0) {
  97.             final double oldN = n;
  98.             super.aggregate(other);
  99.             if (oldN == 0) {
  100.                 m2 = other.m2;
  101.             } else {
  102.                 m2 += other.m2 + (other.n * oldN) / n * dev * dev;
  103.             }
  104.         }
  105.     }

  106.     /** {@inheritDoc} */
  107.     @Override
  108.     public SecondMoment copy() {
  109.         return new SecondMoment(this);
  110.     }

  111. }