src/share/classes/java/util/stream/DoublePipeline.java

Print this page

        

*** 375,386 **** evaluate(ForEachOps.makeDouble(consumer, true)); } @Override public final double sum() { ! // TODO: better algorithm to compensate for errors ! return reduce(0.0, Double::sum); } @Override public final OptionalDouble min() { return reduce(Math::min); --- 375,401 ---- evaluate(ForEachOps.makeDouble(consumer, true)); } @Override public final double sum() { ! /* ! * In the arrays allocated for the collect operation, index 0 ! * holds the high-order bits of the running sum and index 1 ! * holds the low-order bits of the sum computed via ! * compensated summation. ! */ ! double[] summation = collect(() -> new double[2], ! (ll, d) -> { ! Collectors.sumWithCompensation(ll, d); ! }, ! (ll, rr) -> { ! Collectors.sumWithCompensation(ll, rr[0]); ! Collectors.sumWithCompensation(ll, rr[1]); ! }); ! ! // Better error bounds to add both terms as the final sum ! return summation[0] + summation[1]; } @Override public final OptionalDouble min() { return reduce(Math::min);
*** 389,411 **** @Override public final OptionalDouble max() { return reduce(Math::max); } @Override public final OptionalDouble average() { ! double[] avg = collect(() -> new double[2], ! (ll, i) -> { ! ll[0]++; ! ll[1] += i; }, (ll, rr) -> { ! ll[0] += rr[0]; ! ll[1] += rr[1]; }); ! return avg[0] > 0 ! ? OptionalDouble.of(avg[1] / avg[0]) : OptionalDouble.empty(); } @Override public final long count() { --- 404,443 ---- @Override public final OptionalDouble max() { return reduce(Math::max); } + /** + * {@inheritDoc} + * + * @implNote The {@code double} format can represent all + * consecutive integers in the range -2<sup>53</sup> to + * 2<sup>53</sup>. If the pipeline has more than 2<sup>53</sup> + * values, the divisor in the average computation will saturate at + * 2<sup>53</sup>, leading to additional numerical errors. + */ @Override public final OptionalDouble average() { ! /* ! * In the arrays allocated for the collect operation, index 0 ! * holds the high-order bits of the running sum, index 1 holds ! * the low-order bits of the sum computed via compensated ! * summation, and index 2 holds the number of values seen. ! */ ! double[] avg = collect(() -> new double[3], ! (ll, d) -> { ! ll[2]++; ! Collectors.sumWithCompensation(ll, d); }, (ll, rr) -> { ! Collectors.sumWithCompensation(ll, rr[0]); ! Collectors.sumWithCompensation(ll, rr[1]); ! ll[2] += rr[2]; }); ! return avg[2] > 0 ! // Better error bounds to add both terms as the final sum to compute average ! ? OptionalDouble.of((avg[0] + avg[1]) / avg[2]) : OptionalDouble.empty(); } @Override public final long count() {