View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      https://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  /*
19   * This is not the original file distributed by the Apache Software Foundation
20   * It has been modified by the Hipparchus project
21   */
22  package org.hipparchus.stat;
23  
24  import java.util.Arrays;
25  import java.util.List;
26  
27  import org.hipparchus.exception.LocalizedCoreFormats;
28  import org.hipparchus.exception.MathIllegalArgumentException;
29  import org.hipparchus.stat.descriptive.DescriptiveStatistics;
30  import org.hipparchus.stat.descriptive.UnivariateStatistic;
31  import org.hipparchus.stat.descriptive.moment.GeometricMean;
32  import org.hipparchus.stat.descriptive.moment.Mean;
33  import org.hipparchus.stat.descriptive.moment.Variance;
34  import org.hipparchus.stat.descriptive.rank.Max;
35  import org.hipparchus.stat.descriptive.rank.Min;
36  import org.hipparchus.stat.descriptive.rank.Percentile;
37  import org.hipparchus.stat.descriptive.summary.Product;
38  import org.hipparchus.stat.descriptive.summary.Sum;
39  import org.hipparchus.stat.descriptive.summary.SumOfLogs;
40  import org.hipparchus.stat.descriptive.summary.SumOfSquares;
41  import org.hipparchus.util.MathArrays;
42  import org.hipparchus.util.MathUtils;
43  
44  /**
45   * StatUtils provides static methods for computing statistics based on data
46   * stored in double[] arrays.
47   */
48  public final class StatUtils {
49  
50      /** sum */
51      private static final UnivariateStatistic SUM = new Sum();
52  
53      /** sumSq */
54      private static final UnivariateStatistic SUM_OF_SQUARES = new SumOfSquares();
55  
56      /** prod */
57      private static final UnivariateStatistic PRODUCT = new Product();
58  
59      /** sumLog */
60      private static final UnivariateStatistic SUM_OF_LOGS = new SumOfLogs();
61  
62      /** min */
63      private static final UnivariateStatistic MIN = new Min();
64  
65      /** max */
66      private static final UnivariateStatistic MAX = new Max();
67  
68      /** mean */
69      private static final UnivariateStatistic MEAN = new Mean();
70  
71      /** variance */
72      private static final Variance VARIANCE = new Variance();
73  
74      /** percentile */
75      private static final Percentile PERCENTILE = new Percentile();
76  
77      /** geometric mean */
78      private static final GeometricMean GEOMETRIC_MEAN = new GeometricMean();
79  
80      /**
81       * Private Constructor
82       */
83      private StatUtils() {
84      }
85  
86      /**
87       * Returns the sum of the values in the input array, or
88       * <code>Double.NaN</code> if the array is empty.
89       * <p>
90       * Throws <code>IllegalArgumentException</code> if the input array is null.
91       *
92       * @param values  array of values to sum
93       * @return the sum of the values or <code>Double.NaN</code> if the array is empty
94       * @throws MathIllegalArgumentException if the array is null
95       */
96      public static double sum(final double... values) throws MathIllegalArgumentException {
97          return SUM.evaluate(values);
98      }
99  
100     /**
101      * Returns the sum of the entries in the specified portion of
102      * the input array, or <code>Double.NaN</code> if the designated subarray is empty.
103      * <p>
104      * Throws <code>IllegalArgumentException</code> if the array is null.
105      *
106      * @param values the input array
107      * @param begin index of the first array element to include
108      * @param length the number of elements to include
109      * @return the sum of the values or Double.NaN if length = 0
110      * @throws MathIllegalArgumentException if the array is null or the array index
111      *  parameters are not valid
112      */
113     public static double sum(final double[] values, final int begin, final int length)
114         throws MathIllegalArgumentException {
115         return SUM.evaluate(values, begin, length);
116     }
117 
118     /**
119      * Returns the sum of the squares of the entries in the input array, or
120      * <code>Double.NaN</code> if the array is empty.
121      * <p>
122      * Throws <code>IllegalArgumentException</code> if the array is null.
123      *
124      * @param values  input array
125      * @return the sum of the squared values or <code>Double.NaN</code> if the array is empty
126      * @throws MathIllegalArgumentException if the array is null
127      */
128     public static double sumSq(final double... values) throws MathIllegalArgumentException {
129         return SUM_OF_SQUARES.evaluate(values);
130     }
131 
132     /**
133      * Returns the sum of the squares of the entries in the specified portion of
134      * the input array, or <code>Double.NaN</code> if the designated subarray
135      * is empty.
136      * <p>
137      * Throws <code>IllegalArgumentException</code> if the array is null.
138      *
139      * @param values the input array
140      * @param begin index of the first array element to include
141      * @param length the number of elements to include
142      * @return the sum of the squares of the values or Double.NaN if length = 0
143      * @throws MathIllegalArgumentException if the array is null or the array index
144      *  parameters are not valid
145      */
146     public static double sumSq(final double[] values, final int begin, final int length)
147         throws MathIllegalArgumentException {
148         return SUM_OF_SQUARES.evaluate(values, begin, length);
149     }
150 
151     /**
152      * Returns the product of the entries in the input array, or
153      * <code>Double.NaN</code> if the array is empty.
154      * <p>
155      * Throws <code>IllegalArgumentException</code> if the array is null.
156      *
157      * @param values the input array
158      * @return the product of the values or Double.NaN if the array is empty
159      * @throws MathIllegalArgumentException if the array is null
160      */
161     public static double product(final double... values) throws MathIllegalArgumentException {
162         return PRODUCT.evaluate(values);
163     }
164 
165     /**
166      * Returns the product of the entries in the specified portion of
167      * the input array, or <code>Double.NaN</code> if the designated subarray
168      * is empty.
169      * <p>
170      * Throws <code>IllegalArgumentException</code> if the array is null.
171      *
172      * @param values the input array
173      * @param begin index of the first array element to include
174      * @param length the number of elements to include
175      * @return the product of the values or Double.NaN if length = 0
176      * @throws MathIllegalArgumentException if the array is null or the array index
177      *  parameters are not valid
178      */
179     public static double product(final double[] values, final int begin, final int length)
180         throws MathIllegalArgumentException {
181         return PRODUCT.evaluate(values, begin, length);
182     }
183 
184     /**
185      * Returns the sum of the natural logs of the entries in the input array, or
186      * <code>Double.NaN</code> if the array is empty.
187      * <p>
188      * Throws <code>IllegalArgumentException</code> if the array is null.
189      * <p>
190      * See {@link org.hipparchus.stat.descriptive.summary.SumOfLogs}.
191      *
192      * @param values the input array
193      * @return the sum of the natural logs of the values or Double.NaN if the array is empty
194      * @throws MathIllegalArgumentException if the array is null
195      */
196     public static double sumLog(final double... values) throws MathIllegalArgumentException {
197         return SUM_OF_LOGS.evaluate(values);
198     }
199 
200     /**
201      * Returns the sum of the natural logs of the entries in the specified portion of
202      * the input array, or <code>Double.NaN</code> if the designated subarray is empty.
203      * <p>
204      * Throws <code>IllegalArgumentException</code> if the array is null.
205      * <p>
206      * See {@link org.hipparchus.stat.descriptive.summary.SumOfLogs}.
207      *
208      * @param values the input array
209      * @param begin index of the first array element to include
210      * @param length the number of elements to include
211      * @return the sum of the natural logs of the values or Double.NaN if
212      * length = 0
213      * @throws MathIllegalArgumentException if the array is null or the array index
214      * parameters are not valid
215      */
216     public static double sumLog(final double[] values, final int begin, final int length)
217         throws MathIllegalArgumentException {
218         return SUM_OF_LOGS.evaluate(values, begin, length);
219     }
220 
221     /**
222      * Returns the arithmetic mean of the entries in the input array, or
223      * <code>Double.NaN</code> if the array is empty.
224      * <p>
225      * Throws <code>IllegalArgumentException</code> if the array is null.
226      * <p>
227      * See {@link org.hipparchus.stat.descriptive.moment.Mean} for
228      * details on the computing algorithm.
229      *
230      * @param values the input array
231      * @return the mean of the values or Double.NaN if the array is empty
232      * @throws MathIllegalArgumentException if the array is null
233      */
234     public static double mean(final double... values) throws MathIllegalArgumentException {
235         return MEAN.evaluate(values);
236     }
237 
238     /**
239      * Returns the arithmetic mean of the entries in the specified portion of
240      * the input array, or <code>Double.NaN</code> if the designated subarray
241      * is empty.
242      * <p>
243      * Throws <code>IllegalArgumentException</code> if the array is null.
244      * <p>
245      * See {@link org.hipparchus.stat.descriptive.moment.Mean Mean} for
246      * details on the computing algorithm.
247      *
248      * @param values the input array
249      * @param begin index of the first array element to include
250      * @param length the number of elements to include
251      * @return the mean of the values or Double.NaN if length = 0
252      * @throws MathIllegalArgumentException if the array is null or the array index
253      * parameters are not valid
254      */
255     public static double mean(final double[] values, final int begin, final int length)
256         throws MathIllegalArgumentException {
257         return MEAN.evaluate(values, begin, length);
258     }
259 
260     /**
261      * Returns the geometric mean of the entries in the input array, or
262      * <code>Double.NaN</code> if the array is empty.
263      * <p>
264      * Throws <code>IllegalArgumentException</code> if the array is null.
265      * <p>
266      * See {@link org.hipparchus.stat.descriptive.moment.GeometricMean GeometricMean}
267      * for details on the computing algorithm.
268      *
269      * @param values the input array
270      * @return the geometric mean of the values or Double.NaN if the array is empty
271      * @throws MathIllegalArgumentException if the array is null
272      */
273     public static double geometricMean(final double... values) throws MathIllegalArgumentException {
274         return GEOMETRIC_MEAN.evaluate(values);
275     }
276 
277     /**
278      * Returns the geometric mean of the entries in the specified portion of
279      * the input array, or <code>Double.NaN</code> if the designated subarray
280      * is empty.
281      * <p>
282      * Throws <code>IllegalArgumentException</code> if the array is null.
283      * <p>
284      * See {@link org.hipparchus.stat.descriptive.moment.GeometricMean GeometricMean}
285      * for details on the computing algorithm.
286      *
287      * @param values the input array
288      * @param begin index of the first array element to include
289      * @param length the number of elements to include
290      * @return the geometric mean of the values or Double.NaN if length = 0
291      * @throws MathIllegalArgumentException if the array is null or the array index
292      *  parameters are not valid
293      */
294     public static double geometricMean(final double[] values, final int begin, final int length)
295         throws MathIllegalArgumentException {
296         return GEOMETRIC_MEAN.evaluate(values, begin, length);
297     }
298 
299     /**
300      * Returns the variance of the entries in the input array, or
301      * <code>Double.NaN</code> if the array is empty.
302      * <p>
303      * This method returns the bias-corrected sample variance (using {@code n - 1} in
304      * the denominator). Use {@link #populationVariance(double[])} for the non-bias-corrected
305      * population variance.
306      * <p>
307      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
308      * details on the computing algorithm.
309      * <p>
310      * Returns 0 for a single-value (i.e. length = 1) sample.
311      * <p>
312      * Throws <code>MathIllegalArgumentException</code> if the array is null.
313      *
314      * @param values the input array
315      * @return the variance of the values or Double.NaN if the array is empty
316      * @throws MathIllegalArgumentException if the array is null
317      */
318     public static double variance(final double... values) throws MathIllegalArgumentException {
319         return VARIANCE.evaluate(values);
320     }
321 
322     /**
323      * Returns the variance of the entries in the specified portion of
324      * the input array, or <code>Double.NaN</code> if the designated subarray
325      * is empty.
326      * <p>
327      * This method returns the bias-corrected sample variance (using {@code n - 1} in
328      * the denominator). Use {@link #populationVariance(double[], int, int)} for the non-bias-corrected
329      * population variance.
330      * <p>
331      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
332      * details on the computing algorithm.
333      * <p>
334      * Returns 0 for a single-value (i.e. length = 1) sample.
335      * <p>
336      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
337      * array index parameters are not valid.
338      *
339      * @param values the input array
340      * @param begin index of the first array element to include
341      * @param length the number of elements to include
342      * @return the variance of the values or Double.NaN if length = 0
343      * @throws MathIllegalArgumentException if the array is null or the array index
344      *  parameters are not valid
345      */
346     public static double variance(final double[] values, final int begin, final int length)
347         throws MathIllegalArgumentException {
348         return VARIANCE.evaluate(values, begin, length);
349     }
350 
351     /**
352      * Returns the variance of the entries in the specified portion of
353      * the input array, using the precomputed mean value.  Returns
354      * <code>Double.NaN</code> if the designated subarray is empty.
355      * <p>
356      * This method returns the bias-corrected sample variance (using {@code n - 1} in
357      * the denominator). Use {@link #populationVariance(double[], double, int, int)} for
358      * the non-bias-corrected population variance.
359      * <p>
360      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
361      * details on the computing algorithm.
362      * <p>
363      * The formula used assumes that the supplied mean value is the arithmetic
364      * mean of the sample data, not a known population parameter.  This method
365      * is supplied only to save computation when the mean has already been
366      * computed.
367      * <p>
368      * Returns 0 for a single-value (i.e. length = 1) sample.
369      * <p>
370      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
371      * array index parameters are not valid.
372      *
373      * @param values the input array
374      * @param mean the precomputed mean value
375      * @param begin index of the first array element to include
376      * @param length the number of elements to include
377      * @return the variance of the values or Double.NaN if length = 0
378      * @throws MathIllegalArgumentException if the array is null or the array index
379      *  parameters are not valid
380      */
381     public static double variance(final double[] values, final double mean, final int begin, final int length)
382         throws MathIllegalArgumentException {
383         return VARIANCE.evaluate(values, mean, begin, length);
384     }
385 
386     /**
387      * Returns the variance of the entries in the input array, using the
388      * precomputed mean value.  Returns <code>Double.NaN</code> if the array
389      * is empty.
390      * <p>
391      * This method returns the bias-corrected sample variance (using {@code n - 1} in
392      * the denominator).  Use {@link #populationVariance(double[], double)} for the
393      * non-bias-corrected population variance.
394      * <p>
395      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
396      * details on the computing algorithm.
397      * <p>
398      * The formula used assumes that the supplied mean value is the arithmetic
399      * mean of the sample data, not a known population parameter.  This method
400      * is supplied only to save computation when the mean has already been
401      * computed.
402      * <p>
403      * Returns 0 for a single-value (i.e. length = 1) sample.
404      * <p>
405      * Throws <code>MathIllegalArgumentException</code> if the array is null.
406      *
407      * @param values the input array
408      * @param mean the precomputed mean value
409      * @return the variance of the values or Double.NaN if the array is empty
410      * @throws MathIllegalArgumentException if the array is null
411      */
412     public static double variance(final double[] values, final double mean) throws MathIllegalArgumentException {
413         return VARIANCE.evaluate(values, mean);
414     }
415 
416     /**
417      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
418      * population variance</a> of the entries in the input array, or
419      * <code>Double.NaN</code> if the array is empty.
420      * <p>
421      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
422      * details on the formula and computing algorithm.
423      * <p>
424      * Returns 0 for a single-value (i.e. length = 1) sample.
425      * <p>
426      * Throws <code>MathIllegalArgumentException</code> if the array is null.
427      *
428      * @param values the input array
429      * @return the population variance of the values or Double.NaN if the array is empty
430      * @throws MathIllegalArgumentException if the array is null
431      */
432     public static double populationVariance(final double... values) throws MathIllegalArgumentException {
433         return new Variance(false).evaluate(values);
434     }
435 
436     /**
437      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
438      * population variance</a> of the entries in the specified portion of
439      * the input array, or <code>Double.NaN</code> if the designated subarray
440      * is empty.
441      * <p>
442      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
443      * details on the computing algorithm.
444      * <p>
445      * Returns 0 for a single-value (i.e. length = 1) sample.
446      * <p>
447      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
448      * array index parameters are not valid.
449      *
450      * @param values the input array
451      * @param begin index of the first array element to include
452      * @param length the number of elements to include
453      * @return the population variance of the values or Double.NaN if length = 0
454      * @throws MathIllegalArgumentException if the array is null or the array index
455      *  parameters are not valid
456      */
457     public static double populationVariance(final double[] values, final int begin, final int length)
458         throws MathIllegalArgumentException {
459         return new Variance(false).evaluate(values, begin, length);
460     }
461 
462     /**
463      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
464      * population variance</a> of the entries in the specified portion of
465      * the input array, using the precomputed mean value.  Returns
466      * <code>Double.NaN</code> if the designated subarray is empty.
467      * <p>
468      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
469      * details on the computing algorithm.
470      * <p>
471      * The formula used assumes that the supplied mean value is the arithmetic
472      * mean of the sample data, not a known population parameter.  This method
473      * is supplied only to save computation when the mean has already been
474      * computed.
475      * <p>
476      * Returns 0 for a single-value (i.e. length = 1) sample.
477      * <p>
478      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
479      * array index parameters are not valid.
480      *
481      * @param values the input array
482      * @param mean the precomputed mean value
483      * @param begin index of the first array element to include
484      * @param length the number of elements to include
485      * @return the population variance of the values or Double.NaN if length = 0
486      * @throws MathIllegalArgumentException if the array is null or the array index
487      *  parameters are not valid
488      */
489     public static double populationVariance(final double[] values, final double mean,
490                                             final int begin, final int length)
491         throws MathIllegalArgumentException {
492         return new Variance(false).evaluate(values, mean, begin, length);
493     }
494 
495     /**
496      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
497      * population variance</a> of the entries in the input array, using the precomputed
498      * mean value. Returns <code>Double.NaN</code> if the array is empty.
499      * <p>
500      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
501      * details on the computing algorithm.
502      * <p>
503      * The formula used assumes that the supplied mean value is the arithmetic
504      * mean of the sample data, not a known population parameter. This method is
505      * supplied only to save computation when the mean has already been computed.
506      * <p>
507      * Returns 0 for a single-value (i.e. length = 1) sample.
508      * <p>
509      * Throws <code>MathIllegalArgumentException</code> if the array is null.
510      *
511      * @param values the input array
512      * @param mean the precomputed mean value
513      * @return the population variance of the values or Double.NaN if the array is empty
514      * @throws MathIllegalArgumentException if the array is null
515      */
516     public static double populationVariance(final double[] values, final double mean)
517         throws MathIllegalArgumentException {
518         return new Variance(false).evaluate(values, mean);
519     }
520 
521     /**
522      * Returns the maximum of the entries in the input array, or
523      * <code>Double.NaN</code> if the array is empty.
524      * <p>
525      * Throws <code>MathIllegalArgumentException</code> if the array is null.
526      * </p>
527      * <ul>
528      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
529      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
530      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
531      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
532      * </ul>
533      *
534      * @param values the input array
535      * @return the maximum of the values or Double.NaN if the array is empty
536      * @throws MathIllegalArgumentException if the array is null
537      */
538     public static double max(final double... values) throws MathIllegalArgumentException {
539         return MAX.evaluate(values);
540     }
541 
542     /**
543      * Returns the maximum of the entries in the specified portion of the input array,
544      * or <code>Double.NaN</code> if the designated subarray is empty.
545      * <p>
546      * Throws <code>MathIllegalArgumentException</code> if the array is null or
547      * the array index parameters are not valid.
548      * </p>
549      * <ul>
550      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
551      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
552      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
553      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
554      * </ul>
555      *
556      * @param values the input array
557      * @param begin index of the first array element to include
558      * @param length the number of elements to include
559      * @return the maximum of the values or Double.NaN if length = 0
560      * @throws MathIllegalArgumentException if the array is null or the array index
561      *  parameters are not valid
562      */
563     public static double max(final double[] values, final int begin, final int length)
564         throws MathIllegalArgumentException {
565         return MAX.evaluate(values, begin, length);
566     }
567 
568     /**
569      * Returns the minimum of the entries in the input array, or
570      * <code>Double.NaN</code> if the array is empty.
571      * <p>
572      * Throws <code>MathIllegalArgumentException</code> if the array is null.
573      * </p>
574      * <ul>
575      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
576      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
577      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
578      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
579      * </ul>
580      *
581      * @param values the input array
582      * @return the minimum of the values or Double.NaN if the array is empty
583      * @throws MathIllegalArgumentException if the array is null
584      */
585     public static double min(final double... values) throws MathIllegalArgumentException {
586         return MIN.evaluate(values);
587     }
588 
589     /**
590      * Returns the minimum of the entries in the specified portion of the input array,
591      * or <code>Double.NaN</code> if the designated subarray is empty.
592      * <p>
593      * Throws <code>MathIllegalArgumentException</code> if the array is null or
594      * the array index parameters are not valid.
595      * </p>
596      * <ul>
597      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
598      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
599      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
600      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
601      * </ul>
602      *
603      * @param values the input array
604      * @param begin index of the first array element to include
605      * @param length the number of elements to include
606      * @return the minimum of the values or Double.NaN if length = 0
607      * @throws MathIllegalArgumentException if the array is null or the array index
608      *  parameters are not valid
609      */
610     public static double min(final double[] values, final int begin, final int length)
611         throws MathIllegalArgumentException {
612         return MIN.evaluate(values, begin, length);
613     }
614 
615     /**
616      * Returns an estimate of the <code>p</code>th percentile of the values
617      * in the <code>values</code> array.
618      * <ul>
619      * <li>Returns <code>Double.NaN</code> if <code>values</code> has length
620      *  <code>0</code></li>
621      * <li>Returns (for any value of <code>p</code>) <code>values[0]</code>
622      *  if <code>values</code> has length <code>1</code></li>
623      * <li>Throws <code>IllegalArgumentException</code> if <code>values</code>
624      *  is null  or p is not a valid quantile value (p must be greater than 0
625      *  and less than or equal to 100)</li>
626      * </ul>
627      * <p>
628      * See {@link org.hipparchus.stat.descriptive.rank.Percentile Percentile}
629      * for a description of the percentile estimation algorithm used.
630      *
631      * @param values input array of values
632      * @param p the percentile value to compute
633      * @return the percentile value or Double.NaN if the array is empty
634      * @throws MathIllegalArgumentException if <code>values</code> is null or p is invalid
635      */
636     public static double percentile(final double[] values, final double p) throws MathIllegalArgumentException {
637         return PERCENTILE.evaluate(values,p);
638     }
639 
640     /**
641      * Returns an estimate of the <code>p</code>th percentile of the values
642      * in the <code>values</code> array, starting with the element in (0-based)
643      * position <code>begin</code> in the array and including <code>length</code>
644      * values.
645      * <ul>
646      * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li>
647      * <li>Returns (for any value of <code>p</code>) <code>values[begin]</code>
648      *  if <code>length = 1 </code></li>
649      * <li>Throws <code>MathIllegalArgumentException</code> if <code>values</code>
650      *  is null, <code>begin</code> or <code>length</code> is invalid, or
651      *  <code>p</code> is not a valid quantile value (p must be greater than 0
652      *  and less than or equal to 100)</li>
653      * </ul>
654      * <p>
655      * See {@link org.hipparchus.stat.descriptive.rank.Percentile Percentile}
656      * for a description of the percentile estimation algorithm used.
657      *
658      * @param values array of input values
659      * @param p the percentile to compute
660      * @param begin the first (0-based) element to include in the computation
661      * @param length the number of array elements to include
662      * @return the percentile value
663      * @throws MathIllegalArgumentException if the parameters are not valid or the input array is null
664      */
665     public static double percentile(final double[] values, final int begin, final int length, final double p)
666         throws MathIllegalArgumentException {
667         return PERCENTILE.evaluate(values, begin, length, p);
668     }
669 
670     /**
671      * Returns the sum of the (signed) differences between corresponding elements of the
672      * input arrays -- i.e., sum(sample1[i] - sample2[i]).
673      *
674      * @param sample1  the first array
675      * @param sample2  the second array
676      * @return sum of paired differences
677      * @throws MathIllegalArgumentException if the arrays do not have the same (positive) length.
678      * @throws MathIllegalArgumentException if the sample arrays are empty.
679      */
680     public static double sumDifference(final double[] sample1, final double[] sample2)
681         throws MathIllegalArgumentException {
682 
683         int n = sample1.length;
684         MathArrays.checkEqualLength(sample1, sample2);
685         if (n <= 0) {
686             throw new MathIllegalArgumentException(LocalizedCoreFormats.INSUFFICIENT_DIMENSION);
687         }
688         double result = 0;
689         for (int i = 0; i < n; i++) {
690             result += sample1[i] - sample2[i];
691         }
692         return result;
693     }
694 
695     /**
696      * Returns the mean of the (signed) differences between corresponding elements of the
697      * input arrays -- i.e., sum(sample1[i] - sample2[i]) / sample1.length.
698      *
699      * @param sample1  the first array
700      * @param sample2  the second array
701      * @return mean of paired differences
702      * @throws MathIllegalArgumentException if the arrays do not have the same (positive) length.
703      * @throws MathIllegalArgumentException if the sample arrays are empty.
704      */
705     public static double meanDifference(final double[] sample1, final double[] sample2)
706         throws MathIllegalArgumentException {
707         return sumDifference(sample1, sample2) / sample1.length;
708     }
709 
710     /**
711      * Returns the variance of the (signed) differences between corresponding elements of the
712      * input arrays -- i.e., var(sample1[i] - sample2[i]).
713      *
714      * @param sample1  the first array
715      * @param sample2  the second array
716      * @param meanDifference   the mean difference between corresponding entries
717      * @return variance of paired differences
718      * @throws MathIllegalArgumentException if the arrays do not have the same length.
719      * @throws MathIllegalArgumentException if the arrays length is less than 2.
720      * @see #meanDifference(double[],double[])
721      */
722     public static double varianceDifference(final double[] sample1, final double[] sample2, double meanDifference)
723         throws MathIllegalArgumentException {
724 
725         double sum1 = 0d;
726         double sum2 = 0d;
727         int n = sample1.length;
728         MathArrays.checkEqualLength(sample1, sample2);
729         if (n < 2) {
730             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
731                                                    n, 2);
732         }
733         for (int i = 0; i < n; i++) {
734             final double diff = sample1[i] - sample2[i];
735             sum1 += (diff - meanDifference) *(diff - meanDifference);
736             sum2 += diff - meanDifference;
737         }
738         return (sum1 - (sum2 * sum2 / n)) / (n - 1);
739     }
740 
741     /**
742      * Normalize (standardize) the sample, so it is has a mean of 0 and a standard deviation of 1.
743      *
744      * @param sample Sample to normalize.
745      * @return normalized (standardized) sample.
746      */
747     public static double[] normalize(final double... sample) {
748         DescriptiveStatistics stats = new DescriptiveStatistics();
749 
750         // Add the data from the series to stats
751         for (int i = 0; i < sample.length; i++) {
752             stats.addValue(sample[i]);
753         }
754 
755         // Compute mean and standard deviation
756         double mean = stats.getMean();
757         double standardDeviation = stats.getStandardDeviation();
758 
759         // initialize the standardizedSample, which has the same length as the sample
760         double[] standardizedSample = new double[sample.length];
761 
762         for (int i = 0; i < sample.length; i++) {
763             // z = (x- mean)/standardDeviation
764             standardizedSample[i] = (sample[i] - mean) / standardDeviation;
765         }
766         return standardizedSample;
767     }
768 
769     /**
770      * Returns the sample mode(s).
771      * <p>
772      * The mode is the most frequently occurring value in the sample.
773      * If there is a unique value with maximum frequency, this value is returned
774      * as the only element of the output array. Otherwise, the returned array
775      * contains the maximum frequency elements in increasing order.
776      * <p>
777      * For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
778      * the returned array will have length two, with 0 in the first element and
779      * 5 in the second.
780      * <p>
781      * NaN values are ignored when computing the mode - i.e., NaNs will never
782      * appear in the output array.  If the sample includes only NaNs or has
783      * length 0, an empty array is returned.
784      *
785      * @param sample input data
786      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
787      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
788      */
789     public static double[] mode(double... sample) throws MathIllegalArgumentException {
790         MathUtils.checkNotNull(sample, LocalizedCoreFormats.INPUT_ARRAY);
791         return getMode(sample, 0, sample.length);
792     }
793 
794     /**
795      * Returns the sample mode(s).
796      * <p>
797      * The mode is the most frequently occurring value in the sample.
798      * If there is a unique value with maximum frequency, this value is returned
799      * as the only element of the output array. Otherwise, the returned array
800      * contains the maximum frequency elements in increasing order.
801      * <p>
802      * For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
803      * the returned array will have length two, with 0 in the first element and
804      * 5 in the second.
805      * <p>
806      * NaN values are ignored when computing the mode - i.e., NaNs will never
807      * appear in the output array.  If the sample includes only NaNs or has
808      * length 0, an empty array is returned.
809      *
810      * @param sample input data
811      * @param begin index (0-based) of the first array element to include
812      * @param length the number of elements to include
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      */
816     public static double[] mode(double[] sample, final int begin, final int length) {
817         MathUtils.checkNotNull(sample, LocalizedCoreFormats.INPUT_ARRAY);
818 
819         if (begin < 0) {
820             throw new MathIllegalArgumentException(LocalizedCoreFormats.START_POSITION, Integer.valueOf(begin));
821         }
822 
823         if (length < 0) {
824             throw new MathIllegalArgumentException(LocalizedCoreFormats.LENGTH, Integer.valueOf(length));
825         }
826 
827         return getMode(sample, begin, length);
828     }
829 
830     /**
831      * Private helper method.
832      * Assumes parameters have been validated.
833      * @param values input data
834      * @param begin index (0-based) of the first array element to include
835      * @param length the number of elements to include
836      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
837      */
838     private static double[] getMode(double[] values, final int begin, final int length) {
839         // Add the values to the frequency table
840         Frequency<Double> freq = new Frequency<>();
841 
842         Arrays.stream(values, begin, begin + length)
843               .filter(d -> !Double.isNaN(d))
844               .forEach(freq::addValue);
845 
846         List<Double> list = freq.getMode();
847         // Convert the list to an array of primitive double
848         return list.stream()
849                    .mapToDouble(Double::doubleValue)
850                    .toArray();
851     }
852 
853 }