697 * Returns a {@code Collector} that produces the sum of a double-valued
698 * function applied to the input elements. If no elements are present,
699 * the result is 0.
700 *
701 * <p>The sum returned can vary depending upon the order in which
702 * values are recorded, due to accumulated rounding error in
703 * addition of values of differing magnitudes. Values sorted by increasing
704 * absolute magnitude tend to yield more accurate results. If any recorded
705 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
706 * sum will be {@code NaN}.
707 *
708 * @param <T> the type of the input elements
709 * @param mapper a function extracting the property to be summed
710 * @return a {@code Collector} that produces the sum of a derived property
711 */
712 public static <T> Collector<T, ?, Double>
713 summingDouble(ToDoubleFunction<? super T> mapper) {
714 /*
715 * In the arrays allocated for the collect operation, index 0
716 * holds the high-order bits of the running sum, index 1 holds
717 * the low-order bits of the sum computed via compensated
718 * summation, and index 2 holds the simple sum used to compute
719 * the proper result if the stream contains infinite values of
720 * the same sign.
721 */
722 return new CollectorImpl<>(
723 () -> new double[3],
724 (a, t) -> { double val = mapper.applyAsDouble(t);
725 sumWithCompensation(a, val);
726 a[2] += val;},
727 (a, b) -> { sumWithCompensation(a, b[0]);
728 a[2] += b[2];
729 return sumWithCompensation(a, b[1]); },
730 a -> computeFinalSum(a),
731 CH_NOID);
732 }
733
734 /**
735 * Incorporate a new double value using Kahan summation /
736 * compensation summation.
737 *
738 * High-order bits of the sum are in intermediateSum[0], low-order
739 * bits of the sum are in intermediateSum[1], any additional
740 * elements are application-specific.
741 *
742 * @param intermediateSum the high-order and low-order words of the intermediate sum
743 * @param value the name value to be included in the running sum
744 */
745 static double[] sumWithCompensation(double[] intermediateSum, double value) {
746 double tmp = value - intermediateSum[1];
747 double sum = intermediateSum[0];
748 double velvel = sum + tmp; // Little wolf of rounding error
749 intermediateSum[1] = (velvel - sum) - tmp;
750 intermediateSum[0] = velvel;
751 return intermediateSum;
752 }
753
754 /**
755 * If the compensated sum is spuriously NaN from accumulating one
756 * or more same-signed infinite values, return the
757 * correctly-signed infinity stored in the simple sum.
758 */
759 static double computeFinalSum(double[] summands) {
760 // Better error bounds to add both terms as the final sum
761 double tmp = summands[0] + summands[1];
762 double simpleSum = summands[summands.length - 1];
763 if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
764 return simpleSum;
765 else
766 return tmp;
767 }
768
769 /**
770 * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued
771 * function applied to the input elements. If no elements are present,
772 * the result is 0.
773 *
774 * @param <T> the type of the input elements
775 * @param mapper a function extracting the property to be averaged
776 * @return a {@code Collector} that produces the arithmetic mean of a
777 * derived property
778 */
779 public static <T> Collector<T, ?, Double>
780 averagingInt(ToIntFunction<? super T> mapper) {
781 return new CollectorImpl<>(
815 * absolute magnitude tend to yield more accurate results. If any recorded
816 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
817 * average will be {@code NaN}.
818 *
819 * @implNote The {@code double} format can represent all
820 * consecutive integers in the range -2<sup>53</sup> to
821 * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
822 * values, the divisor in the average computation will saturate at
823 * 2<sup>53</sup>, leading to additional numerical errors.
824 *
825 * @param <T> the type of the input elements
826 * @param mapper a function extracting the property to be averaged
827 * @return a {@code Collector} that produces the arithmetic mean of a
828 * derived property
829 */
830 public static <T> Collector<T, ?, Double>
831 averagingDouble(ToDoubleFunction<? super T> mapper) {
832 /*
833 * In the arrays allocated for the collect operation, index 0
834 * holds the high-order bits of the running sum, index 1 holds
835 * the low-order bits of the sum computed via compensated
836 * summation, and index 2 holds the number of values seen.
837 */
838 return new CollectorImpl<>(
839 () -> new double[4],
840 (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3]+= val;},
841 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
842 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
843 CH_NOID);
844 }
845
846 /**
847 * Returns a {@code Collector} which performs a reduction of its
848 * input elements under a specified {@code BinaryOperator} using the
849 * provided identity.
850 *
851 * @apiNote
852 * The {@code reducing()} collectors are most useful when used in a
853 * multi-level reduction, downstream of {@code groupingBy} or
854 * {@code partitioningBy}. To perform a simple reduction on a stream,
855 * use {@link Stream#reduce(Object, BinaryOperator)}} instead.
856 *
857 * @param <T> element type for the input and output of the reduction
858 * @param identity the identity value for the reduction (also, the value
859 * that is returned when there are no input elements)
860 * @param op a {@code BinaryOperator<T>} used to reduce the input elements
861 * @return a {@code Collector} which implements the reduction operation
|
697 * Returns a {@code Collector} that produces the sum of a double-valued
698 * function applied to the input elements. If no elements are present,
699 * the result is 0.
700 *
701 * <p>The sum returned can vary depending upon the order in which
702 * values are recorded, due to accumulated rounding error in
703 * addition of values of differing magnitudes. Values sorted by increasing
704 * absolute magnitude tend to yield more accurate results. If any recorded
705 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
706 * sum will be {@code NaN}.
707 *
708 * @param <T> the type of the input elements
709 * @param mapper a function extracting the property to be summed
710 * @return a {@code Collector} that produces the sum of a derived property
711 */
712 public static <T> Collector<T, ?, Double>
713 summingDouble(ToDoubleFunction<? super T> mapper) {
714 /*
715 * In the arrays allocated for the collect operation, index 0
716 * holds the high-order bits of the running sum, index 1 holds
717 * the (negative) low-order bits of the sum computed via compensated
718 * summation, and index 2 holds the simple sum used to compute
719 * the proper result if the stream contains infinite values of
720 * the same sign.
721 */
722 return new CollectorImpl<>(
723 () -> new double[3],
724 (a, t) -> { double val = mapper.applyAsDouble(t);
725 sumWithCompensation(a, val);
726 a[2] += val;},
727 (a, b) -> { sumWithCompensation(a, b[0]);
728 a[2] += b[2];
729 return sumWithCompensation(a, -b[1]); },
730 a -> computeFinalSum(a),
731 CH_NOID);
732 }
733
734 /**
735 * Incorporate a new double value using Kahan summation /
736 * compensation summation.
737 *
738 * High-order bits of the sum are in intermediateSum[0],
739 * negative low-order bits of the sum are in intermediateSum[1],
740 * any additional elements are application-specific.
741 *
742 * @param intermediateSum the high-order and low-order words of the intermediate sum
743 * @param value the name value to be included in the running sum
744 */
745 static double[] sumWithCompensation(double[] intermediateSum, double value) {
746 double tmp = value - intermediateSum[1];
747 double sum = intermediateSum[0];
748 double velvel = sum + tmp; // Little wolf of rounding error
749 intermediateSum[1] = (velvel - sum) - tmp;
750 intermediateSum[0] = velvel;
751 return intermediateSum;
752 }
753
754 /**
755 * If the compensated sum is spuriously NaN from accumulating one
756 * or more same-signed infinite values, return the
757 * correctly-signed infinity stored in the simple sum.
758 */
759 static double computeFinalSum(double[] summands) {
760 // Better error bounds to add both terms as the final sum
761 double tmp = summands[0] - summands[1];
762 double simpleSum = summands[summands.length - 1];
763 if (Double.isNaN(tmp) && Double.isInfinite(simpleSum))
764 return simpleSum;
765 else
766 return tmp;
767 }
768
769 /**
770 * Returns a {@code Collector} that produces the arithmetic mean of an integer-valued
771 * function applied to the input elements. If no elements are present,
772 * the result is 0.
773 *
774 * @param <T> the type of the input elements
775 * @param mapper a function extracting the property to be averaged
776 * @return a {@code Collector} that produces the arithmetic mean of a
777 * derived property
778 */
779 public static <T> Collector<T, ?, Double>
780 averagingInt(ToIntFunction<? super T> mapper) {
781 return new CollectorImpl<>(
815 * absolute magnitude tend to yield more accurate results. If any recorded
816 * value is a {@code NaN} or the sum is at any point a {@code NaN} then the
817 * average will be {@code NaN}.
818 *
819 * @implNote The {@code double} format can represent all
820 * consecutive integers in the range -2<sup>53</sup> to
821 * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup>
822 * values, the divisor in the average computation will saturate at
823 * 2<sup>53</sup>, leading to additional numerical errors.
824 *
825 * @param <T> the type of the input elements
826 * @param mapper a function extracting the property to be averaged
827 * @return a {@code Collector} that produces the arithmetic mean of a
828 * derived property
829 */
830 public static <T> Collector<T, ?, Double>
831 averagingDouble(ToDoubleFunction<? super T> mapper) {
832 /*
833 * In the arrays allocated for the collect operation, index 0
834 * holds the high-order bits of the running sum, index 1 holds
835 * the (negative) low-order bits of the sum computed via compensated
836 * summation, and index 2 holds the number of values seen.
837 */
838 return new CollectorImpl<>(
839 () -> new double[4],
840 (a, t) -> { double val = mapper.applyAsDouble(t); sumWithCompensation(a, val); a[2]++; a[3] += val; },
841 (a, b) -> { sumWithCompensation(a, b[0]); sumWithCompensation(a, -b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
842 a -> (a[2] == 0) ? 0.0d : (computeFinalSum(a) / a[2]),
843 CH_NOID);
844 }
845
846 /**
847 * Returns a {@code Collector} which performs a reduction of its
848 * input elements under a specified {@code BinaryOperator} using the
849 * provided identity.
850 *
851 * @apiNote
852 * The {@code reducing()} collectors are most useful when used in a
853 * multi-level reduction, downstream of {@code groupingBy} or
854 * {@code partitioningBy}. To perform a simple reduction on a stream,
855 * use {@link Stream#reduce(Object, BinaryOperator)}} instead.
856 *
857 * @param <T> element type for the input and output of the reduction
858 * @param identity the identity value for the reduction (also, the value
859 * that is returned when there are no input elements)
860 * @param op a {@code BinaryOperator<T>} used to reduce the input elements
861 * @return a {@code Collector} which implements the reduction operation
|