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 * @ignore 8145543 30 * @run main compiler.floatingpoint.ModNaN 31 */ 32 33 package compiler.floatingpoint; 34 35 public class ModNaN { 36 /* This bug was seen in the field for a particular version of the VM, 37 * but never reproduced internally, and the reason was never known, 38 * nor were the exact circumstances of the failure. 39 */ 40 /* 41 * Failed on Windows 7/Core i7 980X/1.6.0_38 (64-bit): 42 * 43 * NaNs (i.e., when it fails, this is what we expect to see): 44 * 45 * 8.98846567431158E307 % 1.295163E-318 = NaN 46 * (0x7FE0000000000000L % 0x0000000000040000L) 47 * 48 * 1.7976931348623157E308 % 2.59032E-318 = NaN 49 * (0x7FEFFFFFFFFFFFFFL % 0x000000000007FFFFL) 50 * 51 * 1.7976931348623157E308 % 1.060997895E-314 = NaN 52 * (0x7FEFFFFFFFFFFFFFL % 0x000000007FFFFFFFL) 53 * 54 * 1.7976931348623157E308 % 6.767486E-317 = NaN 55 * (0x7FEFFFFFFFFFFFFFL % 0x0000000000d10208L) 56 * 57 * 1.7976931348623157E308 % 7.528725E-318 = NaN 58 * (0x7FEFFFFFFFFFFFFFL % 0x0000000000174077L) 59 * 60 * These cases did not fail, even when the previous five did: 61 * 8.98846567431158E307 % 1.29516E-318 = 2.53E-321 62 * (0x7fe0000000000000L % 0x000000000003ffffL) 63 * 64 * 1.7976931348623157E308 % 2.590327E-318 = 0.0 65 * (0x7fefffffffffffffL % 0x0000000000080000L) 66 * 67 * 1.7976931348623157E308 % 1.060965516E-314 = 9.35818525E-315 68 * (0x7fefffffffffffffL % 0x000000007ffeffffL) 69 * 70 */ 71 72 static double[][] bad = new double[][] { 73 /* 74 * These hex numbers correspond to the base-10 doubles in the 75 * comment above; this can be checked by observing the output 76 * of testWithPrint. 77 */ 78 new double[] { Double.longBitsToDouble(0x7FE0000000000000L), 79 Double.longBitsToDouble(0x0000000000040000L) }, 80 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 81 Double.longBitsToDouble(0x000000000007FFFFL) }, 82 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 83 Double.longBitsToDouble(0x000000007FFFFFFFL) }, 84 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 85 6.767486E-317 }, 86 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 87 7.528725E-318 }, }; 88 89 static double[][] good = new double[][] { 90 new double[] { Double.longBitsToDouble(0x7FE0000000000000L), 91 Double.longBitsToDouble(0x000000000003FFFFL) }, 92 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 93 Double.longBitsToDouble(0x0000000000080000L) }, 94 new double[] { Double.longBitsToDouble(0x7FEFFFFFFFFFFFFFL), 95 Double.longBitsToDouble(0x000000007FFEFFFFL) }, }; 96 97 public static void main(String[] args) throws InterruptedException { 98 int N = 10000; 99 testWithPrint(); 100 for (int i = 0; i < N; i++) 101 testStrict(); 102 for (int i = 0; i < N; i++) 103 test(); 104 Thread.sleep(1000); // pause to let the compiler work 105 for (int i = 0; i < 10; i++) 106 testStrict(); 107 for (int i = 0; i < 10; i++) 108 test(); 109 } 110 111 public strictfp static void testWithPrint() { 112 for (double[] ab : bad) { 113 double a = ab[0]; 114 double b = ab[1]; 115 double mod = a % b; 116 System.out.println("" + a + "("+toHexRep(a)+") mod " + 117 b + "("+toHexRep(b)+") yields " + 118 mod + "("+toHexRep(mod)+")"); 119 } 120 121 for (double[] ab : good) { 122 double a = ab[0]; 123 double b = ab[1]; 124 double mod = a % b; 125 System.out.println("" + a + "("+toHexRep(a)+") mod " + 126 b + "("+toHexRep(b)+") yields " + 127 mod + "("+toHexRep(mod)+")"); 128 } 129 } 130 131 public strictfp static void testStrict() { 132 for (double[] ab : bad) { 133 double a = ab[0]; 134 double b = ab[1]; 135 double mod = a % b; 136 check(mod); 137 } 138 139 for (double[] ab : good) { 140 double a = ab[0]; 141 double b = ab[1]; 142 double mod = a % b; 143 check(mod); 144 } 145 } 146 147 public static void test() { 148 for (double[] ab : bad) { 149 double a = ab[0]; 150 double b = ab[1]; 151 double mod = a % b; 152 check(mod); 153 } 154 155 for (double[] ab : good) { 156 double a = ab[0]; 157 double b = ab[1]; 158 double mod = a % b; 159 check(mod); 160 } 161 } 162 163 static String toHexRep(double d) { 164 return "0x" + Long.toHexString(Double.doubleToRawLongBits(d)) + "L"; 165 } 166 167 static void check(double mod) { 168 if (Double.isNaN(mod)) { 169 throw new Error("Saw a NaN, fail"); 170 } 171 } 172 }