    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    }