jdk/test/java/util/stream/TestDoubleSumAverage.java
author darcy
Sun, 01 Dec 2013 23:35:28 -0800
changeset 21946 b4cb3bbeb52a
child 22101 231247ddf41a
permissions -rw-r--r--
8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors Reviewed-by: psandoz, mduigou
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
21946
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     1
/*
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     2
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     4
 *
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     7
 * published by the Free Software Foundation.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     8
 *
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
     9
 * This code is distributed in the hope that it will be useful, but WITHOUT
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    11
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    12
 * version 2 for more details (a copy is included in the LICENSE file that
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    13
 * accompanied this code).
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    14
 *
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    15
 * You should have received a copy of the GNU General Public License version
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    16
 * 2 along with this work; if not, write to the Free Software Foundation,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    17
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    18
 *
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    19
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    20
 * or visit www.oracle.com if you need additional information or have any
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    21
 * questions.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    22
 */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    23
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    24
import java.util.*;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    25
import java.util.function.*;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    26
import java.util.stream.*;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    27
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    28
/*
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    29
 * @test
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    30
 * @bug 8006572
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    31
 * @summary Test for use of non-naive summation in stream-related sum and average operations.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    32
 */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    33
public class TestDoubleSumAverage {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    34
    public static void main(String... args) {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    35
        int failures = 0;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    36
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    37
        failures += testForCompenstation();
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    38
        failures += testZeroAverageOfNonEmptyStream();
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    39
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    40
        if (failures > 0) {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    41
            throw new RuntimeException("Found " + failures + " numerical failure(s).");
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    42
        }
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    43
    }
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    44
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    45
    /**
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    46
     * Compute the sum and average of a sequence of double values in
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    47
     * various ways and report an error if naive summation is used.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    48
     */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    49
    private static int testForCompenstation() {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    50
        int failures = 0;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    51
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    52
        /*
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    53
         * The exact sum of the test stream is 1 + 1e6*ulp(1.0) but a
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    54
         * naive summation algorithm will return 1.0 since (1.0 +
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    55
         * ulp(1.0)/2) will round to 1.0 again.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    56
         */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    57
        double base = 1.0;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    58
        double increment = Math.ulp(base)/2.0;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    59
        int count = 1_000_001;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    60
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    61
        double expectedSum = base + (increment * (count - 1));
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    62
        double expectedAvg = expectedSum / count;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    63
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    64
        // Factory for double a stream of [base, increment, ..., increment] limited to a size of count
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    65
        Supplier<DoubleStream> ds = () -> DoubleStream.iterate(base, e -> increment).limit(count);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    66
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    67
        DoubleSummaryStatistics stats = ds.get().collect(DoubleSummaryStatistics::new,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    68
                                                         DoubleSummaryStatistics::accept,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    69
                                                         DoubleSummaryStatistics::combine);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    70
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    71
        failures += compareUlpDifference(expectedSum, stats.getSum(), 3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    72
        failures += compareUlpDifference(expectedAvg, stats.getAverage(), 3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    73
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    74
        failures += compareUlpDifference(expectedSum,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    75
                                         ds.get().sum(), 3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    76
        failures += compareUlpDifference(expectedAvg,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    77
                                         ds.get().average().getAsDouble(), 3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    78
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    79
        failures += compareUlpDifference(expectedSum,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    80
                                         ds.get().boxed().collect(Collectors.summingDouble(d -> d)), 3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    81
        failures += compareUlpDifference(expectedAvg,
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    82
                                         ds.get().boxed().collect(Collectors.averagingDouble(d -> d)),3);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    83
        return failures;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    84
    }
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    85
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    86
    /**
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    87
     * Test to verify that a non-empty stream with a zero average is non-empty.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    88
     */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    89
    private static int testZeroAverageOfNonEmptyStream() {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    90
        Supplier<DoubleStream> ds = () -> DoubleStream.iterate(0.0, e -> 0.0).limit(10);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    91
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    92
        return  compareUlpDifference(0.0, ds.get().average().getAsDouble(), 0);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    93
    }
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    94
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    95
    /**
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    96
     * Compute the ulp difference of two double values and compare against an error threshold.
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    97
     */
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    98
    private static int compareUlpDifference(double expected, double computed, double threshold) {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
    99
        double ulpDifference = Math.abs(expected - computed) / Math.ulp(expected);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   100
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   101
        if (ulpDifference > threshold) {
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   102
            System.err.printf("Numerical summation error too large, %g ulps rather than %g.%n",
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   103
                              ulpDifference, threshold);
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   104
            return 1;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   105
        } else
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   106
            return 0;
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   107
    }
b4cb3bbeb52a 8006572: DoubleStream.sum() & DoubleSummaryStats implementations that reduce numerical errors
darcy
parents:
diff changeset
   108
}