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.statistics.descriptive;
18
19 import java.math.BigInteger;
20 import java.util.Objects;
21 import java.util.Set;
22 import java.util.function.DoubleConsumer;
23 import java.util.function.LongConsumer;
24
25 /**
26 * Statistics for {@code long} values.
27 *
28 * <p>This class provides combinations of individual statistic implementations in the
29 * {@code org.apache.commons.statistics.descriptive} package.
30 *
31 * <p>Supports up to 2<sup>63</sup> (exclusive) observations.
32 * This implementation does not check for overflow of the count.
33 *
34 * @since 1.1
35 */
36 public final class LongStatistics implements LongConsumer {
37 /** Error message for non configured statistics. */
38 private static final String NO_CONFIGURED_STATISTICS = "No configured statistics";
39 /** Error message for an unsupported statistic. */
40 private static final String UNSUPPORTED_STATISTIC = "Unsupported statistic: ";
41
42 /** Count of values recorded. */
43 private long count;
44 /** The consumer of values. */
45 private final LongConsumer consumer;
46 /** The {@link LongMin} implementation. */
47 private final LongMin min;
48 /** The {@link LongMax} implementation. */
49 private final LongMax max;
50 /** The moment implementation. May be any instance of {@link FirstMoment}.
51 * This implementation uses only the third and fourth moments. */
52 private final FirstMoment moment;
53 /** The {@link LongSum} implementation. */
54 private final LongSum sum;
55 /** The {@link Product} implementation. */
56 private final Product product;
57 /** The {@link LongSumOfSquares} implementation. */
58 private final LongSumOfSquares sumOfSquares;
59 /** The {@link SumOfLogs} implementation. */
60 private final SumOfLogs sumOfLogs;
61 /** Configuration options for computation of statistics. */
62 private StatisticsConfiguration config;
63
64 /**
65 * A builder for {@link LongStatistics}.
66 */
67 public static final class Builder {
68 /** An empty double array. */
69 private static final long[] NO_VALUES = {};
70
71 /** The {@link LongMin} constructor. */
72 private RangeFunction<long[], LongMin> min;
73 /** The {@link LongMax} constructor. */
74 private RangeFunction<long[], LongMax> max;
75 /** The moment constructor. May return any instance of {@link FirstMoment}. */
76 private RangeFunction<long[], FirstMoment> moment;
77 /** The {@link LongSum} constructor. */
78 private RangeFunction<long[], LongSum> sum;
79 /** The {@link Product} constructor. */
80 private RangeFunction<long[], Product> product;
81 /** The {@link LongSumOfSquares} constructor. */
82 private RangeFunction<long[], LongSumOfSquares> sumOfSquares;
83 /** The {@link SumOfLogs} constructor. */
84 private RangeFunction<long[], SumOfLogs> sumOfLogs;
85 /** The order of the moment. It corresponds to the power computed by the {@link FirstMoment}
86 * instance constructed by {@link #moment}. This should only be increased from the default
87 * of zero (corresponding to no moment computation). */
88 private int momentOrder;
89 /** Configuration options for computation of statistics. */
90 private StatisticsConfiguration config = StatisticsConfiguration.withDefaults();
91
92 /**
93 * Create an instance.
94 */
95 Builder() {
96 // Do nothing
97 }
98
99 /**
100 * Add the statistic to the statistics to compute.
101 *
102 * @param statistic Statistic to compute.
103 * @return {@code this} instance
104 */
105 Builder add(Statistic statistic) {
106 // Exhaustive switch statement
107 switch (statistic) {
108 case GEOMETRIC_MEAN:
109 case SUM_OF_LOGS:
110 sumOfLogs = SumOfLogs::createFromRange;
111 break;
112 case KURTOSIS:
113 createMoment(4);
114 break;
115 case MAX:
116 max = LongMax::createFromRange;
117 break;
118 case MIN:
119 min = LongMin::createFromRange;
120 break;
121 case PRODUCT:
122 product = Product::createFromRange;
123 break;
124 case SKEWNESS:
125 createMoment(3);
126 break;
127 case STANDARD_DEVIATION:
128 case VARIANCE:
129 sum = LongSum::createFromRange;
130 sumOfSquares = LongSumOfSquares::createFromRange;
131 break;
132 case MEAN:
133 case SUM:
134 sum = LongSum::createFromRange;
135 break;
136 case SUM_OF_SQUARES:
137 sumOfSquares = LongSumOfSquares::createFromRange;
138 break;
139 }
140 return this;
141 }
142
143 /**
144 * Creates the moment constructor for the specified {@code order},
145 * e.g. order=3 is sum of cubed deviations.
146 *
147 * @param order Order.
148 */
149 private void createMoment(int order) {
150 if (order > momentOrder) {
151 momentOrder = order;
152 if (order == 4) {
153 moment = SumOfFourthDeviations::ofRange;
154 } else {
155 // Assume order == 3
156 moment = SumOfCubedDeviations::ofRange;
157 }
158 }
159 }
160
161 /**
162 * Sets the statistics configuration options for computation of statistics.
163 *
164 * @param v Value.
165 * @return the builder
166 * @throws NullPointerException if the value is null
167 */
168 public Builder setConfiguration(StatisticsConfiguration v) {
169 config = Objects.requireNonNull(v);
170 return this;
171 }
172
173 /**
174 * Builds a {@code LongStatistics} instance.
175 *
176 * @return {@code LongStatistics} instance.
177 */
178 public LongStatistics build() {
179 return create(NO_VALUES, 0, 0);
180 }
181
182 /**
183 * Builds a {@code LongStatistics} instance using the input {@code values}.
184 *
185 * <p>Note: {@code LongStatistics} computed using
186 * {@link LongStatistics#accept(long) accept} may be
187 * different from this instance.
188 *
189 * @param values Values.
190 * @return {@code LongStatistics} instance.
191 */
192 public LongStatistics build(long... values) {
193 Objects.requireNonNull(values, "values");
194 return create(values, 0, values.length);
195 }
196
197 /**
198 * Builds a {@code LongStatistics} instance using the specified range of {@code values}.
199 *
200 * <p>Note: {@code LongStatistics} computed using
201 * {@link LongStatistics#accept(long) accept} may be
202 * different from this instance.
203 *
204 * @param values Values.
205 * @param from Inclusive start of the range.
206 * @param to Exclusive end of the range.
207 * @return {@code LongStatistics} instance.
208 * @throws IndexOutOfBoundsException if the sub-range is out of bounds
209 * @since 1.2
210 */
211 public LongStatistics build(long[] values, int from, int to) {
212 Statistics.checkFromToIndex(from, to, values.length);
213 return create(values, from, to);
214 }
215
216 /**
217 * Builds a {@code LongStatistics} instance using the input {@code values}.
218 *
219 * <p>Note: {@code LongStatistics} computed using
220 * {@link LongStatistics#accept(long) accept} may be
221 * different from this instance.
222 *
223 * <p>Warning: No range checks are performed.
224 *
225 * @param values Values.
226 * @param from Inclusive start of the range.
227 * @param to Exclusive end of the range.
228 * @return {@code LongStatistics} instance.
229 */
230 private LongStatistics create(long[] values, int from, int to) {
231 return new LongStatistics(
232 to - from,
233 create(min, values, from, to),
234 create(max, values, from, to),
235 create(moment, values, from, to),
236 create(sum, values, from, to),
237 create(product, values, from, to),
238 create(sumOfSquares, values, from, to),
239 create(sumOfLogs, values, from, to),
240 config);
241 }
242
243 /**
244 * Creates the object from the {@code values}.
245 *
246 * @param <S> value type
247 * @param <T> object type
248 * @param constructor Constructor.
249 * @param values Values
250 * @param from Inclusive start of the range.
251 * @param to Exclusive end of the range.
252 * @return the instance
253 */
254 private static <S, T> T create(RangeFunction<S, T> constructor, S values, int from, int to) {
255 if (constructor != null) {
256 return constructor.apply(values, from, to);
257 }
258 return null;
259 }
260 }
261
262 /**
263 * Create an instance.
264 *
265 * @param count Count of values.
266 * @param min LongMin implementation.
267 * @param max LongMax implementation.
268 * @param moment Moment implementation.
269 * @param sum LongSum implementation.
270 * @param product Product implementation.
271 * @param sumOfSquares Sum of squares implementation.
272 * @param sumOfLogs Sum of logs implementation.
273 * @param config Statistics configuration.
274 */
275 LongStatistics(long count, LongMin min, LongMax max, FirstMoment moment, LongSum sum,
276 Product product, LongSumOfSquares sumOfSquares, SumOfLogs sumOfLogs,
277 StatisticsConfiguration config) {
278 this.count = count;
279 this.min = min;
280 this.max = max;
281 this.moment = moment;
282 this.sum = sum;
283 this.product = product;
284 this.sumOfSquares = sumOfSquares;
285 this.sumOfLogs = sumOfLogs;
286 this.config = config;
287 // The final consumer should never be null as the builder is created
288 // with at least one statistic.
289 consumer = Statistics.composeLongConsumers(min, max, sum, sumOfSquares,
290 composeAsLong(moment, product, sumOfLogs));
291 }
292
293 /**
294 * Chain the {@code consumers} into a single composite {@code LongConsumer}.
295 * Ignore any {@code null} consumer.
296 *
297 * @param consumers Consumers.
298 * @return a composed consumer (or null)
299 */
300 private static LongConsumer composeAsLong(DoubleConsumer... consumers) {
301 final DoubleConsumer c = Statistics.composeDoubleConsumers(consumers);
302 if (c != null) {
303 return c::accept;
304 }
305 return null;
306 }
307
308 /**
309 * Returns a new instance configured to compute the specified {@code statistics}.
310 *
311 * <p>The statistics will be empty and so will return the default values for each
312 * computed statistic.
313 *
314 * @param statistics Statistics to compute.
315 * @return the instance
316 * @throws IllegalArgumentException if there are no {@code statistics} to compute.
317 */
318 public static LongStatistics of(Statistic... statistics) {
319 return builder(statistics).build();
320 }
321
322 /**
323 * Returns a new instance configured to compute the specified {@code statistics}
324 * populated using the input {@code values}.
325 *
326 * <p>Use this method to create an instance populated with a (variable) array of
327 * {@code long[]} data:
328 *
329 * <pre>
330 * LongStatistics stats = LongStatistics.of(
331 * EnumSet.of(Statistic.MIN, Statistic.MAX),
332 * 1, 1, 2, 3, 5, 8, 13);
333 * </pre>
334 *
335 * @param statistics Statistics to compute.
336 * @param values Values.
337 * @return the instance
338 * @throws IllegalArgumentException if there are no {@code statistics} to compute.
339 */
340 public static LongStatistics of(Set<Statistic> statistics, long... values) {
341 if (statistics.isEmpty()) {
342 throw new IllegalArgumentException(NO_CONFIGURED_STATISTICS);
343 }
344 final Builder b = new Builder();
345 statistics.forEach(b::add);
346 return b.build(values);
347 }
348
349 /**
350 * Returns a new instance configured to compute the specified {@code statistics}
351 * populated using the specified range of {@code values}.
352 *
353 * <p>Use this method to create an instance populated with part of an array of
354 * {@code long[]} data, e.g. to use the first half of the data:
355 *
356 * <pre>
357 * long[] data = ...
358 * LongStatistics stats = LongStatistics.of(
359 * EnumSet.of(Statistic.MIN, Statistic.MAX),
360 * data, 0, data.length / 2);
361 * </pre>
362 *
363 * @param statistics Statistics to compute.
364 * @param values Values.
365 * @param from Inclusive start of the range.
366 * @param to Exclusive end of the range.
367 * @return the instance
368 * @throws IllegalArgumentException if there are no {@code statistics} to compute.
369 * @throws IndexOutOfBoundsException if the sub-range is out of bounds
370 * @since 1.2
371 */
372 public static LongStatistics ofRange(Set<Statistic> statistics, long[] values, int from, int to) {
373 if (statistics.isEmpty()) {
374 throw new IllegalArgumentException(NO_CONFIGURED_STATISTICS);
375 }
376 final Builder b = new Builder();
377 statistics.forEach(b::add);
378 return b.build(values, from, to);
379 }
380
381 /**
382 * Returns a new builder configured to create instances to compute the specified
383 * {@code statistics}.
384 *
385 * <p>Use this method to create an instance populated with an array of {@code long[]}
386 * data using the {@link Builder#build(long...)} method:
387 *
388 * <pre>
389 * long[] data = ...
390 * LongStatistics stats = LongStatistics.builder(
391 * Statistic.MIN, Statistic.MAX, Statistic.VARIANCE)
392 * .build(data);
393 * </pre>
394 *
395 * <p>The builder can be used to create multiple instances of {@link LongStatistics}
396 * to be used in parallel, or on separate arrays of {@code long[]} data. These may
397 * be {@link #combine(LongStatistics) combined}. For example:
398 *
399 * <pre>
400 * long[][] data = ...
401 * LongStatistics.Builder builder = LongStatistics.builder(
402 * Statistic.MIN, Statistic.MAX, Statistic.VARIANCE);
403 * LongStatistics stats = Arrays.stream(data)
404 * .parallel()
405 * .map(builder::build)
406 * .reduce(LongStatistics::combine)
407 * .get();
408 * </pre>
409 *
410 * <p>The builder can be used to create a {@link java.util.stream.Collector} for repeat
411 * use on multiple data:
412 *
413 * <pre>{@code
414 * LongStatistics.Builder builder = LongStatistics.builder(
415 * Statistic.MIN, Statistic.MAX, Statistic.VARIANCE);
416 * Collector<long[], LongStatistics, LongStatistics> collector =
417 * Collector.of(builder::build,
418 * (s, d) -> s.combine(builder.build(d)),
419 * LongStatistics::combine);
420 *
421 * // Repeated
422 * long[][] data = ...
423 * LongStatistics stats = Arrays.stream(data).collect(collector);
424 * }</pre>
425 *
426 * @param statistics Statistics to compute.
427 * @return the builder
428 * @throws IllegalArgumentException if there are no {@code statistics} to compute.
429 */
430 public static Builder builder(Statistic... statistics) {
431 if (statistics.length == 0) {
432 throw new IllegalArgumentException(NO_CONFIGURED_STATISTICS);
433 }
434 final Builder b = new Builder();
435 for (final Statistic s : statistics) {
436 b.add(s);
437 }
438 return b;
439 }
440
441 /**
442 * Updates the state of the statistics to reflect the addition of {@code value}.
443 *
444 * @param value Value.
445 */
446 @Override
447 public void accept(long value) {
448 count++;
449 consumer.accept(value);
450 }
451
452 /**
453 * Return the count of values recorded.
454 *
455 * @return the count of values
456 */
457 public long getCount() {
458 return count;
459 }
460
461 /**
462 * Check if the specified {@code statistic} is supported.
463 *
464 * <p>Note: This method will not return {@code false} if the argument is {@code null}.
465 *
466 * @param statistic Statistic.
467 * @return {@code true} if supported
468 * @throws NullPointerException if the {@code statistic} is {@code null}
469 * @see #getResult(Statistic)
470 */
471 public boolean isSupported(Statistic statistic) {
472 // Check for the appropriate underlying implementation
473 // Exhaustive switch statement
474 switch (statistic) {
475 case GEOMETRIC_MEAN:
476 case SUM_OF_LOGS:
477 return sumOfLogs != null;
478 case KURTOSIS:
479 return moment instanceof SumOfFourthDeviations;
480 case MAX:
481 return max != null;
482 case MIN:
483 return min != null;
484 case PRODUCT:
485 return product != null;
486 case SKEWNESS:
487 return moment instanceof SumOfCubedDeviations;
488 case STANDARD_DEVIATION:
489 case VARIANCE:
490 return sum != null && sumOfSquares != null;
491 case MEAN:
492 case SUM:
493 return sum != null;
494 case SUM_OF_SQUARES:
495 return sumOfSquares != null;
496 }
497 // Unreachable code
498 throw new IllegalArgumentException(UNSUPPORTED_STATISTIC + statistic);
499 }
500
501 /**
502 * Gets the value of the specified {@code statistic} as a {@code double}.
503 *
504 * @param statistic Statistic.
505 * @return the value
506 * @throws IllegalArgumentException if the {@code statistic} is not supported
507 * @see #isSupported(Statistic)
508 * @see #getResult(Statistic)
509 */
510 public double getAsDouble(Statistic statistic) {
511 return getResult(statistic).getAsDouble();
512 }
513
514 /**
515 * Gets the value of the specified {@code statistic} as a {@code long}.
516 *
517 * <p>Use this method to access the {@code long} result for exact integer statistics,
518 * for example {@link Statistic#MIN}.
519 *
520 * <p>Note: This method may throw an {@link ArithmeticException} if the result
521 * overflows an {@code long}.
522 *
523 * @param statistic Statistic.
524 * @return the value
525 * @throws IllegalArgumentException if the {@code statistic} is not supported
526 * @throws ArithmeticException if the {@code result} overflows an {@code long} or is not
527 * finite
528 * @see #isSupported(Statistic)
529 * @see #getResult(Statistic)
530 */
531 public long getAsLong(Statistic statistic) {
532 return getResult(statistic).getAsLong();
533 }
534
535 /**
536 * Gets the value of the specified {@code statistic} as a {@code BigInteger}.
537 *
538 * <p>Use this method to access the {@code BigInteger} result for exact integer statistics,
539 * for example {@link Statistic#SUM_OF_SQUARES}.
540 *
541 * <p>Note: This method may throw an {@link ArithmeticException} if the result
542 * is not finite.
543 *
544 * @param statistic Statistic.
545 * @return the value
546 * @throws IllegalArgumentException if the {@code statistic} is not supported
547 * @throws ArithmeticException if the {@code result} is not finite
548 * @see #isSupported(Statistic)
549 * @see #getResult(Statistic)
550 */
551 public BigInteger getAsBigInteger(Statistic statistic) {
552 return getResult(statistic).getAsBigInteger();
553 }
554
555 /**
556 * Gets a supplier for the value of the specified {@code statistic}.
557 *
558 * <p>The returned function will supply the correct result after
559 * calls to {@link #accept(long) accept} or
560 * {@link #combine(LongStatistics) combine} further values into
561 * {@code this} instance.
562 *
563 * <p>This method can be used to perform a one-time look-up of the statistic
564 * function to compute statistics as values are dynamically added.
565 *
566 * @param statistic Statistic.
567 * @return the supplier
568 * @throws IllegalArgumentException if the {@code statistic} is not supported
569 * @see #isSupported(Statistic)
570 * @see #getAsDouble(Statistic)
571 */
572 public StatisticResult getResult(Statistic statistic) {
573 // Locate the implementation.
574 // Statistics that wrap an underlying implementation are created in methods.
575 // The return argument should be an interface reference and not an instance
576 // of LongStatistic. This ensures the statistic implementation cannot
577 // be updated with new values by casting the result and calling accept(long).
578 StatisticResult stat = null;
579 // Exhaustive switch statement
580 switch (statistic) {
581 case GEOMETRIC_MEAN:
582 stat = getGeometricMean();
583 break;
584 case KURTOSIS:
585 stat = getKurtosis();
586 break;
587 case MAX:
588 stat = Statistics.getResultAsLongOrNull(max);
589 break;
590 case MEAN:
591 stat = getMean();
592 break;
593 case MIN:
594 stat = Statistics.getResultAsLongOrNull(min);
595 break;
596 case PRODUCT:
597 stat = Statistics.getResultAsDoubleOrNull(product);
598 break;
599 case SKEWNESS:
600 stat = getSkewness();
601 break;
602 case STANDARD_DEVIATION:
603 stat = getStandardDeviation();
604 break;
605 case SUM:
606 stat = Statistics.getResultAsBigIntegerOrNull(sum);
607 break;
608 case SUM_OF_LOGS:
609 stat = Statistics.getResultAsDoubleOrNull(sumOfLogs);
610 break;
611 case SUM_OF_SQUARES:
612 stat = Statistics.getResultAsBigIntegerOrNull(sumOfSquares);
613 break;
614 case VARIANCE:
615 stat = getVariance();
616 break;
617 }
618 if (stat != null) {
619 return stat;
620 }
621 throw new IllegalArgumentException(UNSUPPORTED_STATISTIC + statistic);
622 }
623
624 /**
625 * Gets the geometric mean.
626 *
627 * @return a geometric mean supplier (or null if unsupported)
628 */
629 private StatisticResult getGeometricMean() {
630 if (sumOfLogs != null) {
631 // Return a function that has access to the count and sumOfLogs
632 return () -> GeometricMean.computeGeometricMean(count, sumOfLogs);
633 }
634 return null;
635 }
636
637 /**
638 * Gets the kurtosis.
639 *
640 * @return a kurtosis supplier (or null if unsupported)
641 */
642 private StatisticResult getKurtosis() {
643 if (moment instanceof SumOfFourthDeviations) {
644 return new Kurtosis((SumOfFourthDeviations) moment)
645 .setBiased(config.isBiased())::getAsDouble;
646 }
647 return null;
648 }
649
650 /**
651 * Gets the mean.
652 *
653 * @return a mean supplier (or null if unsupported)
654 */
655 private StatisticResult getMean() {
656 if (sum != null) {
657 // Return a function that has access to the count and sum
658 final Int128 s = sum.getSum();
659 return () -> LongMean.computeMean(s, count);
660 }
661 return null;
662 }
663
664 /**
665 * Gets the skewness.
666 *
667 * @return a skewness supplier (or null if unsupported)
668 */
669 private StatisticResult getSkewness() {
670 if (moment instanceof SumOfCubedDeviations) {
671 return new Skewness((SumOfCubedDeviations) moment)
672 .setBiased(config.isBiased())::getAsDouble;
673 }
674 return null;
675 }
676
677 /**
678 * Gets the standard deviation.
679 *
680 * @return a standard deviation supplier (or null if unsupported)
681 */
682 private StatisticResult getStandardDeviation() {
683 return getVarianceOrStd(true);
684 }
685
686 /**
687 * Gets the variance.
688 *
689 * @return a variance supplier (or null if unsupported)
690 */
691 private StatisticResult getVariance() {
692 return getVarianceOrStd(false);
693 }
694
695 /**
696 * Gets the variance or standard deviation.
697 *
698 * @param std Flag to control if the statistic is the standard deviation.
699 * @return a variance/standard deviation supplier (or null if unsupported)
700 */
701 private StatisticResult getVarianceOrStd(boolean std) {
702 if (sum != null && sumOfSquares != null) {
703 // Return a function that has access to the count, sum and sum of squares
704 final Int128 s = sum.getSum();
705 final UInt192 ss = sumOfSquares.getSumOfSquares();
706 final boolean biased = config.isBiased();
707 return () -> LongVariance.computeVarianceOrStd(ss, s, count, biased, std);
708 }
709 return null;
710 }
711
712 /**
713 * Combines the state of the {@code other} statistics into this one.
714 * Only {@code this} instance is modified by the {@code combine} operation.
715 *
716 * <p>The {@code other} instance must be <em>compatible</em>. This is {@code true} if the
717 * {@code other} instance returns {@code true} for {@link #isSupported(Statistic)} for
718 * all values of the {@link Statistic} enum which are supported by {@code this}
719 * instance.
720 *
721 * <p>Note that this operation is <em>not symmetric</em>. It may be possible to perform
722 * {@code a.combine(b)} but not {@code b.combine(a)}. In the event that the {@code other}
723 * instance is not compatible then an exception is raised before any state is modified.
724 *
725 * @param other Another set of statistics to be combined.
726 * @return {@code this} instance after combining {@code other}.
727 * @throws IllegalArgumentException if the {@code other} is not compatible
728 */
729 public LongStatistics combine(LongStatistics other) {
730 // Check compatibility
731 Statistics.checkCombineCompatible(min, other.min);
732 Statistics.checkCombineCompatible(max, other.max);
733 Statistics.checkCombineCompatible(sum, other.sum);
734 Statistics.checkCombineCompatible(product, other.product);
735 Statistics.checkCombineCompatible(sumOfSquares, other.sumOfSquares);
736 Statistics.checkCombineCompatible(sumOfLogs, other.sumOfLogs);
737 Statistics.checkCombineAssignable(moment, other.moment);
738 // Combine
739 count += other.count;
740 Statistics.combine(min, other.min);
741 Statistics.combine(max, other.max);
742 Statistics.combine(sum, other.sum);
743 Statistics.combine(product, other.product);
744 Statistics.combine(sumOfSquares, other.sumOfSquares);
745 Statistics.combine(sumOfLogs, other.sumOfLogs);
746 Statistics.combineMoment(moment, other.moment);
747 return this;
748 }
749
750 /**
751 * Sets the statistics configuration.
752 *
753 * <p>These options only control the final computation of statistics. The configuration
754 * will not affect compatibility between instances during a
755 * {@link #combine(LongStatistics) combine} operation.
756 *
757 * <p>Note: These options will affect any future computation of statistics. Supplier functions
758 * that have been previously created will not be updated with the new configuration.
759 *
760 * @param v Value.
761 * @return {@code this} instance
762 * @throws NullPointerException if the value is null
763 * @see #getResult(Statistic)
764 */
765 public LongStatistics setConfiguration(StatisticsConfiguration v) {
766 config = Objects.requireNonNull(v);
767 return this;
768 }
769 }