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.math4.stat.descriptive.summary;
018
019import java.io.Serializable;
020
021import org.apache.commons.math4.exception.MathIllegalArgumentException;
022import org.apache.commons.math4.exception.NullArgumentException;
023import org.apache.commons.math4.stat.descriptive.AbstractStorelessUnivariateStatistic;
024import org.apache.commons.math4.util.MathArrays;
025import org.apache.commons.math4.util.MathUtils;
026
027
028/**
029  * Returns the sum of the available values.
030 * <p>
031 * If there are no values in the dataset, then 0 is returned.
032 * If any of the values are
033 * <code>NaN</code>, then <code>NaN</code> is returned.</p>
034 * <p>
035 * <strong>Note that this implementation is not synchronized.</strong> If
036 * multiple threads access an instance of this class concurrently, and at least
037 * one of the threads invokes the <code>increment()</code> or
038 * <code>clear()</code> method, it must be synchronized externally.</p>
039 */
040public class Sum extends AbstractStorelessUnivariateStatistic implements Serializable {
041
042    /** Serializable version identifier */
043    private static final long serialVersionUID = 20150412L;
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    @Override
093    public long getN() {
094        return n;
095    }
096
097    /**
098     * {@inheritDoc}
099     */
100    @Override
101    public void clear() {
102        value = 0;
103        n = 0;
104    }
105
106    /**
107     * The sum of the entries in the specified portion of the input array,
108     * or 0 if the designated subarray 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
123        double sum = Double.NaN;
124        if (MathArrays.verifyValues(values, begin, length, true)) {
125            sum = 0.0;
126            for (int i = begin; i < begin + length; i++) {
127                sum += values[i];
128            }
129        }
130        return sum;
131    }
132
133    /**
134     * The weighted sum of the entries in the specified portion of
135     * the input array, or 0 if the designated subarray
136     * is empty.
137     * <p>
138     * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
139     * <ul><li>the values array is null</li>
140     *     <li>the weights array is null</li>
141     *     <li>the weights array does not have the same length as the values array</li>
142     *     <li>the weights array contains one or more infinite values</li>
143     *     <li>the weights array contains one or more NaN values</li>
144     *     <li>the weights array contains negative values</li>
145     *     <li>the start and length arguments do not determine a valid array</li>
146     * </ul>
147     * <p>
148     * Uses the formula, <pre>
149     *    weighted sum = &Sigma;(values[i] * weights[i])
150     * </pre>
151     *
152     * @param values the input array
153     * @param weights the weights array
154     * @param begin index of the first array element to include
155     * @param length the number of elements to include
156     * @return the sum of the values or 0 if length = 0
157     * @throws MathIllegalArgumentException if the parameters are not valid
158     * @since 2.1
159     */
160    public double evaluate(final double[] values, final double[] weights,
161                           final int begin, final int length) throws MathIllegalArgumentException {
162        double sum = Double.NaN;
163        if (MathArrays.verifyValues(values, weights, begin, length, true)) {
164            sum = 0.0;
165            for (int i = begin; i < begin + length; i++) {
166                sum += values[i] * weights[i];
167            }
168        }
169        return sum;
170    }
171
172    /**
173     * The weighted sum of the entries in the input array.
174     * <p>
175     * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
176     * <ul><li>the values array is null</li>
177     *     <li>the weights array is null</li>
178     *     <li>the weights array does not have the same length as the values array</li>
179     *     <li>the weights array contains one or more infinite values</li>
180     *     <li>the weights array contains one or more NaN values</li>
181     *     <li>the weights array contains negative values</li>
182     * </ul>
183     * <p>
184     * Uses the formula, <pre>
185     *    weighted sum = &Sigma;(values[i] * weights[i])
186     * </pre>
187     *
188     * @param values the input array
189     * @param weights the weights array
190     * @return the sum of the values or Double.NaN if length = 0
191     * @throws MathIllegalArgumentException if the parameters are not valid
192     * @since 2.1
193     */
194    public double evaluate(final double[] values, final double[] weights) 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.n = source.n;
222        dest.value = source.value;
223    }
224
225}