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