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