1 /* 2 * Copyright 2018-2019 Raffaello Giulietti 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to deal 6 * in the Software without restriction, including without limitation the rights 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 * copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 * THE SOFTWARE. 21 */ 22 23 package jdk.internal.math; 24 25 import java.math.BigDecimal; 26 import java.util.Random; 27 28 import static java.lang.Float.*; 29 import static java.lang.Integer.numberOfTrailingZeros; 30 import static java.lang.Math.scalb; 31 import static jdk.internal.math.FloatToDecimal.*; 32 import static jdk.internal.math.MathUtils.flog10pow2; 33 34 public class FloatToDecimalChecker extends ToDecimalChecker { 35 36 private float v; 37 private final int originalBits; 38 39 private FloatToDecimalChecker(float v, String s) { 40 super(s); 41 this.v = v; 42 originalBits = floatToRawIntBits(v); 43 } 44 45 @Override 46 BigDecimal toBigDecimal() { 47 return new BigDecimal(v); 48 } 49 50 @Override 51 boolean recovers(BigDecimal b) { 52 return b.floatValue() == v; 53 } 54 55 @Override 56 String hexBits() { 57 return String.format("0x%01X__%02X__%02X_%04X", 58 (originalBits >>> 31) & 0x1, 59 (originalBits >>> 23) & 0xFF, 60 (originalBits >>> 16) & 0x7F, 61 originalBits & 0xFFFF); 62 } 63 64 @Override 65 boolean recovers(String s) { 66 return parseFloat(s) == v; 67 } 68 69 @Override 70 int minExp() { 71 return MIN_EXP; 72 } 73 74 @Override 75 int maxExp() { 76 return MAX_EXP; 77 } 78 79 @Override 80 int maxLen10() { 81 return H; 82 } 83 84 @Override 85 boolean isZero() { 86 return v == 0; 87 } 88 89 @Override 90 boolean isInfinity() { 91 return v == POSITIVE_INFINITY; 92 } 93 94 @Override 95 void negate() { 96 v = -v; 97 } 98 99 @Override 100 boolean isNegative() { 101 return originalBits < 0; 102 } 103 104 @Override 105 boolean isNaN() { 106 return Float.isNaN(v); 107 } 108 109 private static void toDec(float v) { 110 // String s = Float.toString(v); 111 String s = FloatToDecimal.toString(v); 112 new FloatToDecimalChecker(v, s).assertTrue(); 113 } 114 115 /* 116 MIN_NORMAL is incorrectly rendered by the JDK. 117 */ 118 private static void testExtremeValues() { 119 toDec(NEGATIVE_INFINITY); 120 toDec(-MAX_VALUE); 121 toDec(-MIN_NORMAL); 122 toDec(-MIN_VALUE); 123 toDec(-0.0f); 124 toDec(0.0f); 125 toDec(MIN_VALUE); 126 toDec(MIN_NORMAL); 127 toDec(MAX_VALUE); 128 toDec(POSITIVE_INFINITY); 129 toDec(NaN); 130 131 /* 132 Quiet NaNs have the most significant bit of the mantissa as 1, 133 while signaling NaNs have it as 0. 134 Exercise 4 combinations of quiet/signaling NaNs and 135 "positive/negative" NaNs. 136 */ 137 toDec(intBitsToFloat(0x7FC0_0001)); 138 toDec(intBitsToFloat(0x7F80_0001)); 139 toDec(intBitsToFloat(0xFFC0_0001)); 140 toDec(intBitsToFloat(0xFF80_0001)); 141 142 /* 143 All values treated specially by Schubfach 144 */ 145 toDec(1.4E-45F); 146 toDec(2.8E-45F); 147 toDec(4.2E-45F); 148 toDec(5.6E-45F); 149 toDec(7.0E-45F); 150 toDec(8.4E-45F); 151 toDec(9.8E-45F); 152 } 153 154 /* 155 A few "powers of 10" are incorrectly rendered by the JDK. 156 The rendering is either too long or it is not the closest decimal. 157 */ 158 private static void testPowersOf10() { 159 for (int e = MIN_EXP; e <= MAX_EXP; ++e) { 160 toDec(parseFloat("1e" + e)); 161 } 162 } 163 164 /* 165 Many powers of 2 are incorrectly rendered by the JDK. 166 The rendering is either too long or it is not the closest decimal. 167 */ 168 private static void testPowersOf2() { 169 for (float v = MIN_VALUE; v <= MAX_VALUE; v *= 2) { 170 toDec(v); 171 } 172 } 173 174 /* 175 There are many floats that are rendered incorrectly by the JDK. 176 While the renderings correctly round back to the original value, 177 they are longer than needed or are not the closest decimal to the float. 178 Here are just a very few examples. 179 */ 180 private static final String[] Anomalies = { 181 // JDK renders these longer than needed. 182 "1.1754944E-38", "2.2E-44", 183 "1.0E16", "2.0E16", "3.0E16", "5.0E16", "3.0E17", 184 "3.2E18", "3.7E18", "3.7E16", "3.72E17", 185 186 // JDK does not render this as the closest. 187 "9.9E-44", 188 }; 189 190 private static void testSomeAnomalies() { 191 for (String dec : Anomalies) { 192 toDec(parseFloat(dec)); 193 } 194 } 195 196 /* 197 Values are from 198 Paxson V, "A Program for Testing IEEE Decimal-Binary Conversion" 199 tables 16 and 17 200 */ 201 private static final float[] PaxsonSignificands = { 202 12_676_506, 203 15_445_013, 204 13_734_123, 205 12_428_269, 206 12_676_506, 207 15_334_037, 208 11_518_287, 209 12_584_953, 210 15_961_084, 211 14_915_817, 212 10_845_484, 213 16_431_059, 214 215 16_093_626, 216 9_983_778, 217 12_745_034, 218 12_706_553, 219 11_005_028, 220 15_059_547, 221 16_015_691, 222 8_667_859, 223 14_855_922, 224 14_855_922, 225 10_144_164, 226 13_248_074, 227 }; 228 229 private static final int[] PaxsonExponents = { 230 -102, 231 -103, 232 86, 233 -138, 234 -130, 235 -146, 236 -41, 237 -145, 238 -125, 239 -146, 240 -102, 241 -61, 242 243 69, 244 25, 245 104, 246 72, 247 45, 248 71, 249 -99, 250 56, 251 -82, 252 -83, 253 -110, 254 95, 255 }; 256 257 private static void testPaxson() { 258 for (int i = 0; i < PaxsonSignificands.length; ++i) { 259 toDec(scalb(PaxsonSignificands[i], PaxsonExponents[i])); 260 } 261 } 262 263 /* 264 Tests all positive integers below 2^23. 265 These are all exact floats and exercise the fast path. 266 */ 267 private static void testInts() { 268 for (int i = 1; i < 1 << P - 1; ++i) { 269 toDec(i); 270 } 271 } 272 273 /* 274 Random floats over the whole range. 275 */ 276 private static void testRandom(int randomCount, Random r) { 277 for (int i = 0; i < randomCount; ++i) { 278 toDec(intBitsToFloat(r.nextInt())); 279 } 280 } 281 282 private static void testConstants() { 283 assertTrue(precision() == P, "P"); 284 assertTrue(flog10pow2(P) + 2 == H, "H"); 285 assertTrue(e(MIN_VALUE) == MIN_EXP, "MIN_EXP"); 286 assertTrue(e(MAX_VALUE) == MAX_EXP, "MAX_EXP"); 287 } 288 289 private static int precision() { 290 /* 291 Given precision P, the floating point value 3 has the bits 292 0e...e10...0 293 where there are exactly P - 2 trailing zeroes. 294 */ 295 return numberOfTrailingZeros(floatToRawIntBits(3)) + 2; 296 } 297 298 /* 299 All, really all, 2^32 possible floats. Takes between 90 and 120 minutes. 300 */ 301 public static void testAll() { 302 for (long bits = Integer.MIN_VALUE; bits <= Integer.MAX_VALUE; ++bits) { 303 toDec(intBitsToFloat((int) bits)); 304 } 305 } 306 307 /* 308 All 2^31 positive floats. 309 */ 310 public static void testPositive() { 311 for (long bits = 0; bits <= Integer.MAX_VALUE; ++bits) { 312 toDec(intBitsToFloat((int) bits)); 313 } 314 } 315 316 public static void test(int randomCount, Random r) { 317 testConstants(); 318 testExtremeValues(); 319 testSomeAnomalies(); 320 testPowersOf2(); 321 testPowersOf10(); 322 testPaxson(); 323 testInts(); 324 testRandom(randomCount, r); 325 } 326 327 }