490 /** 491 * Returns a {@code Collector} that produces the sum of a double-valued 492 * function applied to the input elements. If no elements are present, 493 * the result is 0. 494 * 495 * <p>The sum returned can vary depending upon the order in which 496 * values are recorded, due to accumulated rounding error in 497 * addition of values of differing magnitudes. Values sorted by increasing 498 * absolute magnitude tend to yield more accurate results. If any recorded 499 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the 500 * sum will be {@code NaN}. 501 * 502 * @param <T> the type of the input elements 503 * @param mapper a function extracting the property to be summed 504 * @return a {@code Collector} that produces the sum of a derived property 505 */ 506 public static <T> Collector<T, ?, Double> 507 summingDouble(ToDoubleFunction<? super T> mapper) { 508 /* 509 * In the arrays allocated for the collect operation, index 0 510 * holds the high-order bits of the running sum and index 1 511 * holds the low-order bits of the sum computed via 512 * compensated summation. 513 */ 514 return new CollectorImpl<>( 515 () -> new double[2], 516 (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); }, 517 (a, b) -> { sumWithCompensation(a, b[0]); return sumWithCompensation(a, b[1]); }, 518 // Better error bounds to add both terms as the final sum 519 a -> a[0] + a[1], 520 CH_NOID); 521 } 522 523 /** 524 * Incorporate a new double value using Kahan summation / 525 * compensation summation. 526 * 527 * High-order bits of the sum are in intermediateSum[0], low-order 528 * bits of the sum are in intermediateSum[1], any additional 529 * elements are application-specific. 530 * 531 * @param intermediateSum the high-order and low-order words of the intermediate sum 532 * @param value the name value to be included in the running sum 533 */ 534 static double[] sumWithCompensation(double[] intermediateSum, double value) { 535 double tmp = value - intermediateSum[1]; 536 double sum = intermediateSum[0]; 537 double velvel = sum + tmp; // Little wolf of rounding error 538 intermediateSum[1] = (velvel - sum) - tmp; 539 intermediateSum[0] = velvel; 540 return intermediateSum; 541 } 542 543 544 /** 545 * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued 546 * function applied to the input elements. If no elements are present, 547 * the result is 0. 548 * 549 * @param <T> the type of the input elements 550 * @param mapper a function extracting the property to be summed 551 * @return a {@code Collector} that produces the sum of a derived property 552 */ 553 public static <T> Collector<T, ?, Double> 554 averagingInt(ToIntFunction<? super T> mapper) { 555 return new CollectorImpl<>( 556 () -> new long[2], 557 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, 558 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, 559 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); 560 } 561 562 /** 591 * 592 * @implNote The {@code double} format can represent all 593 * consecutive integers in the range -2<sup>53</sup> to 594 * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup> 595 * values, the divisor in the average computation will saturate at 596 * 2<sup>53</sup>, leading to additional numerical errors. 597 * 598 * @param <T> the type of the input elements 599 * @param mapper a function extracting the property to be summed 600 * @return a {@code Collector} that produces the sum of a derived property 601 */ 602 public static <T> Collector<T, ?, Double> 603 averagingDouble(ToDoubleFunction<? super T> mapper) { 604 /* 605 * In the arrays allocated for the collect operation, index 0 606 * holds the high-order bits of the running sum, index 1 holds 607 * the low-order bits of the sum computed via compensated 608 * summation, and index 2 holds the number of values seen. 609 */ 610 return new CollectorImpl<>( 611 () -> new double[3], 612 (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; }, 613 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; return a; }, 614 // Better error bounds to add both terms as the final sum to compute average 615 a -> (a[2] == 0) ? 0.0d : ((a[0] + a[1]) / a[2]), 616 CH_NOID); 617 } 618 619 /** 620 * Returns a {@code Collector} which performs a reduction of its 621 * input elements under a specified {@code BinaryOperator} using the 622 * provided identity. 623 * 624 * @apiNote 625 * The {@code reducing()} collectors are most useful when used in a 626 * multi-level reduction, downstream of {@code groupingBy} or 627 * {@code partitioningBy}. To perform a simple reduction on a stream, 628 * use {@link Stream#reduce(Object, BinaryOperator)}} instead. 629 * 630 * @param <T> element type for the input and output of the reduction 631 * @param identity the identity value for the reduction (also, the value 632 * that is returned when there are no input elements) 633 * @param op a {@code BinaryOperator<T>} used to reduce the input elements 634 * @return a {@code Collector} which implements the reduction operation 635 * | 490 /** 491 * Returns a {@code Collector} that produces the sum of a double-valued 492 * function applied to the input elements. If no elements are present, 493 * the result is 0. 494 * 495 * <p>The sum returned can vary depending upon the order in which 496 * values are recorded, due to accumulated rounding error in 497 * addition of values of differing magnitudes. Values sorted by increasing 498 * absolute magnitude tend to yield more accurate results. If any recorded 499 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the 500 * sum will be {@code NaN}. 501 * 502 * @param <T> the type of the input elements 503 * @param mapper a function extracting the property to be summed 504 * @return a {@code Collector} that produces the sum of a derived property 505 */ 506 public static <T> Collector<T, ?, Double> 507 summingDouble(ToDoubleFunction<? super T> mapper) { 508 /* 509 * In the arrays allocated for the collect operation, index 0 510 * holds the high-order bits of the running sum, index 1 holds 511 * the low-order bits of the sum computed via compensated 512 * summation, and index 2 holds the simple sum used to compute 513 * the proper result if the stream contains infinite values of 514 * the same sign. 515 */ 516 return new CollectorImpl<>( 517 () -> new double[3], 518 (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); 519 a[2] += mapper.applyAsDouble(t);}, 520 (a, b) -> { sumWithCompensation(a, b[0]); 521 a[2] += b[2]; 522 return sumWithCompensation(a, b[1]); }, 523 a -> computeFinalSum(a), 524 CH_NOID); 525 } 526 527 /** 528 * Incorporate a new double value using Kahan summation / 529 * compensation summation. 530 * 531 * High-order bits of the sum are in intermediateSum[0], low-order 532 * bits of the sum are in intermediateSum[1], any additional 533 * elements are application-specific. 534 * 535 * @param intermediateSum the high-order and low-order words of the intermediate sum 536 * @param value the name value to be included in the running sum 537 */ 538 static double[] sumWithCompensation(double[] intermediateSum, double value) { 539 double tmp = value - intermediateSum[1]; 540 double sum = intermediateSum[0]; 541 double velvel = sum + tmp; // Little wolf of rounding error 542 intermediateSum[1] = (velvel - sum) - tmp; 543 intermediateSum[0] = velvel; 544 return intermediateSum; 545 } 546 547 /** 548 * If the compensated sum is spuriously NaN from accumulating one 549 * or more same-signed infinite values, return the 550 * correctly-signed infinity stored in the simple sum. 551 */ 552 static double computeFinalSum(double[] summands) { 553 // Better error bounds to add both terms as the final sum 554 double tmp = summands[0] + summands[1]; 555 double simpleSum = summands[summands.length - 1]; 556 if (Double.isNaN(tmp) && Double.isInfinite(simpleSum)) 557 return simpleSum; 558 else 559 return tmp; 560 } 561 562 /** 563 * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued 564 * function applied to the input elements. If no elements are present, 565 * the result is 0. 566 * 567 * @param <T> the type of the input elements 568 * @param mapper a function extracting the property to be summed 569 * @return a {@code Collector} that produces the sum of a derived property 570 */ 571 public static <T> Collector<T, ?, Double> 572 averagingInt(ToIntFunction<? super T> mapper) { 573 return new CollectorImpl<>( 574 () -> new long[2], 575 (a, t) -> { a[0] += mapper.applyAsInt(t); a[1]++; }, 576 (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; }, 577 a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], CH_NOID); 578 } 579 580 /** 609 * 610 * @implNote The {@code double} format can represent all 611 * consecutive integers in the range -2<sup>53</sup> to 612 * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup> 613 * values, the divisor in the average computation will saturate at 614 * 2<sup>53</sup>, leading to additional numerical errors. 615 * 616 * @param <T> the type of the input elements 617 * @param mapper a function extracting the property to be summed 618 * @return a {@code Collector} that produces the sum of a derived property 619 */ 620 public static <T> Collector<T, ?, Double> 621 averagingDouble(ToDoubleFunction<? super T> mapper) { 622 /* 623 * In the arrays allocated for the collect operation, index 0 624 * holds the high-order bits of the running sum, index 1 holds 625 * the low-order bits of the sum computed via compensated 626 * summation, and index 2 holds the number of values seen. 627 */ 628 return new CollectorImpl<>( 629 () -> new double[4], 630 (a, t) -> { sumWithCompensation(a, mapper.applyAsDouble(t)); a[2]++; a[3]+= mapper.applyAsDouble(t);}, 631 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]), 632 CH_NOID); 633 } 634 635 /** 636 * Returns a {@code Collector} which performs a reduction of its 637 * input elements under a specified {@code BinaryOperator} using the 638 * provided identity. 639 * 640 * @apiNote 641 * The {@code reducing()} collectors are most useful when used in a 642 * multi-level reduction, downstream of {@code groupingBy} or 643 * {@code partitioningBy}. To perform a simple reduction on a stream, 644 * use {@link Stream#reduce(Object, BinaryOperator)}} instead. 645 * 646 * @param <T> element type for the input and output of the reduction 647 * @param identity the identity value for the reduction (also, the value 648 * that is returned when there are no input elements) 649 * @param op a {@code BinaryOperator<T>} used to reduce the input elements 650 * @return a {@code Collector} which implements the reduction operation 651 * |