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.moment;
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.FastMath;
025import org.apache.commons.math3.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 *
042 */
043public class StandardDeviation extends AbstractStorelessUnivariateStatistic
044    implements Serializable {
045
046    /** Serializable version identifier */
047    private static final long serialVersionUID = 5728716329662425188L;
048
049    /** Wrapped Variance instance */
050    private Variance variance = null;
051
052    /**
053     * Constructs a StandardDeviation.  Sets the underlying {@link Variance}
054     * instance's <code>isBiasCorrected</code> property to true.
055     */
056    public StandardDeviation() {
057        variance = new Variance();
058    }
059
060    /**
061     * Constructs a StandardDeviation from an external second moment.
062     *
063     * @param m2 the external moment
064     */
065    public StandardDeviation(final SecondMoment m2) {
066        variance = new Variance(m2);
067    }
068
069    /**
070     * Copy constructor, creates a new {@code StandardDeviation} identical
071     * to the {@code original}
072     *
073     * @param original the {@code StandardDeviation} instance to copy
074     * @throws NullArgumentException if original is null
075     */
076    public StandardDeviation(StandardDeviation original) throws NullArgumentException {
077        copy(original, this);
078    }
079
080    /**
081     * Contructs a StandardDeviation with the specified value for the
082     * <code>isBiasCorrected</code> property.  If this property is set to
083     * <code>true</code>, the {@link Variance} used in computing results will
084     * use the bias-corrected, or "sample" formula.  See {@link Variance} for
085     * details.
086     *
087     * @param isBiasCorrected  whether or not the variance computation will use
088     * the bias-corrected formula
089     */
090    public StandardDeviation(boolean isBiasCorrected) {
091        variance = new Variance(isBiasCorrected);
092    }
093
094    /**
095     * Contructs a StandardDeviation with the specified value for the
096     * <code>isBiasCorrected</code> property and the supplied external moment.
097     * If <code>isBiasCorrected</code> is set to <code>true</code>, the
098     * {@link Variance} used in computing results will use the bias-corrected,
099     * or "sample" formula.  See {@link Variance} for details.
100     *
101     * @param isBiasCorrected  whether or not the variance computation will use
102     * the bias-corrected formula
103      * @param m2 the external moment
104     */
105    public StandardDeviation(boolean isBiasCorrected, SecondMoment m2) {
106        variance = new Variance(isBiasCorrected, m2);
107    }
108
109    /**
110     * {@inheritDoc}
111     */
112    @Override
113    public void increment(final double d) {
114        variance.increment(d);
115    }
116
117    /**
118     * {@inheritDoc}
119     */
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    /**
265     * Copies source to dest.
266     * <p>Neither source nor dest can be null.</p>
267     *
268     * @param source StandardDeviation to copy
269     * @param dest StandardDeviation to copy to
270     * @throws NullArgumentException if either source or dest is null
271     */
272    public static void copy(StandardDeviation source, StandardDeviation dest)
273        throws NullArgumentException {
274        MathUtils.checkNotNull(source);
275        MathUtils.checkNotNull(dest);
276        dest.setData(source.getDataRef());
277        dest.variance = source.variance.copy();
278    }
279
280}