test/java/util/stream/TestDoubleSumAverage.java
Print this page
@@ -25,26 +25,36 @@
import java.util.function.*;
import java.util.stream.*;
/*
* @test
- * @bug 8006572
+ * @bug 8006572 8030212
* @summary Test for use of non-naive summation in stream-related sum and average operations.
*/
public class TestDoubleSumAverage {
public static void main(String... args) {
int failures = 0;
- failures += testForCompenstation();
failures += testZeroAverageOfNonEmptyStream();
+ failures += testForCompenstation();
+ failures += testInfiniteSum();
if (failures > 0) {
throw new RuntimeException("Found " + failures + " numerical failure(s).");
}
}
/**
+ * Test to verify that a non-empty stream with a zero average is non-empty.
+ */
+ private static int testZeroAverageOfNonEmptyStream() {
+ Supplier<DoubleStream> ds = () -> DoubleStream.iterate(0.0, e -> 0.0).limit(10);
+
+ return compareUlpDifference(0.0, ds.get().average().getAsDouble(), 0);
+ }
+
+ /**
* Compute the sum and average of a sequence of double values in
* various ways and report an error if naive summation is used.
*/
private static int testForCompenstation() {
int failures = 0;
@@ -81,23 +91,64 @@
failures += compareUlpDifference(expectedAvg,
ds.get().boxed().collect(Collectors.averagingDouble(d -> d)),3);
return failures;
}
- /**
- * Test to verify that a non-empty stream with a zero average is non-empty.
- */
- private static int testZeroAverageOfNonEmptyStream() {
- Supplier<DoubleStream> ds = () -> DoubleStream.iterate(0.0, e -> 0.0).limit(10);
+ private static int testInfiniteSum() {
+ int failures = 0;
- return compareUlpDifference(0.0, ds.get().average().getAsDouble(), 0);
+ List<Supplier<DoubleStream>> dss = new ArrayList<>();
+ dss.add(() -> DoubleStream.of(1.0d, Double.POSITIVE_INFINITY, 1.0d));
+ dss.add(() -> DoubleStream.of(1.0d, Double.NEGATIVE_INFINITY, 1.0d));
+ dss.add(() -> DoubleStream.of(1.0d, Double.NaN, 1.0d));
+ dss.add(() -> DoubleStream.of(1.0d, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 1.0d));
+
+ double[] expected = {Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, Double.NaN, Double.NaN};
+
+ int i = 0;
+ for(Supplier<DoubleStream> ds : dss) {
+
+ DoubleSummaryStatistics stats = ds.get().collect(DoubleSummaryStatistics::new,
+ DoubleSummaryStatistics::accept,
+ DoubleSummaryStatistics::combine);
+ System.err.println(i);
+ System.err.println("\ta");
+ failures += compareUlpDifference(expected[i], stats.getSum(), 0);
+ System.err.println("\tb");
+ failures += compareUlpDifference(expected[i], stats.getAverage(), 0);
+
+ System.err.println("\tc");
+ failures += compareUlpDifference(expected[i], ds.get().sum(), 0);
+ System.err.println("\td");
+ failures += compareUlpDifference(expected[i], ds.get().average().getAsDouble(), 0);
+
+ System.err.println("\te");
+ failures += compareUlpDifference(expected[i], ds.get().boxed().collect(Collectors.summingDouble(d -> d)), 0);
+ System.err.println("\tf");
+ failures += compareUlpDifference(expected[i], ds.get().boxed().collect(Collectors.averagingDouble(d -> d)), 0);
+
+ i++;
+ }
+
+ return failures;
}
/**
* Compute the ulp difference of two double values and compare against an error threshold.
*/
private static int compareUlpDifference(double expected, double computed, double threshold) {
+ if (!Double.isFinite(expected)) {
+ // Handle NaN and infinity cases
+ if (Double.compare(expected, computed) == 0)
+ return 0;
+ else {
+ System.err.printf("Unexpected sum, %g rather than %g.%n",
+ computed, expected);
+ return 1;
+ }
+ }
+
double ulpDifference = Math.abs(expected - computed) / Math.ulp(expected);
if (ulpDifference > threshold) {
System.err.printf("Numerical summation error too large, %g ulps rather than %g.%n",
ulpDifference, threshold);