1 /*
2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 
24 /**
25  * @test
26  * @bug 8015396
27  * @summary double a%b returns NaN for some (a,b) (|a| < inf, |b|>0) (on Core i7 980X)
28  *
29  * @run main compiler.floatingpoint.ModNaN
30  */
31 
32 package compiler.floatingpoint;
33 
34 public class ModNaN {
35     /* This bug was seen in the field for a particular version of the VM,
36      * but never reproduced internally, and the reason was never known,
37      * nor were the exact circumstances of the failure.
38      */
39     /*
40      * Failed on Windows 7/Core i7 980X/1.6.0_38 (64-bit):
41      *
42      * NaNs (i.e., when it fails, this is what we expect to see):
43      *
44      * 8.98846567431158E307 % 1.295163E-318 = NaN
45      * (0x7FE0000000000000L % 0x0000000000040000L)
46      *
47      * 1.7976931348623157E308 % 2.59032E-318 = NaN
48      * (0x7FEFFFFFFFFFFFFFL % 0x000000000007FFFFL)
49      *
50      * 1.7976931348623157E308 % 1.060997895E-314 = NaN
51      * (0x7FEFFFFFFFFFFFFFL % 0x000000007FFFFFFFL)
52      *
53      * 1.7976931348623157E308 % 6.767486E-317 = NaN
54      * (0x7FEFFFFFFFFFFFFFL % 0x0000000000d10208L)
55      *
56      * 1.7976931348623157E308 % 7.528725E-318 = NaN
57      * (0x7FEFFFFFFFFFFFFFL % 0x0000000000174077L)
58      *
59      * These cases did not fail, even when the previous five did:
60      * 8.98846567431158E307 % 1.29516E-318 = 2.53E-321
61      * (0x7fe0000000000000L % 0x000000000003ffffL)
62      *
63      * 1.7976931348623157E308 % 2.590327E-318 = 0.0
64      * (0x7fefffffffffffffL % 0x0000000000080000L)
65      *
66      * 1.7976931348623157E308 % 1.060965516E-314 = 9.35818525E-315
67      * (0x7fefffffffffffffL % 0x000000007ffeffffL)
68      *
69      */
70 
71     static double[][] bad = new double[][] {
72             /*
73              * These hex numbers correspond to the base-10 doubles in the
74              * comment above; this can be checked by observing the output
75              * of testWithPrint.
76              */
77             new double[] { Double.longBitsToDouble(0x7FE0000000000000L),
78                     Double.longBitsToDouble(0x0000000000040000L) },
79             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
80                     Double.longBitsToDouble(0x000000000007FFFFL) },
81             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
82                     Double.longBitsToDouble(0x000000007FFFFFFFL) },
83             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
84                     6.767486E-317 },
85             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
86                     7.528725E-318 }, };
87 
88     static double[][] good = new double[][] {
89             new double[] { Double.longBitsToDouble(0x7FE0000000000000L),
90                     Double.longBitsToDouble(0x000000000003FFFFL) },
91             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
92                     Double.longBitsToDouble(0x0000000000080000L) },
93             new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL),
94                     Double.longBitsToDouble(0x000000007FFEFFFFL) }, };
95 
main(String[] args)96     public static void main(String[] args) throws InterruptedException {
97         int N = 10000;
98         testWithPrint();
99         for (int i = 0; i < N; i++)
100             testStrict();
101         for (int i = 0; i < N; i++)
102             test();
103         Thread.sleep(1000); // pause to let the compiler work
104         for (int i = 0; i < 10; i++)
105             testStrict();
106         for (int i = 0; i < 10; i++)
107             test();
108     }
109 
testWithPrint()110     public strictfp static void testWithPrint() {
111         for (double[] ab : bad) {
112             double a = ab[0];
113             double b = ab[1];
114             double mod = a % b;
115             System.out.println("" + a + "("+toHexRep(a)+") mod " +
116                                     b + "("+toHexRep(b)+") yields " +
117                                     mod + "("+toHexRep(mod)+")");
118         }
119 
120         for (double[] ab : good) {
121             double a = ab[0];
122             double b = ab[1];
123             double mod = a % b;
124             System.out.println("" + a + "("+toHexRep(a)+") mod " +
125                                     b + "("+toHexRep(b)+") yields " +
126                                     mod + "("+toHexRep(mod)+")");
127         }
128     }
129 
testStrict()130     public strictfp static void testStrict() {
131         for (double[] ab : bad) {
132             double a = ab[0];
133             double b = ab[1];
134             double mod = a % b;
135             check(mod);
136         }
137 
138         for (double[] ab : good) {
139             double a = ab[0];
140             double b = ab[1];
141             double mod = a % b;
142             check(mod);
143         }
144     }
145 
test()146     public static void test() {
147         for (double[] ab : bad) {
148             double a = ab[0];
149             double b = ab[1];
150             double mod = a % b;
151             check(mod);
152         }
153 
154         for (double[] ab : good) {
155             double a = ab[0];
156             double b = ab[1];
157             double mod = a % b;
158             check(mod);
159         }
160     }
161 
toHexRep(double d)162     static String toHexRep(double d) {
163         return "0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + "L";
164     }
165 
check(double mod)166     static void check(double mod) {
167         if (Double.isNaN(mod)) {
168             throw new Error("Saw a NaN, fail");
169         }
170     }
171 }
172