Home | History | Annotate | Download | only in stat
      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 fvr. 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      */
     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      */
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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