Variance.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.descriptive.moment;

  18. import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException;
  19. import org.apache.commons.math4.legacy.exception.NullArgumentException;
  20. import org.apache.commons.math4.legacy.exception.util.LocalizedFormats;
  21. import org.apache.commons.math4.legacy.stat.descriptive.AbstractStorelessUnivariateStatistic;
  22. import org.apache.commons.math4.legacy.stat.descriptive.WeightedEvaluation;
  23. import org.apache.commons.math4.legacy.core.MathArrays;

  24. /**
  25.  * Computes the variance of the available values.  By default, the unbiased
  26.  * "sample variance" definitional formula is used:
  27.  * <p>
  28.  * variance = sum((x_i - mean)^2) / (n - 1) </p>
  29.  * <p>
  30.  * where mean is the {@link Mean} and <code>n</code> is the number
  31.  * of sample observations.</p>
  32.  * <p>
  33.  * The definitional formula does not have good numerical properties, so
  34.  * this implementation does not compute the statistic using the definitional
  35.  * formula. <ul>
  36.  * <li> The <code>getResult</code> method computes the variance using
  37.  * updating formulas based on West's algorithm, as described in
  38.  * <a href="http://doi.acm.org/10.1145/359146.359152"> Chan, T. F. and
  39.  * J. G. Lewis 1979, <i>Communications of the ACM</i>,
  40.  * vol. 22 no. 9, pp. 526-531.</a></li>
  41.  * <li> The <code>evaluate</code> methods leverage the fact that they have the
  42.  * full array of values in memory to execute a two-pass algorithm.
  43.  * Specifically, these methods use the "corrected two-pass algorithm" from
  44.  * Chan, Golub, Levesque, <i>Algorithms for Computing the Sample Variance</i>,
  45.  * American Statistician, vol. 37, no. 3 (1983) pp. 242-247.</li></ul>
  46.  * Note that adding values using <code>increment</code> or
  47.  * <code>incrementAll</code> and then executing <code>getResult</code> will
  48.  * sometimes give a different, less accurate, result than executing
  49.  * <code>evaluate</code> with the full array of values. The former approach
  50.  * should only be used when the full array of values is not available.
  51.  * <p>
  52.  * The "population variance"  ( sum((x_i - mean)^2) / n ) can also
  53.  * be computed using this statistic.  The <code>isBiasCorrected</code>
  54.  * property determines whether the "population" or "sample" value is
  55.  * returned by the <code>evaluate</code> and <code>getResult</code> methods.
  56.  * To compute population variances, set this property to <code>false.</code>
  57.  * </p>
  58.  * <p>
  59.  * <strong>Note that this implementation is not synchronized.</strong> If
  60.  * multiple threads access an instance of this class concurrently, and at least
  61.  * one of the threads invokes the <code>increment()</code> or
  62.  * <code>clear()</code> method, it must be synchronized externally.</p>
  63.  */
  64. public class Variance extends AbstractStorelessUnivariateStatistic implements WeightedEvaluation {
  65.     /** SecondMoment is used in incremental calculation of Variance. */
  66.     protected SecondMoment moment;

  67.     /**
  68.      * Whether or not {@link #increment(double)} should increment
  69.      * the internal second moment. When a Variance is constructed with an
  70.      * external SecondMoment as a constructor parameter, this property is
  71.      * set to false and increments must be applied to the second moment
  72.      * directly.
  73.      */
  74.     protected boolean incMoment = true;

  75.     /**
  76.      * Whether or not bias correction is applied when computing the
  77.      * value of the statistic. True means that bias is corrected.  See
  78.      * {@link Variance} for details on the formula.
  79.      */
  80.     private boolean isBiasCorrected = true;

  81.     /**
  82.      * Constructs a Variance with default (true) <code>isBiasCorrected</code>
  83.      * property.
  84.      */
  85.     public Variance() {
  86.         moment = new SecondMoment();
  87.     }

  88.     /**
  89.      * Constructs a Variance based on an external second moment.
  90.      * <p>
  91.      * When this constructor is used, the statistic may only be
  92.      * incremented via the moment, i.e., {@link #increment(double)}
  93.      * does nothing; whereas {@code m2.increment(value)} increments
  94.      * both {@code m2} and the Variance instance constructed from it.
  95.      *
  96.      * @param m2 the SecondMoment (Third or Fourth moments work here as well.)
  97.      */
  98.     public Variance(final SecondMoment m2) {
  99.         incMoment = false;
  100.         this.moment = m2;
  101.     }

  102.     /**
  103.      * Constructs a Variance with the specified <code>isBiasCorrected</code>
  104.      * property.
  105.      *
  106.      * @param isBiasCorrected  setting for bias correction - true means
  107.      * bias will be corrected and is equivalent to using the "no arg"
  108.      * constructor
  109.      */
  110.     public Variance(boolean isBiasCorrected) {
  111.         moment = new SecondMoment();
  112.         this.isBiasCorrected = isBiasCorrected;
  113.     }

  114.     /**
  115.      * Constructs a Variance with the specified <code>isBiasCorrected</code>
  116.      * property and the supplied external second moment.
  117.      *
  118.      * @param isBiasCorrected  setting for bias correction - true means
  119.      * bias will be corrected
  120.      * @param m2 the SecondMoment (Third or Fourth moments work
  121.      * here as well.)
  122.      */
  123.     public Variance(boolean isBiasCorrected, SecondMoment m2) {
  124.         incMoment = false;
  125.         this.moment = m2;
  126.         this.isBiasCorrected = isBiasCorrected;
  127.     }

  128.     /**
  129.      * Copy constructor, creates a new {@code Variance} identical
  130.      * to the {@code original}.
  131.      *
  132.      * @param original the {@code Variance} instance to copy
  133.      * @throws NullArgumentException if original is null
  134.      */
  135.     public Variance(Variance original) throws NullArgumentException {
  136.         copy(original, this);
  137.     }

  138.     /**
  139.      * {@inheritDoc}
  140.      * <p>If all values are available, it is more accurate to use
  141.      * {@link #evaluate(double[])} rather than adding values one at a time
  142.      * using this method and then executing {@link #getResult}, since
  143.      * <code>evaluate</code> leverages the fact that is has the full
  144.      * list of values together to execute a two-pass algorithm.
  145.      * See {@link Variance}.</p>
  146.      *
  147.      * <p>Note also that when {@link #Variance(SecondMoment)} is used to
  148.      * create a Variance, this method does nothing. In that case, the
  149.      * SecondMoment should be incremented directly.</p>
  150.      */
  151.     @Override
  152.     public void increment(final double d) {
  153.         if (incMoment) {
  154.             moment.increment(d);
  155.         }
  156.     }

  157.     /**
  158.      * {@inheritDoc}
  159.      */
  160.     @Override
  161.     public double getResult() {
  162.         if (moment.n == 0) {
  163.             return Double.NaN;
  164.         } else if (moment.n == 1) {
  165.             return 0d;
  166.         } else {
  167.             if (isBiasCorrected) {
  168.                 return moment.m2 / (moment.n - 1d);
  169.             } else {
  170.                 return moment.m2 / (moment.n);
  171.             }
  172.         }
  173.     }

  174.     /**
  175.      * {@inheritDoc}
  176.      */
  177.     @Override
  178.     public long getN() {
  179.         return moment.getN();
  180.     }

  181.     /**
  182.      * {@inheritDoc}
  183.      */
  184.     @Override
  185.     public void clear() {
  186.         if (incMoment) {
  187.             moment.clear();
  188.         }
  189.     }

  190.     /**
  191.      * Returns the variance of the entries in the input array, or
  192.      * <code>Double.NaN</code> if the array is empty.
  193.      * <p>
  194.      * See {@link Variance} for details on the computing algorithm.</p>
  195.      * <p>
  196.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  197.      * <p>
  198.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  199.      * <p>
  200.      * Does not change the internal state of the statistic.</p>
  201.      *
  202.      * @param values the input array
  203.      * @return the variance of the values or Double.NaN if length = 0
  204.      * @throws MathIllegalArgumentException if the array is null
  205.      */
  206.     @Override
  207.     public double evaluate(final double[] values) throws MathIllegalArgumentException {
  208.         if (values == null) {
  209.             throw new NullArgumentException(LocalizedFormats.INPUT_ARRAY);
  210.         }
  211.         return evaluate(values, 0, values.length);
  212.     }

  213.     /**
  214.      * Returns the variance of the entries in the specified portion of
  215.      * the input array, or <code>Double.NaN</code> if the designated subarray
  216.      * is empty.  Note that Double.NaN may also be returned if the input
  217.      * includes NaN and / or infinite values.
  218.      * <p>
  219.      * See {@link Variance} for details on the computing algorithm.</p>
  220.      * <p>
  221.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  222.      * <p>
  223.      * Does not change the internal state of the statistic.</p>
  224.      * <p>
  225.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  226.      *
  227.      * @param values the input array
  228.      * @param begin index of the first array element to include
  229.      * @param length the number of elements to include
  230.      * @return the variance of the values or Double.NaN if length = 0
  231.      * @throws MathIllegalArgumentException if the array is null or the array index
  232.      *  parameters are not valid
  233.      */
  234.     @Override
  235.     public double evaluate(final double[] values, final int begin, final int length)
  236.         throws MathIllegalArgumentException {

  237.         double var = Double.NaN;

  238.         if (MathArrays.verifyValues(values, begin, length)) {
  239.             if (length == 1) {
  240.                 var = 0.0;
  241.             } else if (length > 1) {
  242.                 Mean mean = new Mean();
  243.                 double m = mean.evaluate(values, begin, length);
  244.                 var = evaluate(values, m, begin, length);
  245.             }
  246.         }
  247.         return var;
  248.     }

  249.     /**
  250.      * <p>Returns the weighted variance of the entries in the specified portion of
  251.      * the input array, or <code>Double.NaN</code> if the designated subarray
  252.      * is empty.</p>
  253.      * <p>
  254.      * Uses the formula <div style="white-space: pre"><code>
  255.      *   &Sigma;(weights[i]*(values[i] - weightedMean)<sup>2</sup>)/(&Sigma;(weights[i]) - 1)
  256.      * </code></div>
  257.      * where weightedMean is the weighted mean
  258.      * <p>
  259.      * This formula will not return the same result as the unweighted variance when all
  260.      * weights are equal, unless all weights are equal to 1. The formula assumes that
  261.      * weights are to be treated as "expansion values," as will be the case if for example
  262.      * the weights represent frequency counts. To normalize weights so that the denominator
  263.      * in the variance computation equals the length of the input vector minus one, use <pre>
  264.      *   <code>evaluate(values, MathArrays.normalizeArray(weights, values.length)); </code>
  265.      * </pre>
  266.      * <p>
  267.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  268.      * <p>
  269.      * Throws <code>IllegalArgumentException</code> if any of the following are true:
  270.      * <ul><li>the values array is null</li>
  271.      *     <li>the weights array is null</li>
  272.      *     <li>the weights array does not have the same length as the values array</li>
  273.      *     <li>the weights array contains one or more infinite values</li>
  274.      *     <li>the weights array contains one or more NaN values</li>
  275.      *     <li>the weights array contains negative values</li>
  276.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  277.      *     <li>the start and length arguments do not determine a valid array</li>
  278.      * </ul>
  279.      * <p>
  280.      * Does not change the internal state of the statistic.</p>
  281.      * <p>
  282.      * Throws <code>MathIllegalArgumentException</code> if either array is null.</p>
  283.      *
  284.      * @param values the input array
  285.      * @param weights the weights array
  286.      * @param begin index of the first array element to include
  287.      * @param length the number of elements to include
  288.      * @return the weighted variance of the values or Double.NaN if length = 0
  289.      * @throws MathIllegalArgumentException if the parameters are not valid
  290.      * @since 2.1
  291.      */
  292.     @Override
  293.     public double evaluate(final double[] values, final double[] weights,
  294.                            final int begin, final int length) throws MathIllegalArgumentException {

  295.         double var = Double.NaN;

  296.         if (MathArrays.verifyValues(values, weights, begin, length)) {
  297.             if (length == 1) {
  298.                 var = 0.0;
  299.             } else if (length > 1) {
  300.                 Mean mean = new Mean();
  301.                 double m = mean.evaluate(values, weights, begin, length);
  302.                 var = evaluate(values, weights, m, begin, length);
  303.             }
  304.         }
  305.         return var;
  306.     }

  307.     /**
  308.      * <p>
  309.      * Returns the weighted variance of the entries in the input array.</p>
  310.      * <p>
  311.      * Uses the formula <div style="white-space:pre"><code>
  312.      *   &Sigma;(weights[i]*(values[i] - weightedMean)<sup>2</sup>)/(&Sigma;(weights[i]) - 1)
  313.      * </code></div>
  314.      * where weightedMean is the weighted mean
  315.      * <p>
  316.      * This formula will not return the same result as the unweighted variance when all
  317.      * weights are equal, unless all weights are equal to 1. The formula assumes that
  318.      * weights are to be treated as "expansion values," as will be the case if for example
  319.      * the weights represent frequency counts. To normalize weights so that the denominator
  320.      * in the variance computation equals the length of the input vector minus one, use <pre>
  321.      *   <code>evaluate(values, MathArrays.normalizeArray(weights, values.length)); </code>
  322.      * </pre>
  323.      * <p>
  324.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  325.      * <p>
  326.      * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  327.      * <ul><li>the values array is null</li>
  328.      *     <li>the weights array is null</li>
  329.      *     <li>the weights array does not have the same length as the values array</li>
  330.      *     <li>the weights array contains one or more infinite values</li>
  331.      *     <li>the weights array contains one or more NaN values</li>
  332.      *     <li>the weights array contains negative values</li>
  333.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  334.      * </ul>
  335.      * <p>
  336.      * Does not change the internal state of the statistic.</p>
  337.      * <p>
  338.      * Throws <code>MathIllegalArgumentException</code> if either array is null.</p>
  339.      *
  340.      * @param values the input array
  341.      * @param weights the weights array
  342.      * @return the weighted variance of the values
  343.      * @throws MathIllegalArgumentException if the parameters are not valid
  344.      * @since 2.1
  345.      */
  346.     @Override
  347.     public double evaluate(final double[] values, final double[] weights)
  348.         throws MathIllegalArgumentException {
  349.         return evaluate(values, weights, 0, values.length);
  350.     }

  351.     /**
  352.      * Returns the variance of the entries in the specified portion of
  353.      * the input array, using the precomputed mean value.  Returns
  354.      * <code>Double.NaN</code> if the designated subarray is empty.
  355.      * <p>
  356.      * See {@link Variance} for details on the computing algorithm.</p>
  357.      * <p>
  358.      * The formula used assumes that the supplied mean value is the arithmetic
  359.      * mean of the sample data, not a known population parameter.  This method
  360.      * is supplied only to save computation when the mean has already been
  361.      * computed.</p>
  362.      * <p>
  363.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  364.      * <p>
  365.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  366.      * <p>
  367.      * Does not change the internal state of the statistic.</p>
  368.      *
  369.      * @param values the input array
  370.      * @param mean the precomputed mean value
  371.      * @param begin index of the first array element to include
  372.      * @param length the number of elements to include
  373.      * @return the variance of the values or Double.NaN if length = 0
  374.      * @throws MathIllegalArgumentException if the array is null or the array index
  375.      *  parameters are not valid
  376.      */
  377.     public double evaluate(final double[] values, final double mean,
  378.                            final int begin, final int length) throws MathIllegalArgumentException {

  379.         double var = Double.NaN;

  380.         if (MathArrays.verifyValues(values, begin, length)) {
  381.             if (length == 1) {
  382.                 var = 0.0;
  383.             } else if (length > 1) {
  384.                 double accum = 0.0;
  385.                 double dev = 0.0;
  386.                 double accum2 = 0.0;
  387.                 for (int i = begin; i < begin + length; i++) {
  388.                     dev = values[i] - mean;
  389.                     accum += dev * dev;
  390.                     accum2 += dev;
  391.                 }
  392.                 double len = length;
  393.                 if (isBiasCorrected) {
  394.                     var = (accum - (accum2 * accum2 / len)) / (len - 1.0);
  395.                 } else {
  396.                     var = (accum - (accum2 * accum2 / len)) / len;
  397.                 }
  398.             }
  399.         }
  400.         return var;
  401.     }

  402.     /**
  403.      * Returns the variance of the entries in the input array, using the
  404.      * precomputed mean value.  Returns <code>Double.NaN</code> if the array
  405.      * is empty.
  406.      * <p>
  407.      * See {@link Variance} for details on the computing algorithm.</p>
  408.      * <p>
  409.      * If <code>isBiasCorrected</code> is <code>true</code> the formula used
  410.      * assumes that the supplied mean value is the arithmetic mean of the
  411.      * sample data, not a known population parameter.  If the mean is a known
  412.      * population parameter, or if the "population" version of the variance is
  413.      * desired, set <code>isBiasCorrected</code> to <code>false</code> before
  414.      * invoking this method.</p>
  415.      * <p>
  416.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  417.      * <p>
  418.      * Throws <code>MathIllegalArgumentException</code> if the array is null.</p>
  419.      * <p>
  420.      * Does not change the internal state of the statistic.</p>
  421.      *
  422.      * @param values the input array
  423.      * @param mean the precomputed mean value
  424.      * @return the variance of the values or Double.NaN if the array is empty
  425.      * @throws MathIllegalArgumentException if the array is null
  426.      */
  427.     public double evaluate(final double[] values, final double mean) throws MathIllegalArgumentException {
  428.         return evaluate(values, mean, 0, values.length);
  429.     }

  430.     /**
  431.      * Returns the weighted variance of the entries in the specified portion of
  432.      * the input array, using the precomputed weighted mean value.  Returns
  433.      * <code>Double.NaN</code> if the designated subarray is empty.
  434.      * <p>
  435.      * Uses the formula <div style="white-space:pre"><code>
  436.      *   &Sigma;(weights[i]*(values[i] - mean)<sup>2</sup>)/(&Sigma;(weights[i]) - 1)
  437.      * </code></div>
  438.      * <p>
  439.      * The formula used assumes that the supplied mean value is the weighted arithmetic
  440.      * mean of the sample data, not a known population parameter. This method
  441.      * is supplied only to save computation when the mean has already been
  442.      * computed.</p>
  443.      * <p>
  444.      * This formula will not return the same result as the unweighted variance when all
  445.      * weights are equal, unless all weights are equal to 1. The formula assumes that
  446.      * weights are to be treated as "expansion values," as will be the case if for example
  447.      * the weights represent frequency counts. To normalize weights so that the denominator
  448.      * in the variance computation equals the length of the input vector minus one, use <pre>
  449.      *   <code>evaluate(values, MathArrays.normalizeArray(weights, values.length), mean); </code>
  450.      * </pre>
  451.      * <p>
  452.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  453.      * <p>
  454.      * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  455.      * <ul><li>the values array is null</li>
  456.      *     <li>the weights array is null</li>
  457.      *     <li>the weights array does not have the same length as the values array</li>
  458.      *     <li>the weights array contains one or more infinite values</li>
  459.      *     <li>the weights array contains one or more NaN values</li>
  460.      *     <li>the weights array contains negative values</li>
  461.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  462.      *     <li>the start and length arguments do not determine a valid array</li>
  463.      * </ul>
  464.      * <p>
  465.      * Does not change the internal state of the statistic.</p>
  466.      *
  467.      * @param values the input array
  468.      * @param weights the weights array
  469.      * @param mean the precomputed weighted mean value
  470.      * @param begin index of the first array element to include
  471.      * @param length the number of elements to include
  472.      * @return the variance of the values or Double.NaN if length = 0
  473.      * @throws MathIllegalArgumentException if the parameters are not valid
  474.      * @since 2.1
  475.      */
  476.     public double evaluate(final double[] values, final double[] weights,
  477.                            final double mean, final int begin, final int length)
  478.         throws MathIllegalArgumentException {

  479.         double var = Double.NaN;

  480.         if (MathArrays.verifyValues(values, weights, begin, length)) {
  481.             if (length == 1) {
  482.                 var = 0.0;
  483.             } else if (length > 1) {
  484.                 double accum = 0.0;
  485.                 double dev = 0.0;
  486.                 double accum2 = 0.0;
  487.                 for (int i = begin; i < begin + length; i++) {
  488.                     dev = values[i] - mean;
  489.                     accum += weights[i] * (dev * dev);
  490.                     accum2 += weights[i] * dev;
  491.                 }

  492.                 double sumWts = 0;
  493.                 for (int i = begin; i < begin + length; i++) {
  494.                     sumWts += weights[i];
  495.                 }

  496.                 if (isBiasCorrected) {
  497.                     // Note: For this to be valid the weights should correspond to counts
  498.                     // of each observation where the weights are positive integers; the
  499.                     // sum of the weights is the total number of observations and should
  500.                     // be at least 2.
  501.                     var = (accum - (accum2 * accum2 / sumWts)) / (sumWts - 1.0);
  502.                 } else {
  503.                     var = (accum - (accum2 * accum2 / sumWts)) / sumWts;
  504.                 }
  505.             }
  506.         }
  507.         return var;
  508.     }

  509.     /**
  510.      * <p>Returns the weighted variance of the values in the input array, using
  511.      * the precomputed weighted mean value.</p>
  512.      * <p>
  513.      * Uses the formula <div style="white-space:pre"><code>
  514.      *   &Sigma;(weights[i]*(values[i] - mean)<sup>2</sup>)/(&Sigma;(weights[i]) - 1)
  515.      * </code></div>
  516.      * <p>
  517.      * The formula used assumes that the supplied mean value is the weighted arithmetic
  518.      * mean of the sample data, not a known population parameter. This method
  519.      * is supplied only to save computation when the mean has already been
  520.      * computed.</p>
  521.      * <p>
  522.      * This formula will not return the same result as the unweighted variance when all
  523.      * weights are equal, unless all weights are equal to 1. The formula assumes that
  524.      * weights are to be treated as "expansion values," as will be the case if for example
  525.      * the weights represent frequency counts. To normalize weights so that the denominator
  526.      * in the variance computation equals the length of the input vector minus one, use <pre>
  527.      *   <code>evaluate(values, MathArrays.normalizeArray(weights, values.length), mean); </code>
  528.      * </pre>
  529.      * <p>
  530.      * Returns 0 for a single-value (i.e. length = 1) sample.</p>
  531.      * <p>
  532.      * Throws <code>MathIllegalArgumentException</code> if any of the following are true:
  533.      * <ul><li>the values array is null</li>
  534.      *     <li>the weights array is null</li>
  535.      *     <li>the weights array does not have the same length as the values array</li>
  536.      *     <li>the weights array contains one or more infinite values</li>
  537.      *     <li>the weights array contains one or more NaN values</li>
  538.      *     <li>the weights array contains negative values</li>
  539.      *     <li>the weights array does not contain at least one non-zero value (applies when length is non zero)</li>
  540.      * </ul>
  541.      * <p>
  542.      * Does not change the internal state of the statistic.</p>
  543.      *
  544.      * @param values the input array
  545.      * @param weights the weights array
  546.      * @param mean the precomputed weighted mean value
  547.      * @return the variance of the values or Double.NaN if length = 0
  548.      * @throws MathIllegalArgumentException if the parameters are not valid
  549.      * @since 2.1
  550.      */
  551.     public double evaluate(final double[] values, final double[] weights, final double mean)
  552.         throws MathIllegalArgumentException {
  553.         return evaluate(values, weights, mean, 0, values.length);
  554.     }

  555.     /**
  556.      * @return Returns the isBiasCorrected.
  557.      */
  558.     public boolean isBiasCorrected() {
  559.         return isBiasCorrected;
  560.     }

  561.     /**
  562.      * @param biasCorrected The isBiasCorrected to set.
  563.      */
  564.     public void setBiasCorrected(boolean biasCorrected) {
  565.         this.isBiasCorrected = biasCorrected;
  566.     }

  567.     /**
  568.      * {@inheritDoc}
  569.      */
  570.     @Override
  571.     public Variance copy() {
  572.         Variance result = new Variance();
  573.         // No try-catch or advertised exception because parameters are guaranteed non-null
  574.         copy(this, result);
  575.         return result;
  576.     }

  577.     /**
  578.      * Copies source to dest.
  579.      * <p>Neither source nor dest can be null.</p>
  580.      *
  581.      * @param source Variance to copy
  582.      * @param dest Variance to copy to
  583.      * @throws NullArgumentException if either source or dest is null
  584.      */
  585.     public static void copy(Variance source, Variance dest)
  586.         throws NullArgumentException {
  587.         NullArgumentException.check(source);
  588.         NullArgumentException.check(dest);
  589.         dest.moment = source.moment.copy();
  590.         dest.isBiasCorrected = source.isBiasCorrected;
  591.         dest.incMoment = source.incMoment;
  592.     }
  593. }