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.  *      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.math4.legacy.stat;

  18. import java.util.List;

  19. import org.apache.commons.math4.legacy.exception.DimensionMismatchException;
  20. import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
  21. import org.apache.commons.math4.legacy.exception.NoDataException;
  22. import org.apache.commons.math4.legacy.exception.NotPositiveException;
  23. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  24. import org.apache.commons.math4.legacy.exception.NumberIsTooSmallException;
  25. import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
  26. import org.apache.commons.math4.legacy.stat.descriptive.DescriptiveStatistics;
  27. import org.apache.commons.math4.legacy.stat.descriptive.UnivariateStatistic;
  28. import org.apache.commons.math4.legacy.stat.descriptive.moment.GeometricMean;
  29. import org.apache.commons.math4.legacy.stat.descriptive.moment.Mean;
  30. import org.apache.commons.math4.legacy.stat.descriptive.moment.Variance;
  31. import org.apache.commons.math4.legacy.stat.descriptive.rank.Max;
  32. import org.apache.commons.math4.legacy.stat.descriptive.rank.Min;
  33. import org.apache.commons.math4.legacy.stat.descriptive.rank.Percentile;
  34. import org.apache.commons.math4.legacy.stat.descriptive.summary.Product;
  35. import org.apache.commons.math4.legacy.stat.descriptive.summary.Sum;
  36. import org.apache.commons.math4.legacy.stat.descriptive.summary.SumOfLogs;
  37. import org.apache.commons.math4.legacy.stat.descriptive.summary.SumOfSquares;

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

  43.     /** sum. */
  44.     private static final UnivariateStatistic SUM = new Sum();

  45.     /** sumSq. */
  46.     private static final UnivariateStatistic SUM_OF_SQUARES = new SumOfSquares();

  47.     /** prod. */
  48.     private static final UnivariateStatistic PRODUCT = new Product();

  49.     /** sumLog. */
  50.     private static final UnivariateStatistic SUM_OF_LOGS = new SumOfLogs();

  51.     /** min. */
  52.     private static final UnivariateStatistic MIN = new Min();

  53.     /** max. */
  54.     private static final UnivariateStatistic MAX = new Max();

  55.     /** mean. */
  56.     private static final UnivariateStatistic MEAN = new Mean();

  57.     /** variance. */
  58.     private static final Variance VARIANCE = new Variance();

  59.     /** percentile. */
  60.     private static final Percentile PERCENTILE = new Percentile();

  61.     /** geometric mean. */
  62.     private static final GeometricMean GEOMETRIC_MEAN = new GeometricMean();

  63.     /**
  64.      * Private Constructor.
  65.      */
  66.     private StatUtils() {
  67.     }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  622.     /**
  623.      * Returns the sum of the (signed) differences between corresponding elements of the
  624.      * input arrays -- i.e., sum(sample1[i] - sample2[i]).
  625.      *
  626.      * @param sample1  the first array
  627.      * @param sample2  the second array
  628.      * @return sum of paired differences
  629.      * @throws DimensionMismatchException if the arrays do not have the same (positive) length.
  630.      * @throws NoDataException if the sample arrays are empty.
  631.      */
  632.     public static double sumDifference(final double[] sample1, final double[] sample2)
  633.         throws DimensionMismatchException, NoDataException {

  634.         int n = sample1.length;
  635.         if (n != sample2.length) {
  636.             throw new DimensionMismatchException(n, sample2.length);
  637.         }
  638.         if (n <= 0) {
  639.             throw new NoDataException(LocalizedFormats.INSUFFICIENT_DIMENSION);
  640.         }
  641.         double result = 0;
  642.         for (int i = 0; i < n; i++) {
  643.             result += sample1[i] - sample2[i];
  644.         }
  645.         return result;
  646.     }

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

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

  675.         double sum1 = 0d;
  676.         double sum2 = 0d;
  677.         double diff = 0d;
  678.         int n = sample1.length;
  679.         if (n != sample2.length) {
  680.             throw new DimensionMismatchException(n, sample2.length);
  681.         }
  682.         if (n < 2) {
  683.             throw new NumberIsTooSmallException(n, 2, true);
  684.         }
  685.         for (int i = 0; i < n; i++) {
  686.             diff = sample1[i] - sample2[i];
  687.             sum1 += (diff - meanDifference) *(diff - meanDifference);
  688.             sum2 += diff - meanDifference;
  689.         }
  690.         return (sum1 - (sum2 * sum2 / n)) / (n - 1);
  691.     }

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

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

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

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

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

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

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

  770.         if (begin < 0) {
  771.             throw new NotPositiveException(LocalizedFormats.START_POSITION, Integer.valueOf(begin));
  772.         }

  773.         if (length < 0) {
  774.             throw new NotPositiveException(LocalizedFormats.LENGTH, Integer.valueOf(length));
  775.         }

  776.         return getMode(sample, begin, length);
  777.     }

  778.     /**
  779.      * Private helper method.
  780.      * Assumes parameters have been validated.
  781.      * @param values input data
  782.      * @param begin index (0-based) of the first array element to include
  783.      * @param length the number of elements to include
  784.      * @return array of array of the most frequently occurring element(s) sorted in ascending order.
  785.      */
  786.     private static double[] getMode(double[] values, final int begin, final int length) {
  787.         // Add the values to the frequency table
  788.         Frequency<Double> freq = new Frequency<>();
  789.         for (int i = begin; i < begin + length; i++) {
  790.             final double value = values[i];
  791.             if (!Double.isNaN(value)) {
  792.                 freq.addValue(Double.valueOf(value));
  793.             }
  794.         }
  795.         List<Double> list = freq.getMode();
  796.         // Convert the list to an array of primitive double
  797.         return list.stream().mapToDouble(Double::doubleValue).toArray();
  798.     }
  799. }