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 * Returns the sum of the squares 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 */
039public class SumOfSquares extends AbstractStorelessUnivariateStatistic implements Serializable {
040
041    /** Serializable version identifier */
042    private static final long serialVersionUID = 20150412L;
043
044    /** Number of values that have been added */
045    private long n;
046
047    /**
048     * The currently running sumSq
049     */
050    private double value;
051
052    /**
053     * Create a SumOfSquares instance.
054     */
055    public SumOfSquares() {
056        n = 0;
057        value = 0;
058    }
059
060    /**
061     * Copy constructor, creates a new {@code SumOfSquares} identical
062     * to the {@code original}.
063     *
064     * @param original the {@code SumOfSquares} instance to copy
065     * @throws NullArgumentException if original is null
066     */
067    public SumOfSquares(SumOfSquares original) throws NullArgumentException {
068        copy(original, this);
069    }
070
071    /**
072     * {@inheritDoc}
073     */
074    @Override
075    public void increment(final double d) {
076        value += d * 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    @Override
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     * Returns the sum of the squares of the entries in the specified portion of
107     * the input array, or <code>Double.NaN</code> 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 squares 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 sumSq = Double.NaN;
124        if (MathArrays.verifyValues(values, begin, length, true)) {
125            sumSq = 0.0;
126            for (int i = begin; i < begin + length; i++) {
127                sumSq += values[i] * values[i];
128            }
129        }
130        return sumSq;
131    }
132
133    /**
134     * {@inheritDoc}
135     */
136    @Override
137    public SumOfSquares copy() {
138        SumOfSquares result = new SumOfSquares();
139        // no try-catch or advertised exception here because args are valid
140        copy(this, result);
141        return result;
142    }
143
144    /**
145     * Copies source to dest.
146     * <p>Neither source nor dest can be null.</p>
147     *
148     * @param source SumOfSquares to copy
149     * @param dest SumOfSquares to copy to
150     * @throws NullArgumentException if either source or dest is null
151     */
152    public static void copy(SumOfSquares source, SumOfSquares dest)
153        throws NullArgumentException {
154        MathUtils.checkNotNull(source);
155        MathUtils.checkNotNull(dest);
156        dest.n = source.n;
157        dest.value = source.value;
158    }
159
160}