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