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 import org.hipparchus.stat.descriptive.AbstractStorelessUnivariateStatistic;
28 import org.hipparchus.util.MathUtils;
29
30 /**
31 * Computes the first moment (arithmetic mean). Uses the definitional formula:
32 * <p>
33 * mean = sum(x_i) / n
34 * <p>
35 * where <code>n</code> is the number of observations.
36 * <p>
37 * To limit numeric errors, the value of the statistic is computed using the
38 * following recursive updating algorithm:
39 * </p>
40 * <ol>
41 * <li>Initialize <code>m = </code> the first value</li>
42 * <li>For each additional value, update using <br>
43 * <code>m = m + (new value - m) / (number of observations)</code></li>
44 * </ol>
45 * <p>
46 * Returns <code>Double.NaN</code> if the dataset is empty. Note that
47 * Double.NaN may also be returned if the input includes NaN and / or infinite
48 * values.
49 * <p>
50 * <strong>Note that this implementation is not synchronized.</strong> If
51 * multiple threads access an instance of this class concurrently, and at least
52 * one of the threads invokes the <code>increment()</code> or
53 * <code>clear()</code> method, it must be synchronized externally.
54 */
55 class FirstMoment extends AbstractStorelessUnivariateStatistic
56 implements Serializable {
57
58 /** Serializable version identifier */
59 private static final long serialVersionUID = 20150412L;
60
61 /** Count of values that have been added */
62 protected long n;
63
64 /** First moment of values that have been added */
65 protected double m1;
66
67 /**
68 * Deviation of most recently added value from previous first moment.
69 * Retained to prevent repeated computation in higher order moments.
70 */
71 protected double dev;
72
73 /**
74 * Deviation of most recently added value from previous first moment,
75 * normalized by previous sample size. Retained to prevent repeated
76 * computation in higher order moments.
77 */
78 protected double nDev;
79
80 /**
81 * Create a FirstMoment instance.
82 */
83 FirstMoment() {
84 n = 0;
85 m1 = Double.NaN;
86 dev = Double.NaN;
87 nDev = Double.NaN;
88 }
89
90 /**
91 * Copy constructor, creates a new {@code FirstMoment} identical
92 * to the {@code original}
93 *
94 * @param original the {@code FirstMoment} instance to copy
95 * @throws NullArgumentException if original is null
96 */
97 FirstMoment(FirstMoment original) throws NullArgumentException {
98 MathUtils.checkNotNull(original);
99 this.n = original.n;
100 this.m1 = original.m1;
101 this.dev = original.dev;
102 this.nDev = original.nDev;
103 }
104
105 /** {@inheritDoc} */
106 @Override
107 public void increment(final double d) {
108 if (n == 0) {
109 m1 = 0.0;
110 }
111 n++;
112 double n0 = n;
113 dev = d - m1;
114 nDev = dev / n0;
115 m1 += nDev;
116 }
117
118 /** {@inheritDoc} */
119 @Override
120 public void clear() {
121 m1 = Double.NaN;
122 n = 0;
123 dev = Double.NaN;
124 nDev = Double.NaN;
125 }
126
127 /** {@inheritDoc} */
128 @Override
129 public double getResult() {
130 return m1;
131 }
132
133 /** {@inheritDoc} */
134 @Override
135 public long getN() {
136 return n;
137 }
138
139 /**
140 * Aggregates the results of the provided instance
141 * into this instance.
142 *
143 * @param other the instance to aggregate from
144 */
145 protected void aggregate(FirstMoment other) {
146 MathUtils.checkNotNull(other);
147 if (other.n > 0) {
148 if (this.n == 0) {
149 this.m1 = 0.0;
150 }
151 this.n += other.n;
152 this.dev = other.m1 - this.m1;
153 this.nDev = this.dev / this.n;
154 this.m1 += other.n / (double) this.n * this.dev;
155 }
156 }
157
158 /** {@inheritDoc} */
159 @Override
160 public FirstMoment copy() {
161 return new FirstMoment(this);
162 }
163
164 }