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; 18 19 import java.lang.reflect.InvocationTargetException; 20 import java.util.Arrays; 21 22 import org.apache.commons.math4.legacy.exception.MathIllegalArgumentException; 23 import org.apache.commons.math4.legacy.exception.MathIllegalStateException; 24 import org.apache.commons.math4.legacy.exception.NullArgumentException; 25 import org.apache.commons.math4.legacy.exception.util.LocalizedFormats; 26 import org.apache.commons.math4.legacy.stat.descriptive.moment.GeometricMean; 27 import org.apache.commons.math4.legacy.stat.descriptive.moment.Kurtosis; 28 import org.apache.commons.math4.legacy.stat.descriptive.moment.Mean; 29 import org.apache.commons.math4.legacy.stat.descriptive.moment.Skewness; 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.Sum; 35 import org.apache.commons.math4.legacy.stat.descriptive.summary.SumOfSquares; 36 import org.apache.commons.math4.core.jdkmath.JdkMath; 37 38 39 /** 40 * Maintains a dataset of values of a single variable and computes descriptive 41 * statistics based on stored data. 42 * <p> 43 * The {@link #getWindowSize() windowSize} 44 * property sets a limit on the number of values that can be stored in the 45 * dataset. The default value, INFINITE_WINDOW, puts no limit on the size of 46 * the dataset. This value should be used with caution, as the backing store 47 * will grow without bound in this case. For very large datasets, 48 * {@link SummaryStatistics}, which does not store the dataset, should be used 49 * instead of this class. If <code>windowSize</code> is not INFINITE_WINDOW and 50 * more values are added than can be stored in the dataset, new values are 51 * added in a "rolling" manner, with new values replacing the "oldest" values 52 * in the dataset. 53 * <p> 54 * Note: this class is not threadsafe. Use 55 * {@link SynchronizedDescriptiveStatistics} if concurrent access from multiple 56 * threads is required. 57 */ 58 public class DescriptiveStatistics implements StatisticalSummary { 59 60 /** 61 * Represents an infinite window size. When the {@link #getWindowSize()} 62 * returns this value, there is no limit to the number of data values 63 * that can be stored in the dataset. 64 */ 65 public static final int INFINITE_WINDOW = -1; 66 67 /** Name of the setQuantile method. */ 68 private static final String SET_QUANTILE_METHOD_NAME = "setQuantile"; 69 70 /** hold the window size. */ 71 private int windowSize = INFINITE_WINDOW; 72 73 /** Stored data values. */ 74 private ResizableDoubleArray eDA = new ResizableDoubleArray(); 75 76 /** Mean statistic implementation - can be reset by setter. */ 77 private UnivariateStatistic meanImpl = new Mean(); 78 79 /** Geometric mean statistic implementation - can be reset by setter. */ 80 private UnivariateStatistic geometricMeanImpl = new GeometricMean(); 81 82 /** Kurtosis statistic implementation - can be reset by setter. */ 83 private UnivariateStatistic kurtosisImpl = new Kurtosis(); 84 85 /** Maximum statistic implementation - can be reset by setter. */ 86 private UnivariateStatistic maxImpl = new Max(); 87 88 /** Minimum statistic implementation - can be reset by setter. */ 89 private UnivariateStatistic minImpl = new Min(); 90 91 /** Percentile statistic implementation - can be reset by setter. */ 92 private UnivariateStatistic percentileImpl = new Percentile(); 93 94 /** Skewness statistic implementation - can be reset by setter. */ 95 private UnivariateStatistic skewnessImpl = new Skewness(); 96 97 /** Variance statistic implementation - can be reset by setter. */ 98 private UnivariateStatistic varianceImpl = new Variance(); 99 100 /** Sum of squares statistic implementation - can be reset by setter. */ 101 private UnivariateStatistic sumsqImpl = new SumOfSquares(); 102 103 /** Sum statistic implementation - can be reset by setter. */ 104 private UnivariateStatistic sumImpl = new Sum(); 105 106 /** 107 * Construct a {@code DescriptiveStatistics} instance with an infinite 108 * window. 109 */ 110 public DescriptiveStatistics() { 111 } 112 113 /** 114 * Construct a {@code DescriptiveStatistics} instance with the specified 115 * window. 116 * 117 * @param window the window size. 118 * @throws MathIllegalArgumentException if window size is less than 1 but 119 * not equal to {@link #INFINITE_WINDOW} 120 */ 121 public DescriptiveStatistics(int window) throws MathIllegalArgumentException { 122 setWindowSize(window); 123 } 124 125 /** 126 * Construct a {@code DescriptiveStatistics} instance with an infinite 127 * window and the initial data values in {@code initialDoubleArray}. 128 * If {@code initialDoubleArray} is {@code null}, then this constructor 129 * corresponds to the {@link #DescriptiveStatistics() default constructor}. 130 * 131 * @param initialDoubleArray the initial double[]. 132 */ 133 public DescriptiveStatistics(double[] initialDoubleArray) { 134 if (initialDoubleArray != null) { 135 eDA = new ResizableDoubleArray(initialDoubleArray); 136 } 137 } 138 139 /** 140 * Construct a DescriptiveStatistics instance with an infinite window 141 * and the initial data values in {@code initialDoubleArray}. 142 * If {@code initialDoubleArray} is {@code null}, then this constructor 143 * corresponds to {@link #DescriptiveStatistics() }. 144 * 145 * @param initialDoubleArray the initial Double[]. 146 */ 147 public DescriptiveStatistics(Double[] initialDoubleArray) { 148 if (initialDoubleArray != null) { 149 eDA = new ResizableDoubleArray(initialDoubleArray.length); 150 for(double initialValue : initialDoubleArray) { 151 eDA.addElement(initialValue); 152 } 153 } 154 } 155 156 /** 157 * Copy constructor. Construct a new {@code DescriptiveStatistics} instance 158 * that is a copy of {@code original}. 159 * 160 * @param original DescriptiveStatistics instance to copy 161 * @throws NullArgumentException if original is null 162 */ 163 public DescriptiveStatistics(DescriptiveStatistics original) throws NullArgumentException { 164 copy(original, this); 165 } 166 167 /** 168 * Adds the value to the dataset. If the dataset is at the maximum size 169 * (i.e., the number of stored elements equals the currently configured 170 * windowSize), the first (oldest) element in the dataset is discarded 171 * to make room for the new value. 172 * 173 * @param v the value to be added 174 */ 175 public void addValue(double v) { 176 if (windowSize != INFINITE_WINDOW) { 177 if (getN() == windowSize) { 178 eDA.addElementRolling(v); 179 } else if (getN() < windowSize) { 180 eDA.addElement(v); 181 } 182 } else { 183 eDA.addElement(v); 184 } 185 } 186 187 /** 188 * Removes the most recent value from the dataset. 189 * 190 * @throws MathIllegalStateException if there are no elements stored 191 */ 192 public void removeMostRecentValue() throws MathIllegalStateException { 193 try { 194 eDA.discardMostRecentElements(1); 195 } catch (MathIllegalArgumentException ex) { 196 throw new MathIllegalStateException(LocalizedFormats.NO_DATA); 197 } 198 } 199 200 /** 201 * Replaces the most recently stored value with the given value. 202 * There must be at least one element stored to call this method. 203 * 204 * @param v the value to replace the most recent stored value 205 * @return replaced value 206 * @throws MathIllegalStateException if there are no elements stored 207 */ 208 public double replaceMostRecentValue(double v) throws MathIllegalStateException { 209 return eDA.substituteMostRecentElement(v); 210 } 211 212 /** 213 * Returns the <a href="http://www.xycoon.com/arithmetic_mean.htm"> 214 * arithmetic mean </a> of the available values. 215 * @return The mean or Double.NaN if no values have been added. 216 */ 217 @Override 218 public double getMean() { 219 return apply(meanImpl); 220 } 221 222 /** 223 * Returns the <a href="http://www.xycoon.com/geometric_mean.htm"> 224 * geometric mean </a> of the available values. 225 * <p> 226 * See {@link GeometricMean} for details on the computing algorithm.</p> 227 * 228 * @return The geometricMean, Double.NaN if no values have been added, 229 * or if any negative values have been added. 230 */ 231 public double getGeometricMean() { 232 return apply(geometricMeanImpl); 233 } 234 235 /** 236 * Returns the (sample) variance of the available values. 237 * 238 * <p>This method returns the bias-corrected sample variance (using {@code n - 1} in 239 * the denominator). Use {@link #getPopulationVariance()} for the non-bias-corrected 240 * population variance.</p> 241 * 242 * @return The variance, Double.NaN if no values have been added 243 * or 0.0 for a single value set. 244 */ 245 @Override 246 public double getVariance() { 247 return apply(varianceImpl); 248 } 249 250 /** 251 * Returns the <a href="http://en.wikibooks.org/wiki/Statistics/Summary/Variance"> 252 * population variance</a> of the available values. 253 * 254 * @return The population variance, Double.NaN if no values have been added, 255 * or 0.0 for a single value set. 256 */ 257 public double getPopulationVariance() { 258 return apply(new Variance(false)); 259 } 260 261 /** 262 * Returns the standard deviation of the available values. 263 * @return The standard deviation, Double.NaN if no values have been added 264 * or 0.0 for a single value set. 265 */ 266 @Override 267 public double getStandardDeviation() { 268 double stdDev = Double.NaN; 269 if (getN() > 0) { 270 if (getN() > 1) { 271 stdDev = JdkMath.sqrt(getVariance()); 272 } else { 273 stdDev = 0.0; 274 } 275 } 276 return stdDev; 277 } 278 279 /** 280 * Returns the quadratic mean, a.k.a. 281 * <a href="http://mathworld.wolfram.com/Root-Mean-Square.html"> 282 * root-mean-square</a> of the available values 283 * @return The quadratic mean or {@code Double.NaN} if no values 284 * have been added. 285 */ 286 public double getQuadraticMean() { 287 final long n = getN(); 288 return n > 0 ? JdkMath.sqrt(getSumsq() / n) : Double.NaN; 289 } 290 291 /** 292 * Returns the skewness of the available values. Skewness is a 293 * measure of the asymmetry of a given distribution. 294 * 295 * @return The skewness, Double.NaN if less than 3 values have been added. 296 */ 297 public double getSkewness() { 298 return apply(skewnessImpl); 299 } 300 301 /** 302 * Returns the Kurtosis of the available values. Kurtosis is a 303 * measure of the "peakedness" of a distribution. 304 * 305 * @return The kurtosis, Double.NaN if less than 4 values have been added. 306 */ 307 public double getKurtosis() { 308 return apply(kurtosisImpl); 309 } 310 311 /** 312 * Returns the maximum of the available values. 313 * @return The max or Double.NaN if no values have been added. 314 */ 315 @Override 316 public double getMax() { 317 return apply(maxImpl); 318 } 319 320 /** 321 * Returns the minimum of the available values. 322 * @return The min or Double.NaN if no values have been added. 323 */ 324 @Override 325 public double getMin() { 326 return apply(minImpl); 327 } 328 329 /** 330 * Returns the number of available values. 331 * @return The number of available values 332 */ 333 @Override 334 public long getN() { 335 return eDA.getNumElements(); 336 } 337 338 /** 339 * Returns the sum of the values that have been added to Univariate. 340 * @return The sum or Double.NaN if no values have been added 341 */ 342 @Override 343 public double getSum() { 344 return apply(sumImpl); 345 } 346 347 /** 348 * Returns the sum of the squares of the available values. 349 * @return The sum of the squares or Double.NaN if no 350 * values have been added. 351 */ 352 public double getSumsq() { 353 return apply(sumsqImpl); 354 } 355 356 /** 357 * Resets all statistics and storage. 358 */ 359 public void clear() { 360 eDA.clear(); 361 } 362 363 364 /** 365 * Returns the maximum number of values that can be stored in the 366 * dataset, or INFINITE_WINDOW (-1) if there is no limit. 367 * 368 * @return The current window size or -1 if its Infinite. 369 */ 370 public int getWindowSize() { 371 return windowSize; 372 } 373 374 /** 375 * WindowSize controls the number of values that contribute to the 376 * reported statistics. For example, if windowSize is set to 3 and the 377 * values {1,2,3,4,5} have been added <strong> in that order</strong> then 378 * the <i>available values</i> are {3,4,5} and all reported statistics will 379 * be based on these values. If {@code windowSize} is decreased as a result 380 * of this call and there are more than the new value of elements in the 381 * current dataset, values from the front of the array are discarded to 382 * reduce the dataset to {@code windowSize} elements. 383 * 384 * @param windowSize sets the size of the window. 385 * @throws MathIllegalArgumentException if window size is less than 1 but 386 * not equal to {@link #INFINITE_WINDOW} 387 */ 388 public void setWindowSize(int windowSize) throws MathIllegalArgumentException { 389 if (windowSize < 1 && windowSize != INFINITE_WINDOW) { 390 throw new MathIllegalArgumentException( 391 LocalizedFormats.NOT_POSITIVE_WINDOW_SIZE, windowSize); 392 } 393 394 this.windowSize = windowSize; 395 396 // We need to check to see if we need to discard elements 397 // from the front of the array. If the windowSize is less than 398 // the current number of elements. 399 if (windowSize != INFINITE_WINDOW && windowSize < eDA.getNumElements()) { 400 eDA.discardFrontElements(eDA.getNumElements() - windowSize); 401 } 402 } 403 404 /** 405 * Returns the current set of values in an array of double primitives. 406 * The order of addition is preserved. The returned array is a fresh 407 * copy of the underlying data -- i.e., it is not a reference to the 408 * stored data. 409 * 410 * @return returns the current set of numbers in the order in which they 411 * were added to this set 412 */ 413 public double[] getValues() { 414 return eDA.getElements(); 415 } 416 417 /** 418 * Returns the current set of values in an array of double primitives, 419 * sorted in ascending order. The returned array is a fresh 420 * copy of the underlying data -- i.e., it is not a reference to the 421 * stored data. 422 * @return returns the current set of 423 * numbers sorted in ascending order 424 */ 425 public double[] getSortedValues() { 426 double[] sort = getValues(); 427 Arrays.sort(sort); 428 return sort; 429 } 430 431 /** 432 * Returns the element at the specified index. 433 * @param index The Index of the element 434 * @return return the element at the specified index 435 */ 436 public double getElement(int index) { 437 return eDA.getElement(index); 438 } 439 440 /** 441 * Returns an estimate for the pth percentile of the stored values. 442 * <p> 443 * The implementation provided here follows the first estimation procedure presented 444 * <a href="http://www.itl.nist.gov/div898/handbook/prc/section2/prc252.htm">here.</a> 445 * </p><p> 446 * <strong>Preconditions</strong>:<ul> 447 * <li><code>0 < p ≤ 100</code> (otherwise an 448 * <code>MathIllegalArgumentException</code> is thrown)</li> 449 * <li>at least one value must be stored (returns <code>Double.NaN 450 * </code> otherwise)</li> 451 * </ul> 452 * 453 * @param p the requested percentile (scaled from 0 - 100) 454 * @return An estimate for the pth percentile of the stored data 455 * @throws MathIllegalStateException if percentile implementation has been 456 * overridden and the supplied implementation does not support setQuantile 457 * @throws MathIllegalArgumentException if p is not a valid quantile 458 */ 459 public double getPercentile(double p) throws MathIllegalStateException, MathIllegalArgumentException { 460 if (percentileImpl instanceof Percentile) { 461 ((Percentile) percentileImpl).setQuantile(p); 462 } else { 463 try { 464 percentileImpl.getClass().getMethod(SET_QUANTILE_METHOD_NAME, 465 new Class[] {Double.TYPE}).invoke(percentileImpl, 466 new Object[] {Double.valueOf(p)}); 467 } catch (NoSuchMethodException e1) { // Setter guard should prevent 468 throw new MathIllegalStateException( 469 LocalizedFormats.PERCENTILE_IMPLEMENTATION_UNSUPPORTED_METHOD, 470 percentileImpl.getClass().getName(), SET_QUANTILE_METHOD_NAME); 471 } catch (IllegalAccessException e2) { 472 throw new MathIllegalStateException( 473 LocalizedFormats.PERCENTILE_IMPLEMENTATION_CANNOT_ACCESS_METHOD, 474 SET_QUANTILE_METHOD_NAME, percentileImpl.getClass().getName()); 475 } catch (InvocationTargetException e3) { 476 throw new IllegalStateException(e3.getCause()); 477 } 478 } 479 return apply(percentileImpl); 480 } 481 482 /** 483 * Generates a text report displaying univariate statistics from values 484 * that have been added. Each statistic is displayed on a separate 485 * line. 486 * 487 * @return String with line feeds displaying statistics 488 */ 489 @Override 490 public String toString() { 491 StringBuilder outBuffer = new StringBuilder(); 492 String endl = "\n"; 493 outBuffer.append("DescriptiveStatistics:").append(endl); 494 outBuffer.append("n: ").append(getN()).append(endl); 495 outBuffer.append("min: ").append(getMin()).append(endl); 496 outBuffer.append("max: ").append(getMax()).append(endl); 497 outBuffer.append("mean: ").append(getMean()).append(endl); 498 outBuffer.append("std dev: ").append(getStandardDeviation()) 499 .append(endl); 500 try { 501 // No catch for MIAE because actual parameter is valid below 502 outBuffer.append("median: ").append(getPercentile(50)).append(endl); 503 } catch (MathIllegalStateException ex) { 504 outBuffer.append("median: unavailable").append(endl); 505 } 506 outBuffer.append("skewness: ").append(getSkewness()).append(endl); 507 outBuffer.append("kurtosis: ").append(getKurtosis()).append(endl); 508 return outBuffer.toString(); 509 } 510 511 /** 512 * Apply the given statistic to the data associated with this set of statistics. 513 * @param stat the statistic to apply 514 * @return the computed value of the statistic. 515 */ 516 public double apply(UnivariateStatistic stat) { 517 // No try-catch or advertised exception here because arguments are guaranteed valid 518 return eDA.compute(stat); 519 } 520 521 // Implementation getters and setter 522 523 /** 524 * Returns the currently configured mean implementation. 525 * 526 * @return the UnivariateStatistic implementing the mean 527 * @since 1.2 528 */ 529 public synchronized UnivariateStatistic getMeanImpl() { 530 return meanImpl; 531 } 532 533 /** 534 * <p>Sets the implementation for the mean.</p> 535 * 536 * @param meanImpl the UnivariateStatistic instance to use 537 * for computing the mean 538 * @since 1.2 539 */ 540 public synchronized void setMeanImpl(UnivariateStatistic meanImpl) { 541 this.meanImpl = meanImpl; 542 } 543 544 /** 545 * Returns the currently configured geometric mean implementation. 546 * 547 * @return the UnivariateStatistic implementing the geometric mean 548 * @since 1.2 549 */ 550 public synchronized UnivariateStatistic getGeometricMeanImpl() { 551 return geometricMeanImpl; 552 } 553 554 /** 555 * Sets the implementation for the geometric mean. 556 * 557 * @param geometricMeanImpl the UnivariateStatistic instance to use 558 * for computing the geometric mean 559 * @since 1.2 560 */ 561 public synchronized void setGeometricMeanImpl( 562 UnivariateStatistic geometricMeanImpl) { 563 this.geometricMeanImpl = geometricMeanImpl; 564 } 565 566 /** 567 * Returns the currently configured kurtosis implementation. 568 * 569 * @return the UnivariateStatistic implementing the kurtosis 570 * @since 1.2 571 */ 572 public synchronized UnivariateStatistic getKurtosisImpl() { 573 return kurtosisImpl; 574 } 575 576 /** 577 * Sets the implementation for the kurtosis. 578 * 579 * @param kurtosisImpl the UnivariateStatistic instance to use 580 * for computing the kurtosis 581 * @since 1.2 582 */ 583 public synchronized void setKurtosisImpl(UnivariateStatistic kurtosisImpl) { 584 this.kurtosisImpl = kurtosisImpl; 585 } 586 587 /** 588 * Returns the currently configured maximum implementation. 589 * 590 * @return the UnivariateStatistic implementing the maximum 591 * @since 1.2 592 */ 593 public synchronized UnivariateStatistic getMaxImpl() { 594 return maxImpl; 595 } 596 597 /** 598 * Sets the implementation for the maximum. 599 * 600 * @param maxImpl the UnivariateStatistic instance to use 601 * for computing the maximum 602 * @since 1.2 603 */ 604 public synchronized void setMaxImpl(UnivariateStatistic maxImpl) { 605 this.maxImpl = maxImpl; 606 } 607 608 /** 609 * Returns the currently configured minimum implementation. 610 * 611 * @return the UnivariateStatistic implementing the minimum 612 * @since 1.2 613 */ 614 public synchronized UnivariateStatistic getMinImpl() { 615 return minImpl; 616 } 617 618 /** 619 * Sets the implementation for the minimum. 620 * 621 * @param minImpl the UnivariateStatistic instance to use 622 * for computing the minimum 623 * @since 1.2 624 */ 625 public synchronized void setMinImpl(UnivariateStatistic minImpl) { 626 this.minImpl = minImpl; 627 } 628 629 /** 630 * Returns the currently configured percentile implementation. 631 * 632 * @return the UnivariateStatistic implementing the percentile 633 * @since 1.2 634 */ 635 public synchronized UnivariateStatistic getPercentileImpl() { 636 return percentileImpl; 637 } 638 639 /** 640 * Sets the implementation to be used by {@link #getPercentile(double)}. 641 * The supplied <code>UnivariateStatistic</code> must provide a 642 * <code>setQuantile(double)</code> method; otherwise 643 * <code>IllegalArgumentException</code> is thrown. 644 * 645 * @param percentileImpl the percentileImpl to set 646 * @throws MathIllegalArgumentException if the supplied implementation does not 647 * provide a <code>setQuantile</code> method 648 * @since 1.2 649 */ 650 public synchronized void setPercentileImpl(UnivariateStatistic percentileImpl) 651 throws MathIllegalArgumentException { 652 try { 653 percentileImpl.getClass().getMethod(SET_QUANTILE_METHOD_NAME, 654 new Class[] {Double.TYPE}).invoke(percentileImpl, 655 new Object[] {Double.valueOf(50.0d)}); 656 } catch (NoSuchMethodException e1) { 657 throw new MathIllegalArgumentException( 658 LocalizedFormats.PERCENTILE_IMPLEMENTATION_UNSUPPORTED_METHOD, 659 percentileImpl.getClass().getName(), SET_QUANTILE_METHOD_NAME); 660 } catch (IllegalAccessException e2) { 661 throw new MathIllegalArgumentException( 662 LocalizedFormats.PERCENTILE_IMPLEMENTATION_CANNOT_ACCESS_METHOD, 663 SET_QUANTILE_METHOD_NAME, percentileImpl.getClass().getName()); 664 } catch (InvocationTargetException e3) { 665 throw new IllegalArgumentException(e3.getCause()); 666 } 667 this.percentileImpl = percentileImpl; 668 } 669 670 /** 671 * Returns the currently configured skewness implementation. 672 * 673 * @return the UnivariateStatistic implementing the skewness 674 * @since 1.2 675 */ 676 public synchronized UnivariateStatistic getSkewnessImpl() { 677 return skewnessImpl; 678 } 679 680 /** 681 * Sets the implementation for the skewness. 682 * 683 * @param skewnessImpl the UnivariateStatistic instance to use 684 * for computing the skewness 685 * @since 1.2 686 */ 687 public synchronized void setSkewnessImpl( 688 UnivariateStatistic skewnessImpl) { 689 this.skewnessImpl = skewnessImpl; 690 } 691 692 /** 693 * Returns the currently configured variance implementation. 694 * 695 * @return the UnivariateStatistic implementing the variance 696 * @since 1.2 697 */ 698 public synchronized UnivariateStatistic getVarianceImpl() { 699 return varianceImpl; 700 } 701 702 /** 703 * Sets the implementation for the variance. 704 * 705 * @param varianceImpl the UnivariateStatistic instance to use 706 * for computing the variance 707 * @since 1.2 708 */ 709 public synchronized void setVarianceImpl( 710 UnivariateStatistic varianceImpl) { 711 this.varianceImpl = varianceImpl; 712 } 713 714 /** 715 * Returns the currently configured sum of squares implementation. 716 * 717 * @return the UnivariateStatistic implementing the sum of squares 718 * @since 1.2 719 */ 720 public synchronized UnivariateStatistic getSumsqImpl() { 721 return sumsqImpl; 722 } 723 724 /** 725 * Sets the implementation for the sum of squares. 726 * 727 * @param sumsqImpl the UnivariateStatistic instance to use 728 * for computing the sum of squares 729 * @since 1.2 730 */ 731 public synchronized void setSumsqImpl(UnivariateStatistic sumsqImpl) { 732 this.sumsqImpl = sumsqImpl; 733 } 734 735 /** 736 * Returns the currently configured sum implementation. 737 * 738 * @return the UnivariateStatistic implementing the sum 739 * @since 1.2 740 */ 741 public synchronized UnivariateStatistic getSumImpl() { 742 return sumImpl; 743 } 744 745 /** 746 * Sets the implementation for the sum. 747 * 748 * @param sumImpl the UnivariateStatistic instance to use 749 * for computing the sum 750 * @since 1.2 751 */ 752 public synchronized void setSumImpl(UnivariateStatistic sumImpl) { 753 this.sumImpl = sumImpl; 754 } 755 756 /** 757 * Returns a copy of this DescriptiveStatistics instance with the same internal state. 758 * 759 * @return a copy of this 760 */ 761 public DescriptiveStatistics copy() { 762 DescriptiveStatistics result = new DescriptiveStatistics(); 763 // No try-catch or advertised exception because parms are guaranteed valid 764 copy(this, result); 765 return result; 766 } 767 768 /** 769 * Copies source to dest. 770 * <p>Neither source nor dest can be null.</p> 771 * 772 * @param source DescriptiveStatistics to copy 773 * @param dest DescriptiveStatistics to copy to 774 * @throws NullArgumentException if either source or dest is null 775 */ 776 public static void copy(DescriptiveStatistics source, DescriptiveStatistics dest) 777 throws NullArgumentException { 778 NullArgumentException.check(source); 779 NullArgumentException.check(dest); 780 // Copy data and window size 781 dest.eDA = source.eDA.copy(); 782 dest.windowSize = source.windowSize; 783 784 // Copy implementations 785 dest.maxImpl = source.maxImpl.copy(); 786 dest.meanImpl = source.meanImpl.copy(); 787 dest.minImpl = source.minImpl.copy(); 788 dest.sumImpl = source.sumImpl.copy(); 789 dest.varianceImpl = source.varianceImpl.copy(); 790 dest.sumsqImpl = source.sumsqImpl.copy(); 791 dest.geometricMeanImpl = source.geometricMeanImpl.copy(); 792 dest.kurtosisImpl = source.kurtosisImpl; 793 dest.skewnessImpl = source.skewnessImpl; 794 dest.percentileImpl = source.percentileImpl; 795 } 796 }