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    import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
021    
022    /**
023     * Computes the first moment (arithmetic mean).  Uses the definitional formula:
024     * <p>
025     * mean = sum(x_i) / n </p>
026     * <p>
027     * where <code>n</code> is the number of observations. </p>
028     * <p>
029     * To limit numeric errors, the value of the statistic is computed using the
030     * following recursive updating algorithm: </p>
031     * <p>
032     * <ol>
033     * <li>Initialize <code>m = </code> the first value</li>
034     * <li>For each additional value, update using <br>
035     *   <code>m = m + (new value - m) / (number of observations)</code></li>
036     * </ol></p>
037     * <p>
038     *  Returns <code>Double.NaN</code> if the dataset is empty.</p>
039     * <p>
040     * <strong>Note that this implementation is not synchronized.</strong> If
041     * multiple threads access an instance of this class concurrently, and at least
042     * one of the threads invokes the <code>increment()</code> or
043     * <code>clear()</code> method, it must be synchronized externally.</p>
044     *
045     * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
046     */
047    public class FirstMoment extends AbstractStorelessUnivariateStatistic
048        implements Serializable {
049    
050        /** Serializable version identifier */
051        private static final long serialVersionUID = 6112755307178490473L;
052    
053    
054        /** Count of values that have been added */
055        protected long n;
056    
057        /** First moment of values that have been added */
058        protected double m1;
059    
060        /**
061         * Deviation of most recently added value from previous first moment.
062         * Retained to prevent repeated computation in higher order moments.
063         */
064        protected double dev;
065    
066        /**
067         * Deviation of most recently added value from previous first moment,
068         * normalized by previous sample size.  Retained to prevent repeated
069         * computation in higher order moments
070         */
071        protected double nDev;
072    
073        /**
074         * Create a FirstMoment instance
075         */
076        public FirstMoment() {
077            n = 0;
078            m1 = Double.NaN;
079            dev = Double.NaN;
080            nDev = Double.NaN;
081        }
082    
083        /**
084         * Copy constructor, creates a new {@code FirstMoment} identical
085         * to the {@code original}
086         *
087         * @param original the {@code FirstMoment} instance to copy
088         */
089         public FirstMoment(FirstMoment original) {
090             super();
091             copy(original, this);
092         }
093    
094        /**
095         * {@inheritDoc}
096         */
097         @Override
098        public void increment(final double d) {
099            if (n == 0) {
100                m1 = 0.0;
101            }
102            n++;
103            double n0 = n;
104            dev = d - m1;
105            nDev = dev / n0;
106            m1 += nDev;
107        }
108    
109        /**
110         * {@inheritDoc}
111         */
112        @Override
113        public void clear() {
114            m1 = Double.NaN;
115            n = 0;
116            dev = Double.NaN;
117            nDev = Double.NaN;
118        }
119    
120        /**
121         * {@inheritDoc}
122         */
123        @Override
124        public double getResult() {
125            return m1;
126        }
127    
128        /**
129         * {@inheritDoc}
130         */
131        public long getN() {
132            return n;
133        }
134    
135        /**
136         * {@inheritDoc}
137         */
138        @Override
139        public FirstMoment copy() {
140            FirstMoment result = new FirstMoment();
141            copy(this, result);
142            return result;
143        }
144    
145        /**
146         * Copies source to dest.
147         * <p>Neither source nor dest can be null.</p>
148         *
149         * @param source FirstMoment to copy
150         * @param dest FirstMoment to copy to
151         * @throws NullPointerException if either source or dest is null
152         */
153        public static void copy(FirstMoment source, FirstMoment dest) {
154            dest.setData(source.getDataRef());
155            dest.n = source.n;
156            dest.m1 = source.m1;
157            dest.dev = source.dev;
158            dest.nDev = source.nDev;
159        }
160    }