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