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 * Computes a statistic related to the Fourth Central Moment. Specifically,
026 * what is computed is the sum of
027 * <p>
028 * (x_i - xbar) ^ 4, </p>
029 * <p>
030 * where the x_i are the
031 * sample observations and xbar is the sample mean. </p>
032 * <p>
033 * The following recursive updating formula is used: </p>
034 * <p>
035 * Let <ul>
036 * <li> dev = (current obs - previous mean) </li>
037 * <li> m2 = previous value of {@link SecondMoment} </li>
038 * <li> m2 = previous value of {@link ThirdMoment} </li>
039 * <li> n = number of observations (including current obs) </li>
040 * </ul>
041 * Then </p>
042 * <p>
043 * new value = old value - 4 * (dev/n) * m3 + 6 * (dev/n)^2 * m2 + <br>
044 * [n^2 - 3 * (n-1)] * dev^4 * (n-1) / n^3 </p>
045 * <p>
046 * Returns <code>Double.NaN</code> if no data values have been added and
047 * returns <code>0</code> if there is just one value in the data set. </p>
048 * <p>
049 * <strong>Note that this implementation is not synchronized.</strong> If
050 * multiple threads access an instance of this class concurrently, and at least
051 * one of the threads invokes the <code>increment()</code> or
052 * <code>clear()</code> method, it must be synchronized externally. </p>
053 *
054 * @version $Id: FourthMoment.java 1132432 2011-06-05 14:59:29Z luc $
055 */
056 public class FourthMoment extends ThirdMoment implements Serializable{
057
058 /** Serializable version identifier */
059 private static final long serialVersionUID = 4763990447117157611L;
060
061 /** fourth moment of values that have been added */
062 protected double m4;
063
064 /**
065 * Create a FourthMoment instance
066 */
067 public FourthMoment() {
068 super();
069 m4 = Double.NaN;
070 }
071
072 /**
073 * Copy constructor, creates a new {@code FourthMoment} identical
074 * to the {@code original}
075 *
076 * @param original the {@code FourthMoment} instance to copy
077 */
078 public FourthMoment(FourthMoment original) {
079 super();
080 copy(original, this);
081 }
082
083 /**
084 * {@inheritDoc}
085 */
086 @Override
087 public void increment(final double d) {
088 if (n < 1) {
089 m4 = 0.0;
090 m3 = 0.0;
091 m2 = 0.0;
092 m1 = 0.0;
093 }
094
095 double prevM3 = m3;
096 double prevM2 = m2;
097
098 super.increment(d);
099
100 double n0 = n;
101
102 m4 = m4 - 4.0 * nDev * prevM3 + 6.0 * nDevSq * prevM2 +
103 ((n0 * n0) - 3 * (n0 -1)) * (nDevSq * nDevSq * (n0 - 1) * n0);
104 }
105
106 /**
107 * {@inheritDoc}
108 */
109 @Override
110 public double getResult() {
111 return m4;
112 }
113
114 /**
115 * {@inheritDoc}
116 */
117 @Override
118 public void clear() {
119 super.clear();
120 m4 = Double.NaN;
121 }
122
123 /**
124 * {@inheritDoc}
125 */
126 @Override
127 public FourthMoment copy() {
128 FourthMoment result = new FourthMoment();
129 copy(this, result);
130 return result;
131 }
132
133 /**
134 * Copies source to dest.
135 * <p>Neither source nor dest can be null.</p>
136 *
137 * @param source FourthMoment to copy
138 * @param dest FourthMoment to copy to
139 * @throws NullArgumentException if either source or dest is null
140 */
141 public static void copy(FourthMoment source, FourthMoment dest)
142 throws NullArgumentException {
143 MathUtils.checkNotNull(source);
144 MathUtils.checkNotNull(dest);
145 ThirdMoment.copy(source, dest);
146 dest.m4 = source.m4;
147 }
148 }