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 /*
19 * This is not the original file distributed by the Apache Software Foundation
20 * It has been modified by the Hipparchus project
21 */
22 package org.hipparchus.stat.descriptive.moment;
23
24 import java.io.Serializable;
25
26 import org.hipparchus.exception.NullArgumentException;
27
28 /**
29 * Computes a statistic related to the Fourth Central Moment. Specifically,
30 * what is computed is the sum of
31 * <p>
32 * (x_i - xbar) ^ 4,
33 * <p>
34 * where the x_i are the
35 * sample observations and xbar is the sample mean.
36 * <p>
37 * The following recursive updating formula is used:
38 * <p>
39 * Let <ul>
40 * <li> dev = (current obs - previous mean) </li>
41 * <li> m2 = previous value of {@link SecondMoment} </li>
42 * <li> m2 = previous value of {@link ThirdMoment} </li>
43 * <li> n = number of observations (including current obs) </li>
44 * </ul>
45 * Then
46 * <p>
47 * new value = old value - 4 * (dev/n) * m3 + 6 * (dev/n)^2 * m2 + <br>
48 * [n^2 - 3 * (n-1)] * dev^4 * (n-1) / n^3
49 * <p>
50 * Returns <code>Double.NaN</code> if no data values have been added and
51 * returns <code>0</code> if there is just one value in the data set. Note that
52 * Double.NaN may also be returned if the input includes NaN and / or infinite
53 * values.
54 * <p>
55 * <strong>Note that this implementation is not synchronized.</strong> If
56 * multiple threads access an instance of this class concurrently, and at least
57 * one of the threads invokes the <code>increment()</code> or
58 * <code>clear()</code> method, it must be synchronized externally.
59 */
60 class FourthMoment extends ThirdMoment implements Serializable{
61
62 /** Serializable version identifier */
63 private static final long serialVersionUID = 20150412L;
64
65 /** fourth moment of values that have been added */
66 private double m4;
67
68 /**
69 * Create a FourthMoment instance.
70 */
71 FourthMoment() {
72 super();
73 m4 = Double.NaN;
74 }
75
76 /**
77 * Copy constructor, creates a new {@code FourthMoment} identical
78 * to the {@code original}.
79 *
80 * @param original the {@code FourthMoment} instance to copy
81 * @throws NullArgumentException if original is null
82 */
83 FourthMoment(FourthMoment original) throws NullArgumentException {
84 super(original);
85 this.m4 = original.m4;
86 }
87
88 /** {@inheritDoc} */
89 @Override
90 public void increment(final double d) {
91 if (n < 1) {
92 m4 = 0.0;
93 m3 = 0.0;
94 m2 = 0.0;
95 m1 = 0.0;
96 }
97
98 double prevM3 = m3;
99 double prevM2 = m2;
100
101 super.increment(d);
102
103 double n0 = n;
104
105 m4 = m4 - 4.0 * nDev * prevM3 + 6.0 * nDevSq * prevM2 +
106 ((n0 * n0) - 3 * (n0 -1)) * (nDevSq * nDevSq * (n0 - 1) * n0);
107 }
108
109 /** {@inheritDoc} */
110 @Override
111 public double getResult() {
112 return m4;
113 }
114
115 /** {@inheritDoc} */
116 @Override
117 public void clear() {
118 super.clear();
119 m4 = Double.NaN;
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public FourthMoment copy() {
125 return new FourthMoment(this);
126 }
127
128 }