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