< prev index next >

src/java.base/share/classes/java/util/stream/Collectors.java

Print this page
rev 52916 : [mq]: 8214761-Bug-in-parallel-Kahan-summation-implementation-for-Doublestream-sum


 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


< prev index next >