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.moment;
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.core.jdkmath.JdkMath;
023
024/**
025 * Computes the sample standard deviation.  The standard deviation
026 * is the positive square root of the variance.  This implementation wraps a
027 * {@link Variance} instance.  The <code>isBiasCorrected</code> property of the
028 * wrapped Variance instance is exposed, so that this class can be used to
029 * compute both the "sample standard deviation" (the square root of the
030 * bias-corrected "sample variance") or the "population standard deviation"
031 * (the square root of the non-bias-corrected "population variance"). See
032 * {@link Variance} for more information.
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 StandardDeviation extends AbstractStorelessUnivariateStatistic {
040    /** Wrapped Variance instance. */
041    private Variance variance;
042
043    /**
044     * Constructs a StandardDeviation.  Sets the underlying {@link Variance}
045     * instance's <code>isBiasCorrected</code> property to true.
046     */
047    public StandardDeviation() {
048        variance = new Variance();
049    }
050
051    /**
052     * Constructs a StandardDeviation from an external second moment.
053     *
054     * @param m2 the external moment
055     */
056    public StandardDeviation(final SecondMoment m2) {
057        variance = new Variance(m2);
058    }
059
060    /**
061     * Copy constructor, creates a new {@code StandardDeviation} identical
062     * to the {@code original}.
063     *
064     * @param original the {@code StandardDeviation} instance to copy
065     * @throws NullArgumentException if original is null
066     */
067    public StandardDeviation(StandardDeviation original) throws NullArgumentException {
068        copy(original, this);
069    }
070
071    /**
072     * Constructs a StandardDeviation with the specified value for the
073     * <code>isBiasCorrected</code> property.  If this property is set to
074     * <code>true</code>, the {@link Variance} used in computing results will
075     * use the bias-corrected, or "sample" formula.  See {@link Variance} for
076     * details.
077     *
078     * @param isBiasCorrected  whether or not the variance computation will use
079     * the bias-corrected formula
080     */
081    public StandardDeviation(boolean isBiasCorrected) {
082        variance = new Variance(isBiasCorrected);
083    }
084
085    /**
086     * Constructs a StandardDeviation with the specified value for the
087     * <code>isBiasCorrected</code> property and the supplied external moment.
088     * If <code>isBiasCorrected</code> is set to <code>true</code>, the
089     * {@link Variance} used in computing results will use the bias-corrected,
090     * or "sample" formula.  See {@link Variance} for details.
091     *
092     * @param isBiasCorrected  whether or not the variance computation will use
093     * the bias-corrected formula
094      * @param m2 the external moment
095     */
096    public StandardDeviation(boolean isBiasCorrected, SecondMoment m2) {
097        variance = new Variance(isBiasCorrected, m2);
098    }
099
100    /**
101     * {@inheritDoc}
102     */
103    @Override
104    public void increment(final double d) {
105        variance.increment(d);
106    }
107
108    /**
109     * {@inheritDoc}
110     */
111    @Override
112    public long getN() {
113        return variance.getN();
114    }
115
116    /**
117     * {@inheritDoc}
118     */
119    @Override
120    public double getResult() {
121        return JdkMath.sqrt(variance.getResult());
122    }
123
124    /**
125     * {@inheritDoc}
126     */
127    @Override
128    public void clear() {
129        variance.clear();
130    }
131
132    /**
133     * Returns the Standard Deviation of the entries in the input array, or
134     * <code>Double.NaN</code> if the array is empty.
135     * <p>
136     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
137     * <p>
138     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
139     * <p>
140     * Does not change the internal state of the statistic.</p>
141     *
142     * @param values the input array
143     * @return the standard deviation of the values or Double.NaN if length = 0
144     * @throws MathIllegalArgumentException if the array is null
145     */
146    @Override
147    public double evaluate(final double[] values) throws MathIllegalArgumentException  {
148        return JdkMath.sqrt(variance.evaluate(values));
149    }
150
151    /**
152     * Returns the Standard Deviation of the entries in the specified portion of
153     * the input array, or <code>Double.NaN</code> if the designated subarray
154     * is empty.
155     * <p>
156     * Returns 0 for a single-value (i.e. length = 1) sample. </p>
157     * <p>
158     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
159     * <p>
160     * Does not change the internal state of the statistic.</p>
161     *
162     * @param values the input array
163     * @param begin index of the first array element to include
164     * @param length the number of elements to include
165     * @return the standard deviation of the values or Double.NaN if length = 0
166     * @throws MathIllegalArgumentException if the array is null or the array index
167     *  parameters are not valid
168     */
169    @Override
170    public double evaluate(final double[] values, final int begin, final int length)
171        throws MathIllegalArgumentException  {
172        return JdkMath.sqrt(variance.evaluate(values, begin, length));
173    }
174
175    /**
176     * Returns the Standard Deviation of the entries in the specified portion of
177     * the input array, using the precomputed mean value.  Returns
178     * <code>Double.NaN</code> if the designated subarray is empty.
179     * <p>
180     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
181     * <p>
182     * The formula used assumes that the supplied mean value is the arithmetic
183     * mean of the sample data, not a known population parameter.  This method
184     * is supplied only to save computation when the mean has already been
185     * computed.</p>
186     * <p>
187     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
188     * <p>
189     * Does not change the internal state of the statistic.</p>
190     *
191     * @param values the input array
192     * @param mean the precomputed mean value
193     * @param begin index of the first array element to include
194     * @param length the number of elements to include
195     * @return the standard deviation of the values or Double.NaN if length = 0
196     * @throws MathIllegalArgumentException if the array is null or the array index
197     *  parameters are not valid
198     */
199    public double evaluate(final double[] values, final double mean,
200                           final int begin, final int length) throws MathIllegalArgumentException  {
201        return JdkMath.sqrt(variance.evaluate(values, mean, begin, length));
202    }
203
204    /**
205     * Returns the Standard Deviation of the entries in the input array, using
206     * the precomputed mean value.  Returns
207     * <code>Double.NaN</code> if the designated subarray is empty.
208     * <p>
209     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
210     * <p>
211     * The formula used assumes that the supplied mean value is the arithmetic
212     * mean of the sample data, not a known population parameter.  This method
213     * is supplied only to save computation when the mean has already been
214     * computed.</p>
215     * <p>
216     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
217     * <p>
218     * Does not change the internal state of the statistic.</p>
219     *
220     * @param values the input array
221     * @param mean the precomputed mean value
222     * @return the standard deviation of the values or Double.NaN if length = 0
223     * @throws MathIllegalArgumentException if the array is null
224     */
225    public double evaluate(final double[] values, final double mean)
226        throws MathIllegalArgumentException  {
227        return JdkMath.sqrt(variance.evaluate(values, mean));
228    }
229
230    /**
231     * @return Returns the isBiasCorrected.
232     */
233    public boolean isBiasCorrected() {
234        return variance.isBiasCorrected();
235    }
236
237    /**
238     * @param isBiasCorrected The isBiasCorrected to set.
239     */
240    public void setBiasCorrected(boolean isBiasCorrected) {
241        variance.setBiasCorrected(isBiasCorrected);
242    }
243
244    /**
245     * {@inheritDoc}
246     */
247    @Override
248    public StandardDeviation copy() {
249        StandardDeviation result = new StandardDeviation();
250        // No try-catch or advertised exception because args are guaranteed non-null
251        copy(this, result);
252        return result;
253    }
254
255    /**
256     * Copies source to dest.
257     * <p>Neither source nor dest can be null.</p>
258     *
259     * @param source StandardDeviation to copy
260     * @param dest StandardDeviation to copy to
261     * @throws NullArgumentException if either source or dest is null
262     */
263    public static void copy(StandardDeviation source, StandardDeviation dest) throws NullArgumentException {
264        NullArgumentException.check(source);
265        NullArgumentException.check(dest);
266        dest.variance = source.variance.copy();
267    }
268}