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