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;
018
019import java.util.List;
020
021import org.apache.commons.math3.exception.MathIllegalArgumentException;
022import org.apache.commons.math3.exception.NotPositiveException;
023import org.apache.commons.math3.exception.NullArgumentException;
024import org.apache.commons.math3.exception.NumberIsTooSmallException;
025import org.apache.commons.math3.exception.DimensionMismatchException;
026import org.apache.commons.math3.exception.NoDataException;
027import org.apache.commons.math3.exception.util.LocalizedFormats;
028import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
029import org.apache.commons.math3.stat.descriptive.UnivariateStatistic;
030import org.apache.commons.math3.stat.descriptive.moment.GeometricMean;
031import org.apache.commons.math3.stat.descriptive.moment.Mean;
032import org.apache.commons.math3.stat.descriptive.moment.Variance;
033import org.apache.commons.math3.stat.descriptive.rank.Max;
034import org.apache.commons.math3.stat.descriptive.rank.Min;
035import org.apache.commons.math3.stat.descriptive.rank.Percentile;
036import org.apache.commons.math3.stat.descriptive.summary.Product;
037import org.apache.commons.math3.stat.descriptive.summary.Sum;
038import org.apache.commons.math3.stat.descriptive.summary.SumOfLogs;
039import org.apache.commons.math3.stat.descriptive.summary.SumOfSquares;
040
041/**
042 * StatUtils provides static methods for computing statistics based on data
043 * stored in double[] arrays.
044 *
045 */
046public final class StatUtils {
047
048    /** sum */
049    private static final UnivariateStatistic SUM = new Sum();
050
051    /** sumSq */
052    private static final UnivariateStatistic SUM_OF_SQUARES = new SumOfSquares();
053
054    /** prod */
055    private static final UnivariateStatistic PRODUCT = new Product();
056
057    /** sumLog */
058    private static final UnivariateStatistic SUM_OF_LOGS = new SumOfLogs();
059
060    /** min */
061    private static final UnivariateStatistic MIN = new Min();
062
063    /** max */
064    private static final UnivariateStatistic MAX = new Max();
065
066    /** mean */
067    private static final UnivariateStatistic MEAN = new Mean();
068
069    /** variance */
070    private static final Variance VARIANCE = new Variance();
071
072    /** percentile */
073    private static final Percentile PERCENTILE = new Percentile();
074
075    /** geometric mean */
076    private static final GeometricMean GEOMETRIC_MEAN = new GeometricMean();
077
078    /**
079     * Private Constructor
080     */
081    private StatUtils() {
082    }
083
084    /**
085     * Returns the sum of the values in the input array, or
086     * <code>Double.NaN</code> if the array is empty.
087     * <p>
088     * Throws <code>IllegalArgumentException</code> if the input array
089     * is null.</p>
090     *
091     * @param values  array of values to sum
092     * @return the sum of the values or <code>Double.NaN</code> if the array
093     * is empty
094     * @throws MathIllegalArgumentException if the array is null
095     */
096    public static double sum(final double[] values)
097    throws MathIllegalArgumentException {
098        return SUM.evaluate(values);
099    }
100
101    /**
102     * Returns the sum of the entries in the specified portion of
103     * the input array, or <code>Double.NaN</code> if the designated subarray
104     * is empty.
105     * <p>
106     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
107     *
108     * @param values the input array
109     * @param begin index of the first array element to include
110     * @param length the number of elements to include
111     * @return the sum of the values or Double.NaN if length = 0
112     * @throws MathIllegalArgumentException if the array is null or the array index
113     *  parameters are not valid
114     */
115    public static double sum(final double[] values, final int begin,
116            final int length) throws MathIllegalArgumentException {
117        return SUM.evaluate(values, begin, length);
118    }
119
120    /**
121     * Returns the sum of the squares of the entries in the input array, or
122     * <code>Double.NaN</code> if the array is empty.
123     * <p>
124     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
125     *
126     * @param values  input array
127     * @return the sum of the squared values or <code>Double.NaN</code> if the
128     * array is empty
129     * @throws MathIllegalArgumentException if the array is null
130     */
131    public static double sumSq(final double[] values) throws MathIllegalArgumentException {
132        return SUM_OF_SQUARES.evaluate(values);
133    }
134
135    /**
136     * Returns the sum of the squares of the entries in the specified portion of
137     * the input array, or <code>Double.NaN</code> if the designated subarray
138     * is empty.
139     * <p>
140     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
141     *
142     * @param values the input array
143     * @param begin index of the first array element to include
144     * @param length the number of elements to include
145     * @return the sum of the squares of the values or Double.NaN if length = 0
146     * @throws MathIllegalArgumentException if the array is null or the array index
147     * parameters are not valid
148     */
149    public static double sumSq(final double[] values, final int begin,
150            final int length) throws MathIllegalArgumentException {
151        return SUM_OF_SQUARES.evaluate(values, begin, length);
152    }
153
154    /**
155     * Returns the product of the entries in the input array, or
156     * <code>Double.NaN</code> if the array is empty.
157     * <p>
158     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
159     *
160     * @param values the input array
161     * @return the product of the values or Double.NaN if the array is empty
162     * @throws MathIllegalArgumentException if the array is null
163     */
164    public static double product(final double[] values)
165    throws MathIllegalArgumentException {
166        return PRODUCT.evaluate(values);
167    }
168
169    /**
170     * Returns the product of the entries in the specified portion of
171     * the input array, or <code>Double.NaN</code> if the designated subarray
172     * is empty.
173     * <p>
174     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
175     *
176     * @param values the input array
177     * @param begin index of the first array element to include
178     * @param length the number of elements to include
179     * @return the product of the values or Double.NaN if length = 0
180     * @throws MathIllegalArgumentException if the array is null or the array index
181     * parameters are not valid
182     */
183    public static double product(final double[] values, final int begin,
184            final int length) throws MathIllegalArgumentException {
185        return PRODUCT.evaluate(values, begin, length);
186    }
187
188    /**
189     * Returns the sum of the natural logs of the entries in the input array, or
190     * <code>Double.NaN</code> if the array is empty.
191     * <p>
192     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
193     * <p>
194     * See {@link org.apache.commons.math3.stat.descriptive.summary.SumOfLogs}.
195     * </p>
196     *
197     * @param values the input array
198     * @return the sum of the natural logs of the values or Double.NaN if
199     * the array is empty
200     * @throws MathIllegalArgumentException if the array is null
201     */
202    public static double sumLog(final double[] values)
203    throws MathIllegalArgumentException {
204        return SUM_OF_LOGS.evaluate(values);
205    }
206
207    /**
208     * Returns the sum of the natural logs of the entries in the specified portion of
209     * the input array, or <code>Double.NaN</code> if the designated subarray
210     * is empty.
211     * <p>
212     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
213     * <p>
214     * See {@link org.apache.commons.math3.stat.descriptive.summary.SumOfLogs}.
215     * </p>
216     *
217     * @param values the input array
218     * @param begin index of the first array element to include
219     * @param length the number of elements to include
220     * @return the sum of the natural logs of the values or Double.NaN if
221     * length = 0
222     * @throws MathIllegalArgumentException if the array is null or the array index
223     * parameters are not valid
224     */
225    public static double sumLog(final double[] values, final int begin,
226            final int length) throws MathIllegalArgumentException {
227        return SUM_OF_LOGS.evaluate(values, begin, length);
228    }
229
230    /**
231     * Returns the arithmetic mean of the entries in the input array, or
232     * <code>Double.NaN</code> if the array is empty.
233     * <p>
234     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
235     * <p>
236     * See {@link org.apache.commons.math3.stat.descriptive.moment.Mean} for
237     * details on the computing algorithm.</p>
238     *
239     * @param values the input array
240     * @return the mean of the values or Double.NaN if the array is empty
241     * @throws MathIllegalArgumentException if the array is null
242     */
243    public static double mean(final double[] values)
244    throws MathIllegalArgumentException {
245        return MEAN.evaluate(values);
246    }
247
248    /**
249     * Returns the arithmetic mean of the entries in the specified portion of
250     * the input array, or <code>Double.NaN</code> if the designated subarray
251     * is empty.
252     * <p>
253     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
254     * <p>
255     * See {@link org.apache.commons.math3.stat.descriptive.moment.Mean} for
256     * details on the computing algorithm.</p>
257     *
258     * @param values the input array
259     * @param begin index of the first array element to include
260     * @param length the number of elements to include
261     * @return the mean of the values or Double.NaN if length = 0
262     * @throws MathIllegalArgumentException if the array is null or the array index
263     * parameters are not valid
264     */
265    public static double mean(final double[] values, final int begin,
266            final int length) throws MathIllegalArgumentException {
267        return MEAN.evaluate(values, begin, length);
268    }
269
270    /**
271     * Returns the geometric mean of the entries in the input array, or
272     * <code>Double.NaN</code> if the array is empty.
273     * <p>
274     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
275     * <p>
276     * See {@link org.apache.commons.math3.stat.descriptive.moment.GeometricMean}
277     * for details on the computing algorithm.</p>
278     *
279     * @param values the input array
280     * @return the geometric mean of the values or Double.NaN if the array is empty
281     * @throws MathIllegalArgumentException if the array is null
282     */
283    public static double geometricMean(final double[] values)
284    throws MathIllegalArgumentException {
285        return GEOMETRIC_MEAN.evaluate(values);
286    }
287
288    /**
289     * Returns the geometric mean of the entries in the specified portion of
290     * the input array, or <code>Double.NaN</code> if the designated subarray
291     * is empty.
292     * <p>
293     * Throws <code>IllegalArgumentException</code> if the array is null.</p>
294     * <p>
295     * See {@link org.apache.commons.math3.stat.descriptive.moment.GeometricMean}
296     * for details on the computing algorithm.</p>
297     *
298     * @param values the input array
299     * @param begin index of the first array element to include
300     * @param length the number of elements to include
301     * @return the geometric mean of the values or Double.NaN if length = 0
302     * @throws MathIllegalArgumentException if the array is null or the array index
303     * parameters are not valid
304     */
305    public static double geometricMean(final double[] values, final int begin,
306            final int length) throws MathIllegalArgumentException {
307        return GEOMETRIC_MEAN.evaluate(values, begin, length);
308    }
309
310
311    /**
312     * Returns the variance of the entries in the input array, or
313     * <code>Double.NaN</code> if the array is empty.
314     *
315     * <p>This method returns the bias-corrected sample variance (using {@code n - 1} in
316     * the denominator).  Use {@link #populationVariance(double[])} for the non-bias-corrected
317     * population variance.</p>
318     * <p>
319     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
320     * details on the computing algorithm.</p>
321     * <p>
322     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
323     * <p>
324     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
325     *
326     * @param values the input array
327     * @return the variance of the values or Double.NaN if the array is empty
328     * @throws MathIllegalArgumentException if the array is null
329     */
330    public static double variance(final double[] values) throws MathIllegalArgumentException {
331        return VARIANCE.evaluate(values);
332    }
333
334    /**
335     * Returns the variance of the entries in the specified portion of
336     * the input array, or <code>Double.NaN</code> if the designated subarray
337     * is empty.
338     *
339     * <p>This method returns the bias-corrected sample variance (using {@code n - 1} in
340     * the denominator).  Use {@link #populationVariance(double[], int, int)} for the non-bias-corrected
341     * population variance.</p>
342     * <p>
343     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
344     * details on the computing algorithm.</p>
345     * <p>
346     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
347     * <p>
348     * Throws <code>MathIllegalArgumentException</code> if the array is null or the
349     * array index parameters are not valid.</p>
350     *
351     * @param values the input array
352     * @param begin index of the first array element to include
353     * @param length the number of elements to include
354     * @return the variance of the values or Double.NaN if length = 0
355     * @throws MathIllegalArgumentException if the array is null or the array index
356     *  parameters are not valid
357     */
358    public static double variance(final double[] values, final int begin,
359            final int length) throws MathIllegalArgumentException {
360        return VARIANCE.evaluate(values, begin, length);
361    }
362
363    /**
364     * Returns the variance of the entries in the specified portion of
365     * the input array, using the precomputed mean value.  Returns
366     * <code>Double.NaN</code> if the designated subarray is empty.
367     *
368     * <p>This method returns the bias-corrected sample variance (using {@code n - 1} in
369     * the denominator).  Use {@link #populationVariance(double[], double, int, int)} for the non-bias-corrected
370     * population variance.</p>
371     * <p>
372     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
373     * details on the computing algorithm.</p>
374     * <p>
375     * The formula used assumes that the supplied mean value is the arithmetic
376     * mean of the sample data, not a known population parameter.  This method
377     * is supplied only to save computation when the mean has already been
378     * computed.</p>
379     * <p>
380     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
381     * <p>
382     * Throws <code>MathIllegalArgumentException</code> if the array is null or the
383     * array index parameters are not valid.</p>
384     *
385     * @param values the input array
386     * @param mean the precomputed mean value
387     * @param begin index of the first array element to include
388     * @param length the number of elements to include
389     * @return the variance of the values or Double.NaN if length = 0
390     * @throws MathIllegalArgumentException if the array is null or the array index
391     *  parameters are not valid
392     */
393    public static double variance(final double[] values, final double mean,
394            final int begin, final int length) throws MathIllegalArgumentException {
395        return VARIANCE.evaluate(values, mean, begin, length);
396    }
397
398    /**
399     * Returns the variance of the entries in the input array, using the
400     * precomputed mean value.  Returns <code>Double.NaN</code> if the array
401     * is empty.
402     *
403     * <p>This method returns the bias-corrected sample variance (using {@code n - 1} in
404     * the denominator).  Use {@link #populationVariance(double[], double)} for the non-bias-corrected
405     * population variance.</p>
406     * <p>
407     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
408     * details on the computing algorithm.</p>
409     * <p>
410     * The formula used assumes that the supplied mean value is the arithmetic
411     * mean of the sample data, not a known population parameter.  This method
412     * is supplied only to save computation when the mean has already been
413     * computed.</p>
414     * <p>
415     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
416     * <p>
417     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
418     *
419     * @param values the input array
420     * @param mean the precomputed mean value
421     * @return the variance of the values or Double.NaN if the array is empty
422     * @throws MathIllegalArgumentException if the array is null
423     */
424    public static double variance(final double[] values, final double mean)
425    throws MathIllegalArgumentException {
426        return VARIANCE.evaluate(values, mean);
427    }
428
429    /**
430     * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
431     * population variance</a> of the entries in the input array, or
432     * <code>Double.NaN</code> if the array is empty.
433     * <p>
434     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
435     * details on the formula and computing algorithm.</p>
436     * <p>
437     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
438     * <p>
439     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
440     *
441     * @param values the input array
442     * @return the population variance of the values or Double.NaN if the array is empty
443     * @throws MathIllegalArgumentException if the array is null
444     */
445    public static double populationVariance(final double[] values)
446    throws MathIllegalArgumentException {
447        return new Variance(false).evaluate(values);
448    }
449
450    /**
451     * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
452     * population variance</a> of the entries in the specified portion of
453     * the input array, or <code>Double.NaN</code> if the designated subarray
454     * is empty.
455     * <p>
456     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
457     * details on the computing algorithm.</p>
458     * <p>
459     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
460     * <p>
461     * Throws <code>MathIllegalArgumentException</code> if the array is null or the
462     * array index parameters are not valid.</p>
463     *
464     * @param values the input array
465     * @param begin index of the first array element to include
466     * @param length the number of elements to include
467     * @return the population variance of the values or Double.NaN if length = 0
468     * @throws MathIllegalArgumentException if the array is null or the array index
469     *  parameters are not valid
470     */
471    public static double populationVariance(final double[] values, final int begin,
472            final int length) throws MathIllegalArgumentException {
473        return new Variance(false).evaluate(values, begin, length);
474    }
475
476    /**
477     * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
478     * population variance</a> of the entries in the specified portion of
479     * the input array, using the precomputed mean value.  Returns
480     * <code>Double.NaN</code> if the designated subarray is empty.
481     * <p>
482     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
483     * details on the computing algorithm.</p>
484     * <p>
485     * The formula used assumes that the supplied mean value is the arithmetic
486     * mean of the sample data, not a known population parameter.  This method
487     * is supplied only to save computation when the mean has already been
488     * computed.</p>
489     * <p>
490     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
491     * <p>
492     * Throws <code>MathIllegalArgumentException</code> if the array is null or the
493     * array index parameters are not valid.</p>
494     *
495     * @param values the input array
496     * @param mean the precomputed mean value
497     * @param begin index of the first array element to include
498     * @param length the number of elements to include
499     * @return the population variance of the values or Double.NaN if length = 0
500     * @throws MathIllegalArgumentException if the array is null or the array index
501     *  parameters are not valid
502     */
503    public static double populationVariance(final double[] values, final double mean,
504            final int begin, final int length) throws MathIllegalArgumentException {
505        return new Variance(false).evaluate(values, mean, begin, length);
506    }
507
508    /**
509     * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
510     * population variance</a> of the entries in the input array, using the
511     * precomputed mean value.  Returns <code>Double.NaN</code> if the array
512     * is empty.
513     * <p>
514     * See {@link org.apache.commons.math3.stat.descriptive.moment.Variance} for
515     * details on the computing algorithm.</p>
516     * <p>
517     * The formula used assumes that the supplied mean value is the arithmetic
518     * mean of the sample data, not a known population parameter.  This method
519     * is supplied only to save computation when the mean has already been
520     * computed.</p>
521     * <p>
522     * Returns 0 for a single-value (i.e. length = 1) sample.</p>
523     * <p>
524     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
525     *
526     * @param values the input array
527     * @param mean the precomputed mean value
528     * @return the population variance of the values or Double.NaN if the array is empty
529     * @throws MathIllegalArgumentException if the array is null
530     */
531    public static double populationVariance(final double[] values, final double mean)
532    throws MathIllegalArgumentException {
533        return new Variance(false).evaluate(values, mean);
534    }
535
536    /**
537     * Returns the maximum of the entries in the input array, or
538     * <code>Double.NaN</code> if the array is empty.
539     * <p>
540     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
541     * <p>
542     * <ul>
543     * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
544     * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
545     * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
546     * the result is <code>Double.POSITIVE_INFINITY.</code></li>
547     * </ul></p>
548     *
549     * @param values the input array
550     * @return the maximum of the values or Double.NaN if the array is empty
551     * @throws MathIllegalArgumentException if the array is null
552     */
553    public static double max(final double[] values) throws MathIllegalArgumentException {
554        return MAX.evaluate(values);
555    }
556
557    /**
558     * Returns the maximum of the entries in the specified portion of
559     * the input array, or <code>Double.NaN</code> if the designated subarray
560     * is empty.
561     * <p>
562     * Throws <code>MathIllegalArgumentException</code> if the array is null or
563     * the array index parameters are not valid.</p>
564     * <p>
565     * <ul>
566     * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
567     * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
568     * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
569     * the result is <code>Double.POSITIVE_INFINITY.</code></li>
570     * </ul></p>
571     *
572     * @param values the input array
573     * @param begin index of the first array element to include
574     * @param length the number of elements to include
575     * @return the maximum of the values or Double.NaN if length = 0
576     * @throws MathIllegalArgumentException if the array is null or the array index
577     * parameters are not valid
578     */
579    public static double max(final double[] values, final int begin,
580            final int length) throws MathIllegalArgumentException {
581        return MAX.evaluate(values, begin, length);
582    }
583
584     /**
585     * Returns the minimum of the entries in the input array, or
586     * <code>Double.NaN</code> if the array is empty.
587     * <p>
588     * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
589     * <p>
590     * <ul>
591     * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
592     * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
593     * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
594     * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
595     * </ul> </p>
596     *
597     * @param values the input array
598     * @return the minimum of the values or Double.NaN if the array is empty
599     * @throws MathIllegalArgumentException if the array is null
600     */
601    public static double min(final double[] values) throws MathIllegalArgumentException {
602        return MIN.evaluate(values);
603    }
604
605     /**
606     * Returns the minimum of the entries in the specified portion of
607     * the input array, or <code>Double.NaN</code> if the designated subarray
608     * is empty.
609     * <p>
610     * Throws <code>MathIllegalArgumentException</code> if the array is null or
611     * the array index parameters are not valid.</p>
612     * <p>
613     * <ul>
614     * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
615     * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
616     * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
617     * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
618     * </ul></p>
619     *
620     * @param values the input array
621     * @param begin index of the first array element to include
622     * @param length the number of elements to include
623     * @return the minimum of the values or Double.NaN if length = 0
624     * @throws MathIllegalArgumentException if the array is null or the array index
625     * parameters are not valid
626     */
627    public static double min(final double[] values, final int begin,
628            final int length) throws MathIllegalArgumentException {
629        return MIN.evaluate(values, begin, length);
630    }
631
632    /**
633     * Returns an estimate of the <code>p</code>th percentile of the values
634     * in the <code>values</code> array.
635     * <p>
636     * <ul>
637     * <li>Returns <code>Double.NaN</code> if <code>values</code> has length
638     * <code>0</code></li></p>
639     * <li>Returns (for any value of <code>p</code>) <code>values[0]</code>
640     *  if <code>values</code> has length <code>1</code></li>
641     * <li>Throws <code>IllegalArgumentException</code> if <code>values</code>
642     * is null  or p is not a valid quantile value (p must be greater than 0
643     * and less than or equal to 100)</li>
644     * </ul></p>
645     * <p>
646     * See {@link org.apache.commons.math3.stat.descriptive.rank.Percentile} for
647     * a description of the percentile estimation algorithm used.</p>
648     *
649     * @param values input array of values
650     * @param p the percentile value to compute
651     * @return the percentile value or Double.NaN if the array is empty
652     * @throws MathIllegalArgumentException if <code>values</code> is null
653     * or p is invalid
654     */
655    public static double percentile(final double[] values, final double p)
656    throws MathIllegalArgumentException {
657            return PERCENTILE.evaluate(values,p);
658    }
659
660     /**
661     * Returns an estimate of the <code>p</code>th percentile of the values
662     * in the <code>values</code> array, starting with the element in (0-based)
663     * position <code>begin</code> in the array and including <code>length</code>
664     * values.
665     * <p>
666     * <ul>
667     * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li>
668     * <li>Returns (for any value of <code>p</code>) <code>values[begin]</code>
669     *  if <code>length = 1 </code></li>
670     * <li>Throws <code>MathIllegalArgumentException</code> if <code>values</code>
671     *  is null , <code>begin</code> or <code>length</code> is invalid, or
672     * <code>p</code> is not a valid quantile value (p must be greater than 0
673     * and less than or equal to 100)</li>
674     * </ul></p>
675     * <p>
676     * See {@link org.apache.commons.math3.stat.descriptive.rank.Percentile} for
677     * a description of the percentile estimation algorithm used.</p>
678     *
679     * @param values array of input values
680     * @param p  the percentile to compute
681     * @param begin  the first (0-based) element to include in the computation
682     * @param length  the number of array elements to include
683     * @return  the percentile value
684     * @throws MathIllegalArgumentException if the parameters are not valid or the
685     * input array is null
686     */
687    public static double percentile(final double[] values, final int begin,
688            final int length, final double p) throws MathIllegalArgumentException {
689        return PERCENTILE.evaluate(values, begin, length, p);
690    }
691
692    /**
693     * Returns the sum of the (signed) differences between corresponding elements of the
694     * input arrays -- i.e., sum(sample1[i] - sample2[i]).
695     *
696     * @param sample1  the first array
697     * @param sample2  the second array
698     * @return sum of paired differences
699     * @throws DimensionMismatchException if the arrays do not have the same
700     * (positive) length.
701     * @throws NoDataException if the sample arrays are empty.
702     */
703    public static double sumDifference(final double[] sample1, final double[] sample2)
704    throws DimensionMismatchException, NoDataException {
705        int n = sample1.length;
706        if (n != sample2.length) {
707            throw new DimensionMismatchException(n, sample2.length);
708        }
709        if (n <= 0) {
710            throw new NoDataException(LocalizedFormats.INSUFFICIENT_DIMENSION);
711        }
712        double result = 0;
713        for (int i = 0; i < n; i++) {
714            result += sample1[i] - sample2[i];
715        }
716        return result;
717    }
718
719    /**
720     * Returns the mean of the (signed) differences between corresponding elements of the
721     * input arrays -- i.e., sum(sample1[i] - sample2[i]) / sample1.length.
722     *
723     * @param sample1  the first array
724     * @param sample2  the second array
725     * @return mean of paired differences
726     * @throws DimensionMismatchException if the arrays do not have the same
727     * (positive) length.
728     * @throws NoDataException if the sample arrays are empty.
729     */
730    public static double meanDifference(final double[] sample1, final double[] sample2)
731    throws DimensionMismatchException, NoDataException{
732        return sumDifference(sample1, sample2) / sample1.length;
733    }
734
735    /**
736     * Returns the variance of the (signed) differences between corresponding elements of the
737     * input arrays -- i.e., var(sample1[i] - sample2[i]).
738     *
739     * @param sample1  the first array
740     * @param sample2  the second array
741     * @param meanDifference   the mean difference between corresponding entries
742     * @see #meanDifference(double[],double[])
743     * @return variance of paired differences
744     * @throws DimensionMismatchException if the arrays do not have the same
745     * length.
746     * @throws NumberIsTooSmallException if the arrays length is less than 2.
747     */
748    public static double varianceDifference(final double[] sample1,
749            final double[] sample2, double meanDifference) throws DimensionMismatchException,
750            NumberIsTooSmallException {
751        double sum1 = 0d;
752        double sum2 = 0d;
753        double diff = 0d;
754        int n = sample1.length;
755        if (n != sample2.length) {
756            throw new DimensionMismatchException(n, sample2.length);
757        }
758        if (n < 2) {
759            throw new NumberIsTooSmallException(n, 2, true);
760        }
761        for (int i = 0; i < n; i++) {
762            diff = sample1[i] - sample2[i];
763            sum1 += (diff - meanDifference) *(diff - meanDifference);
764            sum2 += diff - meanDifference;
765        }
766        return (sum1 - (sum2 * sum2 / n)) / (n - 1);
767    }
768
769    /**
770     * Normalize (standardize) the sample, so it is has a mean of 0 and a standard deviation of 1.
771     *
772     * @param sample Sample to normalize.
773     * @return normalized (standardized) sample.
774     * @since 2.2
775     */
776    public static double[] normalize(final double[] sample) {
777        DescriptiveStatistics stats = new DescriptiveStatistics();
778
779        // Add the data from the series to stats
780        for (int i = 0; i < sample.length; i++) {
781            stats.addValue(sample[i]);
782        }
783
784        // Compute mean and standard deviation
785        double mean = stats.getMean();
786        double standardDeviation = stats.getStandardDeviation();
787
788        // initialize the standardizedSample, which has the same length as the sample
789        double[] standardizedSample = new double[sample.length];
790
791        for (int i = 0; i < sample.length; i++) {
792            // z = (x- mean)/standardDeviation
793            standardizedSample[i] = (sample[i] - mean) / standardDeviation;
794        }
795        return standardizedSample;
796    }
797
798    /**
799     * Returns the sample mode(s).  The mode is the most frequently occurring
800     * value in the sample. If there is a unique value with maximum frequency,
801     * this value is returned as the only element of the output array. Otherwise,
802     * the returned array contains the maximum frequency elements in increasing
803     * order.  For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
804     * the returned array will have length two, with 0 in the first element and
805     * 5 in the second.
806     *
807     * <p>NaN values are ignored when computing the mode - i.e., NaNs will never
808     * appear in the output array.  If the sample includes only NaNs or has
809     * length 0, an empty array is returned.</p>
810     *
811     * @param sample input data
812     * @return array of array of the most frequently occurring element(s) sorted in ascending order.
813     * @throws MathIllegalArgumentException if the indices are invalid or the array is null
814     * @since 3.3
815     */
816    public static double[] mode(double[] sample) throws MathIllegalArgumentException {
817        if (sample == null) {
818            throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
819        }
820        return getMode(sample, 0, sample.length);
821    }
822
823    /**
824     * Returns the sample mode(s).  The mode is the most frequently occurring
825     * value in the sample. If there is a unique value with maximum frequency,
826     * this value is returned as the only element of the output array. Otherwise,
827     * the returned array contains the maximum frequency elements in increasing
828     * order.  For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
829     * the returned array will have length two, with 0 in the first element and
830     * 5 in the second.
831     *
832     * <p>NaN values are ignored when computing the mode - i.e., NaNs will never
833     * appear in the output array.  If the sample includes only NaNs or has
834     * length 0, an empty array is returned.</p>
835     *
836     * @param sample input data
837     * @param begin index (0-based) of the first array element to include
838     * @param length the number of elements to include
839     *
840     * @return array of array of the most frequently occurring element(s) sorted in ascending order.
841     * @throws MathIllegalArgumentException if the indices are invalid or the array is null
842     * @since 3.3
843     */
844    public static double[] mode(double[] sample, final int begin, final int length) {
845        if (sample == null) {
846            throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
847        }
848
849        if (begin < 0) {
850            throw new NotPositiveException(LocalizedFormats.START_POSITION, Integer.valueOf(begin));
851        }
852
853        if (length < 0) {
854            throw new NotPositiveException(LocalizedFormats.LENGTH, Integer.valueOf(length));
855        }
856
857        return getMode(sample, begin, length);
858    }
859
860    /**
861     * Private helper method.
862     * Assumes parameters have been validated.
863     * @param values input data
864     * @param begin index (0-based) of the first array element to include
865     * @param length the number of elements to include
866     * @return array of array of the most frequently occurring element(s) sorted in ascending order.
867     */
868    private static double[] getMode(double[] values, final int begin, final int length) {
869        // Add the values to the frequency table
870        Frequency freq = new Frequency();
871        for (int i = begin; i < begin + length; i++) {
872            final double value = values[i];
873            if (!Double.isNaN(value)) {
874                freq.addValue(Double.valueOf(value));
875            }
876        }
877        List<Comparable<?>> list = freq.getMode();
878        // Convert the list to an array of primitive double
879        double[] modes = new double[list.size()];
880        int i = 0;
881        for(Comparable<?> c : list) {
882            modes[i++] = ((Double) c).doubleValue();
883        }
884        return modes;
885    }
886
887}