StatUtils.java

  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.  * This is not the original file distributed by the Apache Software Foundation
  19.  * It has been modified by the Hipparchus project
  20.  */
  21. package org.hipparchus.stat;

  22. import java.util.Arrays;
  23. import java.util.List;

  24. import org.hipparchus.exception.LocalizedCoreFormats;
  25. import org.hipparchus.exception.MathIllegalArgumentException;
  26. import org.hipparchus.stat.descriptive.DescriptiveStatistics;
  27. import org.hipparchus.stat.descriptive.UnivariateStatistic;
  28. import org.hipparchus.stat.descriptive.moment.GeometricMean;
  29. import org.hipparchus.stat.descriptive.moment.Mean;
  30. import org.hipparchus.stat.descriptive.moment.Variance;
  31. import org.hipparchus.stat.descriptive.rank.Max;
  32. import org.hipparchus.stat.descriptive.rank.Min;
  33. import org.hipparchus.stat.descriptive.rank.Percentile;
  34. import org.hipparchus.stat.descriptive.summary.Product;
  35. import org.hipparchus.stat.descriptive.summary.Sum;
  36. import org.hipparchus.stat.descriptive.summary.SumOfLogs;
  37. import org.hipparchus.stat.descriptive.summary.SumOfSquares;
  38. import org.hipparchus.util.MathArrays;
  39. import org.hipparchus.util.MathUtils;

  40. /**
  41.  * StatUtils provides static methods for computing statistics based on data
  42.  * stored in double[] arrays.
  43.  */
  44. public final class StatUtils {

  45.     /** sum */
  46.     private static final UnivariateStatistic SUM = new Sum();

  47.     /** sumSq */
  48.     private static final UnivariateStatistic SUM_OF_SQUARES = new SumOfSquares();

  49.     /** prod */
  50.     private static final UnivariateStatistic PRODUCT = new Product();

  51.     /** sumLog */
  52.     private static final UnivariateStatistic SUM_OF_LOGS = new SumOfLogs();

  53.     /** min */
  54.     private static final UnivariateStatistic MIN = new Min();

  55.     /** max */
  56.     private static final UnivariateStatistic MAX = new Max();

  57.     /** mean */
  58.     private static final UnivariateStatistic MEAN = new Mean();

  59.     /** variance */
  60.     private static final Variance VARIANCE = new Variance();

  61.     /** percentile */
  62.     private static final Percentile PERCENTILE = new Percentile();

  63.     /** geometric mean */
  64.     private static final GeometricMean GEOMETRIC_MEAN = new GeometricMean();

  65.     /**
  66.      * Private Constructor
  67.      */
  68.     private StatUtils() {
  69.     }

  70.     /**
  71.      * Returns the sum of the values in the input array, or
  72.      * <code>Double.NaN</code> if the array is empty.
  73.      * <p>
  74.      * Throws <code>IllegalArgumentException</code> if the input array is null.
  75.      *
  76.      * @param values  array of values to sum
  77.      * @return the sum of the values or <code>Double.NaN</code> if the array is empty
  78.      * @throws MathIllegalArgumentException if the array is null
  79.      */
  80.     public static double sum(final double... values) throws MathIllegalArgumentException {
  81.         return SUM.evaluate(values);
  82.     }

  83.     /**
  84.      * Returns the sum of the entries in the specified portion of
  85.      * the input array, or <code>Double.NaN</code> if the designated subarray is empty.
  86.      * <p>
  87.      * Throws <code>IllegalArgumentException</code> if the array is null.
  88.      *
  89.      * @param values the input array
  90.      * @param begin index of the first array element to include
  91.      * @param length the number of elements to include
  92.      * @return the sum of the values or Double.NaN if length = 0
  93.      * @throws MathIllegalArgumentException if the array is null or the array index
  94.      *  parameters are not valid
  95.      */
  96.     public static double sum(final double[] values, final int begin, final int length)
  97.         throws MathIllegalArgumentException {
  98.         return SUM.evaluate(values, begin, length);
  99.     }

  100.     /**
  101.      * Returns the sum of the squares of the entries in the input array, or
  102.      * <code>Double.NaN</code> if the array is empty.
  103.      * <p>
  104.      * Throws <code>IllegalArgumentException</code> if the array is null.
  105.      *
  106.      * @param values  input array
  107.      * @return the sum of the squared values or <code>Double.NaN</code> if the array is empty
  108.      * @throws MathIllegalArgumentException if the array is null
  109.      */
  110.     public static double sumSq(final double... values) throws MathIllegalArgumentException {
  111.         return SUM_OF_SQUARES.evaluate(values);
  112.     }

  113.     /**
  114.      * Returns the sum of the squares of the entries in the specified portion of
  115.      * the input array, or <code>Double.NaN</code> if the designated subarray
  116.      * is empty.
  117.      * <p>
  118.      * Throws <code>IllegalArgumentException</code> if the array is null.
  119.      *
  120.      * @param values the input array
  121.      * @param begin index of the first array element to include
  122.      * @param length the number of elements to include
  123.      * @return the sum of the squares of the values or Double.NaN if length = 0
  124.      * @throws MathIllegalArgumentException if the array is null or the array index
  125.      *  parameters are not valid
  126.      */
  127.     public static double sumSq(final double[] values, final int begin, final int length)
  128.         throws MathIllegalArgumentException {
  129.         return SUM_OF_SQUARES.evaluate(values, begin, length);
  130.     }

  131.     /**
  132.      * Returns the product of the entries in the input array, or
  133.      * <code>Double.NaN</code> if the array is empty.
  134.      * <p>
  135.      * Throws <code>IllegalArgumentException</code> if the array is null.
  136.      *
  137.      * @param values the input array
  138.      * @return the product of the values or Double.NaN if the array is empty
  139.      * @throws MathIllegalArgumentException if the array is null
  140.      */
  141.     public static double product(final double... values) throws MathIllegalArgumentException {
  142.         return PRODUCT.evaluate(values);
  143.     }

  144.     /**
  145.      * Returns the product of the entries in the specified portion of
  146.      * the input array, or <code>Double.NaN</code> if the designated subarray
  147.      * is empty.
  148.      * <p>
  149.      * Throws <code>IllegalArgumentException</code> if the array is null.
  150.      *
  151.      * @param values the input array
  152.      * @param begin index of the first array element to include
  153.      * @param length the number of elements to include
  154.      * @return the product of the values or Double.NaN if length = 0
  155.      * @throws MathIllegalArgumentException if the array is null or the array index
  156.      *  parameters are not valid
  157.      */
  158.     public static double product(final double[] values, final int begin, final int length)
  159.         throws MathIllegalArgumentException {
  160.         return PRODUCT.evaluate(values, begin, length);
  161.     }

  162.     /**
  163.      * Returns the sum of the natural logs of the entries in the input array, or
  164.      * <code>Double.NaN</code> if the array is empty.
  165.      * <p>
  166.      * Throws <code>IllegalArgumentException</code> if the array is null.
  167.      * <p>
  168.      * See {@link org.hipparchus.stat.descriptive.summary.SumOfLogs}.
  169.      *
  170.      * @param values the input array
  171.      * @return the sum of the natural logs of the values or Double.NaN if the array is empty
  172.      * @throws MathIllegalArgumentException if the array is null
  173.      */
  174.     public static double sumLog(final double... values) throws MathIllegalArgumentException {
  175.         return SUM_OF_LOGS.evaluate(values);
  176.     }

  177.     /**
  178.      * Returns the sum of the natural logs of the entries in the specified portion of
  179.      * the input array, or <code>Double.NaN</code> if the designated subarray is empty.
  180.      * <p>
  181.      * Throws <code>IllegalArgumentException</code> if the array is null.
  182.      * <p>
  183.      * See {@link org.hipparchus.stat.descriptive.summary.SumOfLogs}.
  184.      *
  185.      * @param values the input array
  186.      * @param begin index of the first array element to include
  187.      * @param length the number of elements to include
  188.      * @return the sum of the natural logs of the values or Double.NaN if
  189.      * length = 0
  190.      * @throws MathIllegalArgumentException if the array is null or the array index
  191.      * parameters are not valid
  192.      */
  193.     public static double sumLog(final double[] values, final int begin, final int length)
  194.         throws MathIllegalArgumentException {
  195.         return SUM_OF_LOGS.evaluate(values, begin, length);
  196.     }

  197.     /**
  198.      * Returns the arithmetic mean of the entries in the input array, or
  199.      * <code>Double.NaN</code> if the array is empty.
  200.      * <p>
  201.      * Throws <code>IllegalArgumentException</code> if the array is null.
  202.      * <p>
  203.      * See {@link org.hipparchus.stat.descriptive.moment.Mean} for
  204.      * details on the computing algorithm.
  205.      *
  206.      * @param values the input array
  207.      * @return the mean of the values or Double.NaN if the array is empty
  208.      * @throws MathIllegalArgumentException if the array is null
  209.      */
  210.     public static double mean(final double... values) throws MathIllegalArgumentException {
  211.         return MEAN.evaluate(values);
  212.     }

  213.     /**
  214.      * Returns the arithmetic mean of the entries in the specified portion of
  215.      * the input array, or <code>Double.NaN</code> if the designated subarray
  216.      * is empty.
  217.      * <p>
  218.      * Throws <code>IllegalArgumentException</code> if the array is null.
  219.      * <p>
  220.      * See {@link org.hipparchus.stat.descriptive.moment.Mean Mean} for
  221.      * details on the computing algorithm.
  222.      *
  223.      * @param values the input array
  224.      * @param begin index of the first array element to include
  225.      * @param length the number of elements to include
  226.      * @return the mean of the values or Double.NaN if length = 0
  227.      * @throws MathIllegalArgumentException if the array is null or the array index
  228.      * parameters are not valid
  229.      */
  230.     public static double mean(final double[] values, final int begin, final int length)
  231.         throws MathIllegalArgumentException {
  232.         return MEAN.evaluate(values, begin, length);
  233.     }

  234.     /**
  235.      * Returns the geometric mean of the entries in the input array, or
  236.      * <code>Double.NaN</code> if the array is empty.
  237.      * <p>
  238.      * Throws <code>IllegalArgumentException</code> if the array is null.
  239.      * <p>
  240.      * See {@link org.hipparchus.stat.descriptive.moment.GeometricMean GeometricMean}
  241.      * for details on the computing algorithm.
  242.      *
  243.      * @param values the input array
  244.      * @return the geometric mean of the values or Double.NaN if the array is empty
  245.      * @throws MathIllegalArgumentException if the array is null
  246.      */
  247.     public static double geometricMean(final double... values) throws MathIllegalArgumentException {
  248.         return GEOMETRIC_MEAN.evaluate(values);
  249.     }

  250.     /**
  251.      * Returns the geometric mean of the entries in the specified portion of
  252.      * the input array, or <code>Double.NaN</code> if the designated subarray
  253.      * is empty.
  254.      * <p>
  255.      * Throws <code>IllegalArgumentException</code> if the array is null.
  256.      * <p>
  257.      * See {@link org.hipparchus.stat.descriptive.moment.GeometricMean GeometricMean}
  258.      * for details on the computing algorithm.
  259.      *
  260.      * @param values the input array
  261.      * @param begin index of the first array element to include
  262.      * @param length the number of elements to include
  263.      * @return the geometric mean of the values or Double.NaN if length = 0
  264.      * @throws MathIllegalArgumentException if the array is null or the array index
  265.      *  parameters are not valid
  266.      */
  267.     public static double geometricMean(final double[] values, final int begin, final int length)
  268.         throws MathIllegalArgumentException {
  269.         return GEOMETRIC_MEAN.evaluate(values, begin, length);
  270.     }

  271.     /**
  272.      * Returns the variance of the entries in the input array, or
  273.      * <code>Double.NaN</code> if the array is empty.
  274.      * <p>
  275.      * This method returns the bias-corrected sample variance (using {@code n - 1} in
  276.      * the denominator). Use {@link #populationVariance(double[])} for the non-bias-corrected
  277.      * population variance.
  278.      * <p>
  279.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  280.      * details on the computing algorithm.
  281.      * <p>
  282.      * Returns 0 for a single-value (i.e. length = 1) sample.
  283.      * <p>
  284.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  285.      *
  286.      * @param values the input array
  287.      * @return the variance of the values or Double.NaN if the array is empty
  288.      * @throws MathIllegalArgumentException if the array is null
  289.      */
  290.     public static double variance(final double... values) throws MathIllegalArgumentException {
  291.         return VARIANCE.evaluate(values);
  292.     }

  293.     /**
  294.      * Returns the variance of the entries in the specified portion of
  295.      * the input array, or <code>Double.NaN</code> if the designated subarray
  296.      * is empty.
  297.      * <p>
  298.      * This method returns the bias-corrected sample variance (using {@code n - 1} in
  299.      * the denominator). Use {@link #populationVariance(double[], int, int)} for the non-bias-corrected
  300.      * population variance.
  301.      * <p>
  302.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  303.      * details on the computing algorithm.
  304.      * <p>
  305.      * Returns 0 for a single-value (i.e. length = 1) sample.
  306.      * <p>
  307.      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
  308.      * array index parameters are not valid.
  309.      *
  310.      * @param values the input array
  311.      * @param begin index of the first array element to include
  312.      * @param length the number of elements to include
  313.      * @return the variance of the values or Double.NaN if length = 0
  314.      * @throws MathIllegalArgumentException if the array is null or the array index
  315.      *  parameters are not valid
  316.      */
  317.     public static double variance(final double[] values, final int begin, final int length)
  318.         throws MathIllegalArgumentException {
  319.         return VARIANCE.evaluate(values, begin, length);
  320.     }

  321.     /**
  322.      * Returns the variance of the entries in the specified portion of
  323.      * the input array, using the precomputed mean value.  Returns
  324.      * <code>Double.NaN</code> if the designated subarray is empty.
  325.      * <p>
  326.      * This method returns the bias-corrected sample variance (using {@code n - 1} in
  327.      * the denominator). Use {@link #populationVariance(double[], double, int, int)} for
  328.      * the non-bias-corrected population variance.
  329.      * <p>
  330.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  331.      * details on the computing algorithm.
  332.      * <p>
  333.      * The formula used assumes that the supplied mean value is the arithmetic
  334.      * mean of the sample data, not a known population parameter.  This method
  335.      * is supplied only to save computation when the mean has already been
  336.      * computed.
  337.      * <p>
  338.      * Returns 0 for a single-value (i.e. length = 1) sample.
  339.      * <p>
  340.      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
  341.      * array index parameters are not valid.
  342.      *
  343.      * @param values the input array
  344.      * @param mean the precomputed mean value
  345.      * @param begin index of the first array element to include
  346.      * @param length the number of elements to include
  347.      * @return the variance of the values or Double.NaN if length = 0
  348.      * @throws MathIllegalArgumentException if the array is null or the array index
  349.      *  parameters are not valid
  350.      */
  351.     public static double variance(final double[] values, final double mean, final int begin, final int length)
  352.         throws MathIllegalArgumentException {
  353.         return VARIANCE.evaluate(values, mean, begin, length);
  354.     }

  355.     /**
  356.      * Returns the variance of the entries in the input array, using the
  357.      * precomputed mean value.  Returns <code>Double.NaN</code> if the array
  358.      * is empty.
  359.      * <p>
  360.      * This method returns the bias-corrected sample variance (using {@code n - 1} in
  361.      * the denominator).  Use {@link #populationVariance(double[], double)} for the
  362.      * non-bias-corrected population variance.
  363.      * <p>
  364.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  365.      * details on the computing algorithm.
  366.      * <p>
  367.      * The formula used assumes that the supplied mean value is the arithmetic
  368.      * mean of the sample data, not a known population parameter.  This method
  369.      * is supplied only to save computation when the mean has already been
  370.      * computed.
  371.      * <p>
  372.      * Returns 0 for a single-value (i.e. length = 1) sample.
  373.      * <p>
  374.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  375.      *
  376.      * @param values the input array
  377.      * @param mean the precomputed mean value
  378.      * @return the variance of the values or Double.NaN if the array is empty
  379.      * @throws MathIllegalArgumentException if the array is null
  380.      */
  381.     public static double variance(final double[] values, final double mean) throws MathIllegalArgumentException {
  382.         return VARIANCE.evaluate(values, mean);
  383.     }

  384.     /**
  385.      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
  386.      * population variance</a> of the entries in the input array, or
  387.      * <code>Double.NaN</code> if the array is empty.
  388.      * <p>
  389.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  390.      * details on the formula and computing algorithm.
  391.      * <p>
  392.      * Returns 0 for a single-value (i.e. length = 1) sample.
  393.      * <p>
  394.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  395.      *
  396.      * @param values the input array
  397.      * @return the population variance of the values or Double.NaN if the array is empty
  398.      * @throws MathIllegalArgumentException if the array is null
  399.      */
  400.     public static double populationVariance(final double... values) throws MathIllegalArgumentException {
  401.         return new Variance(false).evaluate(values);
  402.     }

  403.     /**
  404.      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
  405.      * population variance</a> of the entries in the specified portion of
  406.      * the input array, or <code>Double.NaN</code> if the designated subarray
  407.      * is empty.
  408.      * <p>
  409.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  410.      * details on the computing algorithm.
  411.      * <p>
  412.      * Returns 0 for a single-value (i.e. length = 1) sample.
  413.      * <p>
  414.      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
  415.      * array index parameters are not valid.
  416.      *
  417.      * @param values the input array
  418.      * @param begin index of the first array element to include
  419.      * @param length the number of elements to include
  420.      * @return the population variance of the values or Double.NaN if length = 0
  421.      * @throws MathIllegalArgumentException if the array is null or the array index
  422.      *  parameters are not valid
  423.      */
  424.     public static double populationVariance(final double[] values, final int begin, final int length)
  425.         throws MathIllegalArgumentException {
  426.         return new Variance(false).evaluate(values, begin, length);
  427.     }

  428.     /**
  429.      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
  430.      * population variance</a> of the entries in the specified portion of
  431.      * the input array, using the precomputed mean value.  Returns
  432.      * <code>Double.NaN</code> if the designated subarray is empty.
  433.      * <p>
  434.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  435.      * details on the computing algorithm.
  436.      * <p>
  437.      * The formula used assumes that the supplied mean value is the arithmetic
  438.      * mean of the sample data, not a known population parameter.  This method
  439.      * is supplied only to save computation when the mean has already been
  440.      * computed.
  441.      * <p>
  442.      * Returns 0 for a single-value (i.e. length = 1) sample.
  443.      * <p>
  444.      * Throws <code>MathIllegalArgumentException</code> if the array is null or the
  445.      * array index parameters are not valid.
  446.      *
  447.      * @param values the input array
  448.      * @param mean the precomputed mean value
  449.      * @param begin index of the first array element to include
  450.      * @param length the number of elements to include
  451.      * @return the population variance of the values or Double.NaN if length = 0
  452.      * @throws MathIllegalArgumentException if the array is null or the array index
  453.      *  parameters are not valid
  454.      */
  455.     public static double populationVariance(final double[] values, final double mean,
  456.                                             final int begin, final int length)
  457.         throws MathIllegalArgumentException {
  458.         return new Variance(false).evaluate(values, mean, begin, length);
  459.     }

  460.     /**
  461.      * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance">
  462.      * population variance</a> of the entries in the input array, using the precomputed
  463.      * mean value. Returns <code>Double.NaN</code> if the array is empty.
  464.      * <p>
  465.      * See {@link org.hipparchus.stat.descriptive.moment.Variance Variance} for
  466.      * details on the computing algorithm.
  467.      * <p>
  468.      * The formula used assumes that the supplied mean value is the arithmetic
  469.      * mean of the sample data, not a known population parameter. This method is
  470.      * supplied only to save computation when the mean has already been computed.
  471.      * <p>
  472.      * Returns 0 for a single-value (i.e. length = 1) sample.
  473.      * <p>
  474.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  475.      *
  476.      * @param values the input array
  477.      * @param mean the precomputed mean value
  478.      * @return the population variance of the values or Double.NaN if the array is empty
  479.      * @throws MathIllegalArgumentException if the array is null
  480.      */
  481.     public static double populationVariance(final double[] values, final double mean)
  482.         throws MathIllegalArgumentException {
  483.         return new Variance(false).evaluate(values, mean);
  484.     }

  485.     /**
  486.      * Returns the maximum of the entries in the input array, or
  487.      * <code>Double.NaN</code> if the array is empty.
  488.      * <p>
  489.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  490.      * </p>
  491.      * <ul>
  492.      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
  493.      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
  494.      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
  495.      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
  496.      * </ul>
  497.      *
  498.      * @param values the input array
  499.      * @return the maximum of the values or Double.NaN if the array is empty
  500.      * @throws MathIllegalArgumentException if the array is null
  501.      */
  502.     public static double max(final double... values) throws MathIllegalArgumentException {
  503.         return MAX.evaluate(values);
  504.     }

  505.     /**
  506.      * Returns the maximum of the entries in the specified portion of the input array,
  507.      * or <code>Double.NaN</code> if the designated subarray is empty.
  508.      * <p>
  509.      * Throws <code>MathIllegalArgumentException</code> if the array is null or
  510.      * the array index parameters are not valid.
  511.      * </p>
  512.      * <ul>
  513.      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
  514.      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
  515.      * <li>If any of the values equals <code>Double.POSITIVE_INFINITY</code>,
  516.      * the result is <code>Double.POSITIVE_INFINITY.</code></li>
  517.      * </ul>
  518.      *
  519.      * @param values the input array
  520.      * @param begin index of the first array element to include
  521.      * @param length the number of elements to include
  522.      * @return the maximum of the values or Double.NaN if length = 0
  523.      * @throws MathIllegalArgumentException if the array is null or the array index
  524.      *  parameters are not valid
  525.      */
  526.     public static double max(final double[] values, final int begin, final int length)
  527.         throws MathIllegalArgumentException {
  528.         return MAX.evaluate(values, begin, length);
  529.     }

  530.     /**
  531.      * Returns the minimum of the entries in the input array, or
  532.      * <code>Double.NaN</code> if the array is empty.
  533.      * <p>
  534.      * Throws <code>MathIllegalArgumentException</code> if the array is null.
  535.      * </p>
  536.      * <ul>
  537.      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
  538.      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
  539.      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
  540.      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
  541.      * </ul>
  542.      *
  543.      * @param values the input array
  544.      * @return the minimum of the values or Double.NaN if the array is empty
  545.      * @throws MathIllegalArgumentException if the array is null
  546.      */
  547.     public static double min(final double... values) throws MathIllegalArgumentException {
  548.         return MIN.evaluate(values);
  549.     }

  550.     /**
  551.      * Returns the minimum of the entries in the specified portion of the input array,
  552.      * or <code>Double.NaN</code> if the designated subarray is empty.
  553.      * <p>
  554.      * Throws <code>MathIllegalArgumentException</code> if the array is null or
  555.      * the array index parameters are not valid.
  556.      * </p>
  557.      * <ul>
  558.      * <li>The result is <code>NaN</code> iff all values are <code>NaN</code>
  559.      * (i.e. <code>NaN</code> values have no impact on the value of the statistic).</li>
  560.      * <li>If any of the values equals <code>Double.NEGATIVE_INFINITY</code>,
  561.      * the result is <code>Double.NEGATIVE_INFINITY.</code></li>
  562.      * </ul>
  563.      *
  564.      * @param values the input array
  565.      * @param begin index of the first array element to include
  566.      * @param length the number of elements to include
  567.      * @return the minimum of the values or Double.NaN if length = 0
  568.      * @throws MathIllegalArgumentException if the array is null or the array index
  569.      *  parameters are not valid
  570.      */
  571.     public static double min(final double[] values, final int begin, final int length)
  572.         throws MathIllegalArgumentException {
  573.         return MIN.evaluate(values, begin, length);
  574.     }

  575.     /**
  576.      * Returns an estimate of the <code>p</code>th percentile of the values
  577.      * in the <code>values</code> array.
  578.      * <ul>
  579.      * <li>Returns <code>Double.NaN</code> if <code>values</code> has length
  580.      *  <code>0</code></li>
  581.      * <li>Returns (for any value of <code>p</code>) <code>values[0]</code>
  582.      *  if <code>values</code> has length <code>1</code></li>
  583.      * <li>Throws <code>IllegalArgumentException</code> if <code>values</code>
  584.      *  is null  or p is not a valid quantile value (p must be greater than 0
  585.      *  and less than or equal to 100)</li>
  586.      * </ul>
  587.      * <p>
  588.      * See {@link org.hipparchus.stat.descriptive.rank.Percentile Percentile}
  589.      * for a description of the percentile estimation algorithm used.
  590.      *
  591.      * @param values input array of values
  592.      * @param p the percentile value to compute
  593.      * @return the percentile value or Double.NaN if the array is empty
  594.      * @throws MathIllegalArgumentException if <code>values</code> is null or p is invalid
  595.      */
  596.     public static double percentile(final double[] values, final double p) throws MathIllegalArgumentException {
  597.         return PERCENTILE.evaluate(values,p);
  598.     }

  599.     /**
  600.      * Returns an estimate of the <code>p</code>th percentile of the values
  601.      * in the <code>values</code> array, starting with the element in (0-based)
  602.      * position <code>begin</code> in the array and including <code>length</code>
  603.      * values.
  604.      * <ul>
  605.      * <li>Returns <code>Double.NaN</code> if <code>length = 0</code></li>
  606.      * <li>Returns (for any value of <code>p</code>) <code>values[begin]</code>
  607.      *  if <code>length = 1 </code></li>
  608.      * <li>Throws <code>MathIllegalArgumentException</code> if <code>values</code>
  609.      *  is null, <code>begin</code> or <code>length</code> is invalid, or
  610.      *  <code>p</code> is not a valid quantile value (p must be greater than 0
  611.      *  and less than or equal to 100)</li>
  612.      * </ul>
  613.      * <p>
  614.      * See {@link org.hipparchus.stat.descriptive.rank.Percentile Percentile}
  615.      * for a description of the percentile estimation algorithm used.
  616.      *
  617.      * @param values array of input values
  618.      * @param p the percentile to compute
  619.      * @param begin the first (0-based) element to include in the computation
  620.      * @param length the number of array elements to include
  621.      * @return the percentile value
  622.      * @throws MathIllegalArgumentException if the parameters are not valid or the input array is null
  623.      */
  624.     public static double percentile(final double[] values, final int begin, final int length, final double p)
  625.         throws MathIllegalArgumentException {
  626.         return PERCENTILE.evaluate(values, begin, length, p);
  627.     }

  628.     /**
  629.      * Returns the sum of the (signed) differences between corresponding elements of the
  630.      * input arrays -- i.e., sum(sample1[i] - sample2[i]).
  631.      *
  632.      * @param sample1  the first array
  633.      * @param sample2  the second array
  634.      * @return sum of paired differences
  635.      * @throws MathIllegalArgumentException if the arrays do not have the same (positive) length.
  636.      * @throws MathIllegalArgumentException if the sample arrays are empty.
  637.      */
  638.     public static double sumDifference(final double[] sample1, final double[] sample2)
  639.         throws MathIllegalArgumentException {

  640.         int n = sample1.length;
  641.         MathArrays.checkEqualLength(sample1, sample2);
  642.         if (n <= 0) {
  643.             throw new MathIllegalArgumentException(LocalizedCoreFormats.INSUFFICIENT_DIMENSION);
  644.         }
  645.         double result = 0;
  646.         for (int i = 0; i < n; i++) {
  647.             result += sample1[i] - sample2[i];
  648.         }
  649.         return result;
  650.     }

  651.     /**
  652.      * Returns the mean of the (signed) differences between corresponding elements of the
  653.      * input arrays -- i.e., sum(sample1[i] - sample2[i]) / sample1.length.
  654.      *
  655.      * @param sample1  the first array
  656.      * @param sample2  the second array
  657.      * @return mean of paired differences
  658.      * @throws MathIllegalArgumentException if the arrays do not have the same (positive) length.
  659.      * @throws MathIllegalArgumentException if the sample arrays are empty.
  660.      */
  661.     public static double meanDifference(final double[] sample1, final double[] sample2)
  662.         throws MathIllegalArgumentException {
  663.         return sumDifference(sample1, sample2) / sample1.length;
  664.     }

  665.     /**
  666.      * Returns the variance of the (signed) differences between corresponding elements of the
  667.      * input arrays -- i.e., var(sample1[i] - sample2[i]).
  668.      *
  669.      * @param sample1  the first array
  670.      * @param sample2  the second array
  671.      * @param meanDifference   the mean difference between corresponding entries
  672.      * @return variance of paired differences
  673.      * @throws MathIllegalArgumentException if the arrays do not have the same length.
  674.      * @throws MathIllegalArgumentException if the arrays length is less than 2.
  675.      * @see #meanDifference(double[],double[])
  676.      */
  677.     public static double varianceDifference(final double[] sample1, final double[] sample2, double meanDifference)
  678.         throws MathIllegalArgumentException {

  679.         double sum1 = 0d;
  680.         double sum2 = 0d;
  681.         int n = sample1.length;
  682.         MathArrays.checkEqualLength(sample1, sample2);
  683.         if (n < 2) {
  684.             throw new MathIllegalArgumentException(LocalizedCoreFormats.NUMBER_TOO_SMALL,
  685.                                                    n, 2);
  686.         }
  687.         for (int i = 0; i < n; i++) {
  688.             final double diff = sample1[i] - sample2[i];
  689.             sum1 += (diff - meanDifference) *(diff - meanDifference);
  690.             sum2 += diff - meanDifference;
  691.         }
  692.         return (sum1 - (sum2 * sum2 / n)) / (n - 1);
  693.     }

  694.     /**
  695.      * Normalize (standardize) the sample, so it is has a mean of 0 and a standard deviation of 1.
  696.      *
  697.      * @param sample Sample to normalize.
  698.      * @return normalized (standardized) sample.
  699.      */
  700.     public static double[] normalize(final double... sample) {
  701.         DescriptiveStatistics stats = new DescriptiveStatistics();

  702.         // Add the data from the series to stats
  703.         for (int i = 0; i < sample.length; i++) {
  704.             stats.addValue(sample[i]);
  705.         }

  706.         // Compute mean and standard deviation
  707.         double mean = stats.getMean();
  708.         double standardDeviation = stats.getStandardDeviation();

  709.         // initialize the standardizedSample, which has the same length as the sample
  710.         double[] standardizedSample = new double[sample.length];

  711.         for (int i = 0; i < sample.length; i++) {
  712.             // z = (x- mean)/standardDeviation
  713.             standardizedSample[i] = (sample[i] - mean) / standardDeviation;
  714.         }
  715.         return standardizedSample;
  716.     }

  717.     /**
  718.      * Returns the sample mode(s).
  719.      * <p>
  720.      * The mode is the most frequently occurring value in the sample.
  721.      * If there is a unique value with maximum frequency, this value is returned
  722.      * as the only element of the output array. Otherwise, the returned array
  723.      * contains the maximum frequency elements in increasing order.
  724.      * <p>
  725.      * For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
  726.      * the returned array will have length two, with 0 in the first element and
  727.      * 5 in the second.
  728.      * <p>
  729.      * NaN values are ignored when computing the mode - i.e., NaNs will never
  730.      * appear in the output array.  If the sample includes only NaNs or has
  731.      * length 0, an empty array is returned.
  732.      *
  733.      * @param sample input data
  734.      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
  735.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  736.      */
  737.     public static double[] mode(double... sample) throws MathIllegalArgumentException {
  738.         MathUtils.checkNotNull(sample, LocalizedCoreFormats.INPUT_ARRAY);
  739.         return getMode(sample, 0, sample.length);
  740.     }

  741.     /**
  742.      * Returns the sample mode(s).
  743.      * <p>
  744.      * The mode is the most frequently occurring value in the sample.
  745.      * If there is a unique value with maximum frequency, this value is returned
  746.      * as the only element of the output array. Otherwise, the returned array
  747.      * contains the maximum frequency elements in increasing order.
  748.      * <p>
  749.      * For example, if {@code sample} is {0, 12, 5, 6, 0, 13, 5, 17},
  750.      * the returned array will have length two, with 0 in the first element and
  751.      * 5 in the second.
  752.      * <p>
  753.      * NaN values are ignored when computing the mode - i.e., NaNs will never
  754.      * appear in the output array.  If the sample includes only NaNs or has
  755.      * length 0, an empty array is returned.
  756.      *
  757.      * @param sample input data
  758.      * @param begin index (0-based) of the first array element to include
  759.      * @param length the number of elements to include
  760.      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
  761.      * @throws MathIllegalArgumentException if the indices are invalid or the array is null
  762.      */
  763.     public static double[] mode(double[] sample, final int begin, final int length) {
  764.         MathUtils.checkNotNull(sample, LocalizedCoreFormats.INPUT_ARRAY);

  765.         if (begin < 0) {
  766.             throw new MathIllegalArgumentException(LocalizedCoreFormats.START_POSITION, Integer.valueOf(begin));
  767.         }

  768.         if (length < 0) {
  769.             throw new MathIllegalArgumentException(LocalizedCoreFormats.LENGTH, Integer.valueOf(length));
  770.         }

  771.         return getMode(sample, begin, length);
  772.     }

  773.     /**
  774.      * Private helper method.
  775.      * Assumes parameters have been validated.
  776.      * @param values input data
  777.      * @param begin index (0-based) of the first array element to include
  778.      * @param length the number of elements to include
  779.      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
  780.      */
  781.     private static double[] getMode(double[] values, final int begin, final int length) {
  782.         // Add the values to the frequency table
  783.         Frequency<Double> freq = new Frequency<>();

  784.         Arrays.stream(values, begin, begin + length)
  785.               .filter(d -> !Double.isNaN(d))
  786.               .forEach(freq::addValue);

  787.         List<Double> list = freq.getMode();
  788.         // Convert the list to an array of primitive double
  789.         return list.stream()
  790.                    .mapToDouble(Double::doubleValue)
  791.                    .toArray();
  792.     }

  793. }