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 */
017package org.apache.commons.math3.stat.descriptive.summary;
018
019import java.io.Serializable;
020
021import org.apache.commons.math3.exception.MathIllegalArgumentException;
022import org.apache.commons.math3.exception.NullArgumentException;
023import org.apache.commons.math3.stat.descriptive.AbstractStorelessUnivariateStatistic;
024import org.apache.commons.math3.util.MathUtils;
025
026
027/**
028  * Returns the sum of the available values.
029 * <p>
030 * If there are no values in the dataset, then 0 is returned.
031 * If any of the values are
032 * <code>NaN</code>, then <code>NaN</code> is returned.</p>
033 * <p>
034 * <strong>Note that this implementation is not synchronized.</strong> If
035 * multiple threads access an instance of this class concurrently, and at least
036 * one of the threads invokes the <code>increment()</code> or
037 * <code>clear()</code> method, it must be synchronized externally.</p>
038 *
039 */
040public class Sum extends AbstractStorelessUnivariateStatistic implements Serializable {
041
042    /** Serializable version identifier */
043    private static final long serialVersionUID = -8231831954703408316L;
044
045    /** */
046    private long n;
047
048    /**
049     * The currently running sum.
050     */
051    private double value;
052
053    /**
054     * Create a Sum instance
055     */
056    public Sum() {
057        n = 0;
058        value = 0;
059    }
060
061    /**
062     * Copy constructor, creates a new {@code Sum} identical
063     * to the {@code original}
064     *
065     * @param original the {@code Sum} instance to copy
066     * @throws NullArgumentException if original is null
067     */
068    public Sum(Sum original) throws NullArgumentException {
069        copy(original, this);
070    }
071
072    /**
073     * {@inheritDoc}
074     */
075    @Override
076    public void increment(final double d) {
077        value += d;
078        n++;
079    }
080
081    /**
082     * {@inheritDoc}
083     */
084    @Override
085    public double getResult() {
086        return value;
087    }
088
089    /**
090     * {@inheritDoc}
091     */
092    public long getN() {
093        return n;
094    }
095
096    /**
097     * {@inheritDoc}
098     */
099    @Override
100    public void clear() {
101        value = 0;
102        n = 0;
103    }
104
105    /**
106     * The sum of the entries in the specified portion of
107     * the input array, or 0 if the designated subarray
108     * is empty.
109     * <p>
110     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
111     *
112     * @param values the input array
113     * @param begin index of the first array element to include
114     * @param length the number of elements to include
115     * @return the sum of the values or 0 if length = 0
116     * @throws MathIllegalArgumentException if the array is null or the array index
117     *  parameters are not valid
118     */
119    @Override
120    public double evaluate(final double[] values, final int begin, final int length)
121    throws MathIllegalArgumentException {
122        double sum = Double.NaN;
123        if (test(values, begin, length, true)) {
124            sum = 0.0;
125            for (int i = begin; i < begin + length; i++) {
126                sum += values[i];
127            }
128        }
129        return sum;
130    }
131
132    /**
133     * The weighted sum of the entries in the specified portion of
134     * the input array, or 0 if the designated subarray
135     * is empty.
136     * <p>
137     * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
138     * <ul><li>the values array is null</li>
139     *     <li>the weights array is null</li>
140     *     <li>the weights array does not have the same length as the values array</li>
141     *     <li>the weights array contains one or more infinite values</li>
142     *     <li>the weights array contains one or more NaN values</li>
143     *     <li>the weights array contains negative values</li>
144     *     <li>the start and length arguments do not determine a valid array</li>
145     * </ul></p>
146     * <p>
147     * Uses the formula, <pre>
148     *    weighted sum = &Sigma;(values[i] * weights[i])
149     * </pre></p>
150     *
151     * @param values the input array
152     * @param weights the weights array
153     * @param begin index of the first array element to include
154     * @param length the number of elements to include
155     * @return the sum of the values or 0 if length = 0
156     * @throws MathIllegalArgumentException if the parameters are not valid
157     * @since 2.1
158     */
159    public double evaluate(final double[] values, final double[] weights,
160        final int begin, final int length) throws MathIllegalArgumentException {
161        double sum = Double.NaN;
162        if (test(values, weights, begin, length, true)) {
163            sum = 0.0;
164            for (int i = begin; i < begin + length; i++) {
165                sum += values[i] * weights[i];
166            }
167        }
168        return sum;
169    }
170
171    /**
172     * The weighted sum of the entries in the the input array.
173     * <p>
174     * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
175     * <ul><li>the values array is null</li>
176     *     <li>the weights array is null</li>
177     *     <li>the weights array does not have the same length as the values array</li>
178     *     <li>the weights array contains one or more infinite values</li>
179     *     <li>the weights array contains one or more NaN values</li>
180     *     <li>the weights array contains negative values</li>
181     * </ul></p>
182     * <p>
183     * Uses the formula, <pre>
184     *    weighted sum = &Sigma;(values[i] * weights[i])
185     * </pre></p>
186     *
187     * @param values the input array
188     * @param weights the weights array
189     * @return the sum of the values or Double.NaN if length = 0
190     * @throws MathIllegalArgumentException if the parameters are not valid
191     * @since 2.1
192     */
193    public double evaluate(final double[] values, final double[] weights)
194    throws MathIllegalArgumentException {
195        return evaluate(values, weights, 0, values.length);
196    }
197
198    /**
199     * {@inheritDoc}
200     */
201    @Override
202    public Sum copy() {
203        Sum result = new Sum();
204        // No try-catch or advertised exception because args are valid
205        copy(this, result);
206        return result;
207    }
208
209    /**
210     * Copies source to dest.
211     * <p>Neither source nor dest can be null.</p>
212     *
213     * @param source Sum to copy
214     * @param dest Sum to copy to
215     * @throws NullArgumentException if either source or dest is null
216     */
217    public static void copy(Sum source, Sum dest)
218        throws NullArgumentException {
219        MathUtils.checkNotNull(source);
220        MathUtils.checkNotNull(dest);
221        dest.setData(source.getDataRef());
222        dest.n = source.n;
223        dest.value = source.value;
224    }
225
226}