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 * Returns the sum of the squares 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 */
039public class SumOfSquares extends AbstractStorelessUnivariateStatistic implements Serializable {
040
041    /** Serializable version identifier */
042    private static final long serialVersionUID = 1460986908574398008L;
043
044    /** */
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    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     * Returns the sum of the squares of the entries in the specified portion of
106     * the input array, or <code>Double.NaN</code> if the designated subarray
107     * is empty.
108     * <p>
109     * Throws <code>MathIllegalArgumentException</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 squares of the values or 0 if length = 0
115     * @throws MathIllegalArgumentException 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    throws MathIllegalArgumentException {
121        double sumSq = Double.NaN;
122        if (test(values, begin, length, true)) {
123            sumSq = 0.0;
124            for (int i = begin; i < begin + length; i++) {
125                sumSq += values[i] * values[i];
126            }
127        }
128        return sumSq;
129    }
130
131    /**
132     * {@inheritDoc}
133     */
134    @Override
135    public SumOfSquares copy() {
136        SumOfSquares result = new SumOfSquares();
137        // no try-catch or advertised exception here because args are valid
138        copy(this, result);
139        return result;
140    }
141
142    /**
143     * Copies source to dest.
144     * <p>Neither source nor dest can be null.</p>
145     *
146     * @param source SumOfSquares to copy
147     * @param dest SumOfSquares to copy to
148     * @throws NullArgumentException if either source or dest is null
149     */
150    public static void copy(SumOfSquares source, SumOfSquares dest)
151        throws NullArgumentException {
152        MathUtils.checkNotNull(source);
153        MathUtils.checkNotNull(dest);
154        dest.setData(source.getDataRef());
155        dest.n = source.n;
156        dest.value = source.value;
157    }
158
159}