1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package org.apache.commons.math.stat.descriptive.moment;
18
19import java.io.Serializable;
20
21import org.apache.commons.math.stat.descriptive.AbstractStorelessUnivariateStatistic;
22import org.apache.commons.math.util.FastMath;
23
24/**
25 * Computes the sample standard deviation.  The standard deviation
26 * is the positive square root of the variance.  This implementation wraps a
27 * {@link Variance} instance.  The <code>isBiasCorrected</code> property of the
28 * wrapped Variance instance is exposed, so that this class can be used to
29 * compute both the "sample standard deviation" (the square root of the
30 * bias-corrected "sample variance") or the "population standard deviation"
31 * (the square root of the non-bias-corrected "population variance"). See
32 * {@link Variance} for more information.
33 * <p>
34 * <strong>Note that this implementation is not synchronized.</strong> If
35 * multiple threads access an instance of this class concurrently, and at least
36 * one of the threads invokes the <code>increment()</code> or
37 * <code>clear()</code> method, it must be synchronized externally.</p>
38 *
39 * @version $Revision: 1006299 $ $Date: 2010-10-10 16:47:17 +0200 (dim. 10 oct. 2010) $
40 */
41public class StandardDeviation extends AbstractStorelessUnivariateStatistic
42    implements Serializable {
43
44    /** Serializable version identifier */
45    private static final long serialVersionUID = 5728716329662425188L;
46
47    /** Wrapped Variance instance */
48    private Variance variance = null;
49
50    /**
51     * Constructs a StandardDeviation.  Sets the underlying {@link Variance}
52     * instance's <code>isBiasCorrected</code> property to true.
53     */
54    public StandardDeviation() {
55        variance = new Variance();
56    }
57
58    /**
59     * Constructs a StandardDeviation from an external second moment.
60     *
61     * @param m2 the external moment
62     */
63    public StandardDeviation(final SecondMoment m2) {
64        variance = new Variance(m2);
65    }
66
67    /**
68     * Copy constructor, creates a new {@code StandardDeviation} identical
69     * to the {@code original}
70     *
71     * @param original the {@code StandardDeviation} instance to copy
72     */
73    public StandardDeviation(StandardDeviation original) {
74        copy(original, this);
75    }
76
77    /**
78     * Contructs a StandardDeviation with the specified value for the
79     * <code>isBiasCorrected</code> property.  If this property is set to
80     * <code>true</code>, the {@link Variance} used in computing results will
81     * use the bias-corrected, or "sample" formula.  See {@link Variance} for
82     * details.
83     *
84     * @param isBiasCorrected  whether or not the variance computation will use
85     * the bias-corrected formula
86     */
87    public StandardDeviation(boolean isBiasCorrected) {
88        variance = new Variance(isBiasCorrected);
89    }
90
91    /**
92     * Contructs a StandardDeviation with the specified value for the
93     * <code>isBiasCorrected</code> property and the supplied external moment.
94     * If <code>isBiasCorrected</code> is set to <code>true</code>, the
95     * {@link Variance} used in computing results will use the bias-corrected,
96     * or "sample" formula.  See {@link Variance} for details.
97     *
98     * @param isBiasCorrected  whether or not the variance computation will use
99     * the bias-corrected formula
100      * @param m2 the external moment
101     */
102    public StandardDeviation(boolean isBiasCorrected, SecondMoment m2) {
103        variance = new Variance(isBiasCorrected, m2);
104    }
105
106    /**
107     * {@inheritDoc}
108     */
109    @Override
110    public void increment(final double d) {
111        variance.increment(d);
112    }
113
114    /**
115     * {@inheritDoc}
116     */
117    public long getN() {
118        return variance.getN();
119    }
120
121    /**
122     * {@inheritDoc}
123     */
124    @Override
125    public double getResult() {
126        return FastMath.sqrt(variance.getResult());
127    }
128
129    /**
130     * {@inheritDoc}
131     */
132    @Override
133    public void clear() {
134        variance.clear();
135    }
136
137    /**
138     * Returns the Standard Deviation of the entries in the input array, or
139     * <code>Double.NaN</code> if the array is empty.
140     * <p>
141     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
142     * <p>
143     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
144     * <p>
145     * Does not change the internal state of the statistic.</p>
146     *
147     * @param values the input array
148     * @return the standard deviation of the values or Double.NaN if length = 0
149     * @throws IllegalArgumentException if the array is null
150     */
151    @Override
152    public double evaluate(final double[] values)  {
153        return FastMath.sqrt(variance.evaluate(values));
154    }
155
156    /**
157     * Returns the Standard Deviation of the entries in the specified portion of
158     * the input array, or <code>Double.NaN</code> if the designated subarray
159     * is empty.
160     * <p>
161     * Returns 0 for a single-value (i.e. length = 1) sample. </p>
162     * <p>
163     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
164     * <p>
165     * Does not change the internal state of the statistic.</p>
166     *
167     * @param values the input array
168     * @param begin index of the first array element to include
169     * @param length the number of elements to include
170     * @return the standard deviation of the values or Double.NaN if length = 0
171     * @throws IllegalArgumentException if the array is null or the array index
172     *  parameters are not valid
173     */
174    @Override
175    public double evaluate(final double[] values, final int begin, final int length)  {
176       return FastMath.sqrt(variance.evaluate(values, begin, length));
177    }
178
179    /**
180     * Returns the Standard Deviation of the entries in the specified portion of
181     * the input array, using the precomputed mean value.  Returns
182     * <code>Double.NaN</code> if the designated subarray is empty.
183     * <p>
184     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
185     * <p>
186     * The formula used assumes that the supplied mean value is the arithmetic
187     * mean of the sample data, not a known population parameter.  This method
188     * is supplied only to save computation when the mean has already been
189     * computed.</p>
190     * <p>
191     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
192     * <p>
193     * Does not change the internal state of the statistic.</p>
194     *
195     * @param values the input array
196     * @param mean the precomputed mean value
197     * @param begin index of the first array element to include
198     * @param length the number of elements to include
199     * @return the standard deviation of the values or Double.NaN if length = 0
200     * @throws IllegalArgumentException if the array is null or the array index
201     *  parameters are not valid
202     */
203    public double evaluate(final double[] values, final double mean,
204            final int begin, final int length)  {
205        return FastMath.sqrt(variance.evaluate(values, mean, begin, length));
206    }
207
208    /**
209     * Returns the Standard Deviation of the entries in the input array, using
210     * the precomputed mean value.  Returns
211     * <code>Double.NaN</code> if the designated subarray is empty.
212     * <p>
213     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
214     * <p>
215     * The formula used assumes that the supplied mean value is the arithmetic
216     * mean of the sample data, not a known population parameter.  This method
217     * is supplied only to save computation when the mean has already been
218     * computed.</p>
219     * <p>
220     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
221     * <p>
222     * Does not change the internal state of the statistic.</p>
223     *
224     * @param values the input array
225     * @param mean the precomputed mean value
226     * @return the standard deviation of the values or Double.NaN if length = 0
227     * @throws IllegalArgumentException if the array is null
228     */
229    public double evaluate(final double[] values, final double mean)  {
230        return FastMath.sqrt(variance.evaluate(values, mean));
231    }
232
233    /**
234     * @return Returns the isBiasCorrected.
235     */
236    public boolean isBiasCorrected() {
237        return variance.isBiasCorrected();
238    }
239
240    /**
241     * @param isBiasCorrected The isBiasCorrected to set.
242     */
243    public void setBiasCorrected(boolean isBiasCorrected) {
244        variance.setBiasCorrected(isBiasCorrected);
245    }
246
247    /**
248     * {@inheritDoc}
249     */
250    @Override
251    public StandardDeviation copy() {
252        StandardDeviation result = new StandardDeviation();
253        copy(this, result);
254        return result;
255    }
256
257
258    /**
259     * Copies source to dest.
260     * <p>Neither source nor dest can be null.</p>
261     *
262     * @param source StandardDeviation to copy
263     * @param dest StandardDeviation to copy to
264     * @throws NullPointerException if either source or dest is null
265     */
266    public static void copy(StandardDeviation source, StandardDeviation dest) {
267        dest.setData(source.getDataRef());
268        dest.variance = source.variance.copy();
269    }
270
271}
272