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