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 }