• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *      http://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 package org.apache.commons.math.stat;
18 
19 import org.apache.commons.math.MathRuntimeException;
20 import org.apache.commons.math.exception.util.LocalizedFormats;
21 import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
22 import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
23 import org.apache.commons.math.stat.descriptive.moment.GeometricMean;
24 import org.apache.commons.math.stat.descriptive.moment.Mean;
25 import org.apache.commons.math.stat.descriptive.moment.Variance;
26 import org.apache.commons.math.stat.descriptive.rank.Max;
27 import org.apache.commons.math.stat.descriptive.rank.Min;
28 import org.apache.commons.math.stat.descriptive.rank.Percentile;
29 import org.apache.commons.math.stat.descriptive.summary.Product;
30 import org.apache.commons.math.stat.descriptive.summary.Sum;
31 import org.apache.commons.math.stat.descriptive.summary.SumOfLogs;
32 import org.apache.commons.math.stat.descriptive.summary.SumOfSquares;
33 
34 /**
35  * StatUtils provides static methods for computing statistics based on data
36  * stored in double[] arrays.
37  *
38  * @version $Revision: 1073276 $ $Date: 2011-02-22 10:34:52 +0100 (mar. 22 févr. 2011) $
39  */
40 public final class StatUtils {
41 
42     /** sum */
43     private static final UnivariateStatistic SUM = new Sum();
44 
45     /** sumSq */
46     private static final UnivariateStatistic SUM_OF_SQUARES = new SumOfSquares();
47 
48     /** prod */
49     private static final UnivariateStatistic PRODUCT = new Product();
50 
51     /** sumLog */
52     private static final UnivariateStatistic SUM_OF_LOGS = new SumOfLogs();
53 
54     /** min */
55     private static final UnivariateStatistic MIN = new Min();
56 
57     /** max */
58     private static final UnivariateStatistic MAX = new Max();
59 
60     /** mean */
61     private static final UnivariateStatistic MEAN = new Mean();
62 
63     /** variance */
64     private static final Variance VARIANCE = new Variance();
65 
66     /** percentile */
67     private static final Percentile PERCENTILE = new Percentile();
68 
69     /** geometric mean */
70     private static final GeometricMean GEOMETRIC_MEAN = new GeometricMean();
71 
72     /**
73      * Private Constructor
74      */
StatUtils()75     private StatUtils() {
76     }
77 
78     /**
79      * Returns the sum of the values in the input array, or
80      * <code>Double.NaN</code> if the array is empty.
81      * <p>
82      * Throws <code>IllegalArgumentException</code> if the input array
83      * is null.</p>
84      *
85      * @param values  array of values to sum
86      * @return the sum of the values or <code>Double.NaN</code> if the array
87      * is empty
88      * @throws IllegalArgumentException if the array is null
89      */
sum(final double[] values)90     public static double sum(final double[] values) {
91         return SUM.evaluate(values);
92     }
93 
94     /**
95      * Returns the sum of the entries in the specified portion of
96      * the input array, or <code>Double.NaN</code> if the designated subarray
97      * is empty.
98      * <p>
99      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
100      *
101      * @param values the input array
102      * @param begin index of the first array element to include
103      * @param length the number of elements to include
104      * @return the sum of the values or Double.NaN if length = 0
105      * @throws IllegalArgumentException if the array is null or the array index
106      *  parameters are not valid
107      */
sum(final double[] values, final int begin, final int length)108     public static double sum(final double[] values, final int begin,
109             final int length) {
110         return SUM.evaluate(values, begin, length);
111     }
112 
113     /**
114      * Returns the sum of the squares of the entries in the input array, or
115      * <code>Double.NaN</code> if the array is empty.
116      * <p>
117      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
118      *
119      * @param values  input array
120      * @return the sum of the squared values or <code>Double.NaN</code> if the
121      * array is empty
122      * @throws IllegalArgumentException if the array is null
123      */
sumSq(final double[] values)124     public static double sumSq(final double[] values) {
125         return SUM_OF_SQUARES.evaluate(values);
126     }
127 
128     /**
129      * Returns the sum of the squares of the entries in the specified portion of
130      * the input array, or <code>Double.NaN</code> if the designated subarray
131      * is empty.
132      * <p>
133      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
134      *
135      * @param values the input array
136      * @param begin index of the first array element to include
137      * @param length the number of elements to include
138      * @return the sum of the squares of the values or Double.NaN if length = 0
139      * @throws IllegalArgumentException if the array is null or the array index
140      * parameters are not valid
141      */
sumSq(final double[] values, final int begin, final int length)142     public static double sumSq(final double[] values, final int begin,
143             final int length) {
144         return SUM_OF_SQUARES.evaluate(values, begin, length);
145     }
146 
147     /**
148      * Returns the product of the entries in the input array, or
149      * <code>Double.NaN</code> if the array is empty.
150      * <p>
151      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
152      *
153      * @param values the input array
154      * @return the product of the values or Double.NaN if the array is empty
155      * @throws IllegalArgumentException if the array is null
156      */
product(final double[] values)157     public static double product(final double[] values) {
158         return PRODUCT.evaluate(values);
159     }
160 
161     /**
162      * Returns the product of the entries in the specified portion of
163      * the input array, or <code>Double.NaN</code> if the designated subarray
164      * is empty.
165      * <p>
166      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
167      *
168      * @param values the input array
169      * @param begin index of the first array element to include
170      * @param length the number of elements to include
171      * @return the product of the values or Double.NaN if length = 0
172      * @throws IllegalArgumentException if the array is null or the array index
173      * parameters are not valid
174      */
product(final double[] values, final int begin, final int length)175     public static double product(final double[] values, final int begin,
176             final int length) {
177         return PRODUCT.evaluate(values, begin, length);
178     }
179 
180     /**
181      * Returns the sum of the natural logs of the entries in the input array, or
182      * <code>Double.NaN</code> if the array is empty.
183      * <p>
184      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
185      * <p>
186      * See {@link org.apache.commons.math.stat.descriptive.summary.SumOfLogs}.
187      * </p>
188      *
189      * @param values the input array
190      * @return the sum of the natural logs of the values or Double.NaN if
191      * the array is empty
192      * @throws IllegalArgumentException if the array is null
193      */
sumLog(final double[] values)194     public static double sumLog(final double[] values) {
195         return SUM_OF_LOGS.evaluate(values);
196     }
197 
198     /**
199      * Returns the sum of the natural logs of the entries in the specified portion of
200      * the input array, or <code>Double.NaN</code> if the designated subarray
201      * is empty.
202      * <p>
203      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
204      * <p>
205      * See {@link org.apache.commons.math.stat.descriptive.summary.SumOfLogs}.
206      * </p>
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 IllegalArgumentException if the array is null or the array index
214      * parameters are not valid
215      */
sumLog(final double[] values, final int begin, final int length)216     public static double sumLog(final double[] values, final int begin,
217             final int length) {
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.</p>
226      * <p>
227      * See {@link org.apache.commons.math.stat.descriptive.moment.Mean} for
228      * details on the computing algorithm.</p>
229      *
230      * @param values the input array
231      * @return the mean of the values or Double.NaN if the array is empty
232      * @throws IllegalArgumentException if the array is null
233      */
mean(final double[] values)234     public static double mean(final double[] values) {
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.</p>
244      * <p>
245      * See {@link org.apache.commons.math.stat.descriptive.moment.Mean} for
246      * details on the computing algorithm.</p>
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 IllegalArgumentException if the array is null or the array index
253      * parameters are not valid
254      */
mean(final double[] values, final int begin, final int length)255     public static double mean(final double[] values, final int begin,
256             final int length) {
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.</p>
265      * <p>
266      * See {@link org.apache.commons.math.stat.descriptive.moment.GeometricMean}
267      * for details on the computing algorithm.</p>
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 IllegalArgumentException if the array is null
272      */
geometricMean(final double[] values)273     public static double geometricMean(final double[] values) {
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.</p>
283      * <p>
284      * See {@link org.apache.commons.math.stat.descriptive.moment.GeometricMean}
285      * for details on the computing algorithm.</p>
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 IllegalArgumentException if the array is null or the array index
292      * parameters are not valid
293      */
geometricMean(final double[] values, final int begin, final int length)294     public static double geometricMean(final double[] values, final int begin,
295             final int length) {
296         return GEOMETRIC_MEAN.evaluate(values, begin, length);
297     }
298 
299 
300     /**
301      * Returns the variance of the entries in the input array, or
302      * <code>Double.NaN</code> if the array is empty.
303      * <p>
304      * See {@link org.apache.commons.math.stat.descriptive.moment.Variance} for
305      * details on the computing algorithm.</p>
306      * <p>
307      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
308      * <p>
309      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
310      *
311      * @param values the input array
312      * @return the variance of the values or Double.NaN if the array is empty
313      * @throws IllegalArgumentException if the array is null
314      */
variance(final double[] values)315     public static double variance(final double[] values) {
316         return VARIANCE.evaluate(values);
317     }
318 
319     /**
320      * Returns the variance of the entries in the specified portion of
321      * the input array, or <code>Double.NaN</code> if the designated subarray
322      * is empty.
323      * <p>
324      * See {@link org.apache.commons.math.stat.descriptive.moment.Variance} for
325      * details on the computing algorithm.</p>
326      * <p>
327      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
328      * <p>
329      * Throws <code>IllegalArgumentException</code> if the array is null or the
330      * array index parameters are not valid.</p>
331      *
332      * @param values the input array
333      * @param begin index of the first array element to include
334      * @param length the number of elements to include
335      * @return the variance of the values or Double.NaN if length = 0
336      * @throws IllegalArgumentException if the array is null or the array index
337      *  parameters are not valid
338      */
variance(final double[] values, final int begin, final int length)339     public static double variance(final double[] values, final int begin,
340             final int length) {
341         return VARIANCE.evaluate(values, begin, length);
342     }
343 
344     /**
345      * Returns the variance of the entries in the specified portion of
346      * the input array, using the precomputed mean value.  Returns
347      * <code>Double.NaN</code> if the designated subarray is empty.
348      * <p>
349      * See {@link org.apache.commons.math.stat.descriptive.moment.Variance} for
350      * details on the computing algorithm.</p>
351      * <p>
352      * The formula used assumes that the supplied mean value is the arithmetic
353      * mean of the sample data, not a known population parameter.  This method
354      * is supplied only to save computation when the mean has already been
355      * computed.</p>
356      * <p>
357      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
358      * <p>
359      * Throws <code>IllegalArgumentException</code> if the array is null or the
360      * array index parameters are not valid.</p>
361      *
362      * @param values the input array
363      * @param mean the precomputed mean value
364      * @param begin index of the first array element to include
365      * @param length the number of elements to include
366      * @return the variance of the values or Double.NaN if length = 0
367      * @throws IllegalArgumentException if the array is null or the array index
368      *  parameters are not valid
369      */
variance(final double[] values, final double mean, final int begin, final int length)370     public static double variance(final double[] values, final double mean,
371             final int begin, final int length) {
372         return VARIANCE.evaluate(values, mean, begin, length);
373     }
374 
375     /**
376      * Returns the variance of the entries in the input array, using the
377      * precomputed mean value.  Returns <code>Double.NaN</code> if the array
378      * is empty.
379      * <p>
380      * See {@link org.apache.commons.math.stat.descriptive.moment.Variance} for
381      * details on the computing algorithm.</p>
382      * <p>
383      * The formula used assumes that the supplied mean value is the arithmetic
384      * mean of the sample data, not a known population parameter.  This method
385      * is supplied only to save computation when the mean has already been
386      * computed.</p>
387      * <p>
388      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
389      * <p>
390      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
391      *
392      * @param values the input array
393      * @param mean the precomputed mean value
394      * @return the variance of the values or Double.NaN if the array is empty
395      * @throws IllegalArgumentException if the array is null
396      */
variance(final double[] values, final double mean)397     public static double variance(final double[] values, final double mean) {
398         return VARIANCE.evaluate(values, mean);
399     }
400 
401     /**
402      * Returns the maximum of the entries in the input array, or
403      * <code>Double.NaN</code> if the array is empty.
404      * <p>
405      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
406      * <p>
407      * <ul>
408      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
409      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
410      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
411      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
412      * </ul></p>
413      *
414      * @param values the input array
415      * @return the maximum of the values or Double.NaN if the array is empty
416      * @throws IllegalArgumentException if the array is null
417      */
max(final double[] values)418     public static double max(final double[] values) {
419         return MAX.evaluate(values);
420     }
421 
422     /**
423      * Returns the maximum of the entries in the specified portion of
424      * the input array, or <code>Double.NaN</code> if the designated subarray
425      * is empty.
426      * <p>
427      * Throws <code>IllegalArgumentException</code> if the array is null or
428      * the array index parameters are not valid.</p>
429      * <p>
430      * <ul>
431      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
432      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
433      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
434      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
435      * </ul></p>
436      *
437      * @param values the input array
438      * @param begin index of the first array element to include
439      * @param length the number of elements to include
440      * @return the maximum of the values or Double.NaN if length = 0
441      * @throws IllegalArgumentException if the array is null or the array index
442      * parameters are not valid
443      */
max(final double[] values, final int begin, final int length)444     public static double max(final double[] values, final int begin,
445             final int length) {
446         return MAX.evaluate(values, begin, length);
447     }
448 
449      /**
450      * Returns the minimum of the entries in the input array, or
451      * <code>Double.NaN</code> if the array is empty.
452      * <p>
453      * Throws <code>IllegalArgumentException</code> if the array is null.</p>
454      * <p>
455      * <ul>
456      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
457      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
458      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
459      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
460      * </ul> </p>
461      *
462      * @param values the input array
463      * @return the minimum of the values or Double.NaN if the array is empty
464      * @throws IllegalArgumentException if the array is null
465      */
min(final double[] values)466     public static double min(final double[] values) {
467         return MIN.evaluate(values);
468     }
469 
470      /**
471      * Returns the minimum of the entries in the specified portion of
472      * the input array, or <code>Double.NaN</code> if the designated subarray
473      * is empty.
474      * <p>
475      * Throws <code>IllegalArgumentException</code> if the array is null or
476      * the array index parameters are not valid.</p>
477      * <p>
478      * <ul>
479      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
480      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
481      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
482      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
483      * </ul></p>
484      *
485      * @param values the input array
486      * @param begin index of the first array element to include
487      * @param length the number of elements to include
488      * @return the minimum of the values or Double.NaN if length = 0
489      * @throws IllegalArgumentException if the array is null or the array index
490      * parameters are not valid
491      */
min(final double[] values, final int begin, final int length)492     public static double min(final double[] values, final int begin,
493             final int length) {
494         return MIN.evaluate(values, begin, length);
495     }
496 
497     /**
498      * Returns an estimate of the <code>p</code>th percentile of the values
499      * in the <code>values</code> array.
500      * <p>
501      * <ul>
502      * <li>Returns <code>Double.NaN</code> if <code>values</code> has length
503      * <code>0</code></li></p>
504      * <li>Returns (for any value of <code>p</code>) <code>values[0]</code>
505      *  if <code>values</code> has length <code>1</code></li>
506      * <li>Throws <code>IllegalArgumentException</code> if <code>values</code>
507      * is null  or p is not a valid quantile value (p must be greater than 0
508      * and less than or equal to 100)</li>
509      * </ul></p>
510      * <p>
511      * See {@link org.apache.commons.math.stat.descriptive.rank.Percentile} for
512      * a description of the percentile estimation algorithm used.</p>
513      *
514      * @param values input array of values
515      * @param p the percentile value to compute
516      * @return the percentile value or Double.NaN if the array is empty
517      * @throws IllegalArgumentException if <code>values</code> is null
518      * or p is invalid
519      */
percentile(final double[] values, final double p)520     public static double percentile(final double[] values, final double p) {
521             return PERCENTILE.evaluate(values,p);
522     }
523 
524      /**
525      * Returns an estimate of the <code>p</code>th percentile of the values
526      * in the <code>values</code> array, starting with the element in (0-based)
527      * position <code>begin</code> in the array and including <code>length</code>
528      * values.
529      * <p>
530      * <ul>
531      * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li>
532      * <li>Returns (for any value of <code>p</code>) <code>values[begin]</code>
533      *  if <code>length = 1 </code></li>
534      * <li>Throws <code>IllegalArgumentException</code> if <code>values</code>
535      *  is null , <code>begin</code> or <code>length</code> is invalid, or
536      * <code>p</code> is not a valid quantile value (p must be greater than 0
537      * and less than or equal to 100)</li>
538      * </ul></p>
539      * <p>
540       * See {@link org.apache.commons.math.stat.descriptive.rank.Percentile} for
541       * a description of the percentile estimation algorithm used.</p>
542      *
543      * @param values array of input values
544      * @param p  the percentile to compute
545      * @param begin  the first (0-based) element to include in the computation
546      * @param length  the number of array elements to include
547      * @return  the percentile value
548      * @throws IllegalArgumentException if the parameters are not valid or the
549      * input array is null
550      */
percentile(final double[] values, final int begin, final int length, final double p)551     public static double percentile(final double[] values, final int begin,
552             final int length, final double p) {
553         return PERCENTILE.evaluate(values, begin, length, p);
554     }
555 
556     /**
557      * Returns the sum of the (signed) differences between corresponding elements of the
558      * input arrays -- i.e., sum(sample1[i] - sample2[i]).
559      *
560      * @param sample1  the first array
561      * @param sample2  the second array
562      * @return sum of paired differences
563      * @throws IllegalArgumentException if the arrays do not have the same
564      * (positive) length
565      */
sumDifference(final double[] sample1, final double[] sample2)566     public static double sumDifference(final double[] sample1, final double[] sample2)
567         throws IllegalArgumentException {
568         int n = sample1.length;
569         if (n  != sample2.length) {
570             throw MathRuntimeException.createIllegalArgumentException(
571                   LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, n, sample2.length);
572         }
573         if (n < 1) {
574             throw MathRuntimeException.createIllegalArgumentException(
575                   LocalizedFormats.INSUFFICIENT_DIMENSION, sample2.length, 1);
576         }
577         double result = 0;
578         for (int i = 0; i < n; i++) {
579             result += sample1[i] - sample2[i];
580         }
581         return result;
582     }
583 
584     /**
585      * Returns the mean of the (signed) differences between corresponding elements of the
586      * input arrays -- i.e., sum(sample1[i] - sample2[i]) / sample1.length.
587      *
588      * @param sample1  the first array
589      * @param sample2  the second array
590      * @return mean of paired differences
591      * @throws IllegalArgumentException if the arrays do not have the same
592      * (positive) length
593      */
meanDifference(final double[] sample1, final double[] sample2)594     public static double meanDifference(final double[] sample1, final double[] sample2)
595     throws IllegalArgumentException {
596         return sumDifference(sample1, sample2) / sample1.length;
597     }
598 
599     /**
600      * Returns the variance of the (signed) differences between corresponding elements of the
601      * input arrays -- i.e., var(sample1[i] - sample2[i]).
602      *
603      * @param sample1  the first array
604      * @param sample2  the second array
605      * @param meanDifference   the mean difference between corresponding entries
606      * @see #meanDifference(double[],double[])
607      * @return variance of paired differences
608      * @throws IllegalArgumentException if the arrays do not have the same
609      * length or their common length is less than 2.
610      */
varianceDifference(final double[] sample1, final double[] sample2, double meanDifference)611     public static double varianceDifference(final double[] sample1, final double[] sample2,
612             double meanDifference)  throws IllegalArgumentException {
613         double sum1 = 0d;
614         double sum2 = 0d;
615         double diff = 0d;
616         int n = sample1.length;
617         if (n != sample2.length) {
618             throw MathRuntimeException.createIllegalArgumentException(
619                   LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE, n, sample2.length);
620         }
621         if (n < 2) {
622             throw MathRuntimeException.createIllegalArgumentException(
623                   LocalizedFormats.INSUFFICIENT_DIMENSION, n, 2);
624         }
625         for (int i = 0; i < n; i++) {
626             diff = sample1[i] - sample2[i];
627             sum1 += (diff - meanDifference) *(diff - meanDifference);
628             sum2 += diff - meanDifference;
629         }
630         return (sum1 - (sum2 * sum2 / n)) / (n - 1);
631     }
632 
633 
634     /**
635      * Normalize (standardize) the series, so in the end it is having a mean of 0 and a standard deviation of 1.
636      *
637      * @param sample sample to normalize
638      * @return normalized (standardized) sample
639      * @since 2.2
640      */
normalize(final double[] sample)641     public static double[] normalize(final double[] sample) {
642         DescriptiveStatistics stats = new DescriptiveStatistics();
643 
644         // Add the data from the series to stats
645         for (int i = 0; i < sample.length; i++) {
646             stats.addValue(sample[i]);
647         }
648 
649         // Compute mean and standard deviation
650         double mean = stats.getMean();
651         double standardDeviation = stats.getStandardDeviation();
652 
653         // initialize the standardizedSample, which has the same length as the sample
654         double[] standardizedSample = new double[sample.length];
655 
656         for (int i = 0; i < sample.length; i++) {
657             // z = (x- mean)/standardDeviation
658             standardizedSample[i] = (sample[i] - mean) / standardDeviation;
659         }
660         return standardizedSample;
661     }
662 
663 }
664