1 /*
   2  * Copyright 2018-2020 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.StrictMath.scalb;
  31 import static jdk.internal.math.MathUtils.flog10pow2;
  32 
  33 public class FloatToDecimalChecker extends ToDecimalChecker {
  34 
  35     private static final int P =
  36             numberOfTrailingZeros(floatToRawIntBits(3)) + 2;
  37     private static final int W = (SIZE - 1) - (P - 1);
  38     private static final int Q_MIN = (-1 << W - 1) - P + 3;
  39     private static final int Q_MAX = (1 << W - 1) - P;
  40     private static final int C_MIN = 1 << P - 1;
  41     private static final int C_MAX = (1 << P) - 1;
  42 
  43     private static final int K_MIN = flog10pow2(Q_MIN);
  44     private static final int K_MAX = flog10pow2(Q_MAX);
  45     private static final int H = flog10pow2(P) + 2;
  46 
  47     private static final float MIN_VALUE = scalb(1.0f, Q_MIN);
  48     private static final float MIN_NORMAL = scalb((float) C_MIN, Q_MIN);
  49     private static final float MAX_VALUE = scalb((float) C_MAX, Q_MAX);
  50 
  51     private static final int E_MIN = e(MIN_VALUE);
  52     private static final int E_MAX = e(MAX_VALUE);
  53 
  54     private static final long C_TINY = cTiny(Q_MIN, K_MIN);
  55 
  56     private float v;
  57     private final int originalBits;
  58 
  59     private FloatToDecimalChecker(float v, String s) {
  60         super(s);
  61         this.v = v;
  62         originalBits = floatToRawIntBits(v);
  63     }
  64 
  65     @Override
  66     BigDecimal toBigDecimal() {
  67         return new BigDecimal(v);
  68     }
  69 
  70     @Override
  71     boolean recovers(BigDecimal b) {
  72         return b.floatValue() == v;
  73     }
  74 
  75     @Override
  76     String hexBits() {
  77         return String.format("0x%01X__%02X__%02X_%04X",
  78                 (originalBits >>> 31) & 0x1,
  79                 (originalBits >>> 23) & 0xFF,
  80                 (originalBits >>> 16) & 0x7F,
  81                 originalBits & 0xFFFF);
  82     }
  83 
  84     @Override
  85     boolean recovers(String s) {
  86         return parseFloat(s) == v;
  87     }
  88 
  89     @Override
  90     int minExp() {
  91         return E_MIN;
  92     }
  93 
  94     @Override
  95     int maxExp() {
  96         return E_MAX;
  97     }
  98 
  99     @Override
 100     int maxLen10() {
 101         return H;
 102     }
 103 
 104     @Override
 105     boolean isZero() {
 106         return v == 0;
 107     }
 108 
 109     @Override
 110     boolean isInfinity() {
 111         return v == POSITIVE_INFINITY;
 112     }
 113 
 114     @Override
 115     void negate() {
 116         v = -v;
 117     }
 118 
 119     @Override
 120     boolean isNegative() {
 121         return originalBits < 0;
 122     }
 123 
 124     @Override
 125     boolean isNaN() {
 126         return Float.isNaN(v);
 127     }
 128 
 129     private static void toDec(float v) {
 130 //        String s = Float.toString(v);
 131         String s = FloatToDecimal.toString(v);
 132         new FloatToDecimalChecker(v, s).assertTrue();
 133     }
 134 
 135     /*
 136     MIN_NORMAL is incorrectly rendered by the JDK.
 137      */
 138     private static void testExtremeValues() {
 139         toDec(NEGATIVE_INFINITY);
 140         toDec(-MAX_VALUE);
 141         toDec(-MIN_NORMAL);
 142         toDec(-MIN_VALUE);
 143         toDec(-0.0f);
 144         toDec(0.0f);
 145         toDec(MIN_VALUE);
 146         toDec(MIN_NORMAL);
 147         toDec(MAX_VALUE);
 148         toDec(POSITIVE_INFINITY);
 149         toDec(NaN);
 150 
 151         /*
 152         Quiet NaNs have the most significant bit of the mantissa as 1,
 153         while signaling NaNs have it as 0.
 154         Exercise 4 combinations of quiet/signaling NaNs and
 155         "positive/negative" NaNs.
 156          */
 157         toDec(intBitsToFloat(0x7FC0_0001));
 158         toDec(intBitsToFloat(0x7F80_0001));
 159         toDec(intBitsToFloat(0xFFC0_0001));
 160         toDec(intBitsToFloat(0xFF80_0001));
 161 
 162         /*
 163         All values treated specially by Schubfach
 164          */
 165         for (int c = 1; c < C_TINY; ++c) {
 166             toDec(c * MIN_VALUE);
 167         }
 168     }
 169 
 170     /*
 171     Some "powers of 10" are incorrectly rendered by the JDK.
 172     The rendering is either too long or it is not the closest decimal.
 173      */
 174     private static void testPowersOf10() {
 175         for (int e = E_MIN; e <= E_MAX; ++e) {
 176             toDec(parseFloat("1e" + e));
 177         }
 178     }
 179 
 180     /*
 181     Many powers of 2 are incorrectly rendered by the JDK.
 182     The rendering is either too long or it is not the closest decimal.
 183      */
 184     private static void testPowersOf2() {
 185         for (float v = MIN_VALUE; v <= MAX_VALUE; v *= 2) {
 186             toDec(v);
 187         }
 188     }
 189 
 190     /*
 191     There are tons of doubles that are rendered incorrectly by the JDK.
 192     While the renderings correctly round back to the original value,
 193     they are longer than needed or are not the closest decimal to the double.
 194     Here are just a very few examples.
 195      */
 196     private static final String[] Anomalies = {
 197             // JDK renders these longer than needed.
 198             "1.1754944E-38", "2.2E-44",
 199             "1.0E16", "2.0E16", "3.0E16", "5.0E16", "3.0E17",
 200             "3.2E18", "3.7E18", "3.7E16", "3.72E17",
 201 
 202             // JDK does not render this as the closest.
 203             "9.9E-44",
 204     };
 205 
 206     private static void testSomeAnomalies() {
 207         for (String dec : Anomalies) {
 208             toDec(parseFloat(dec));
 209         }
 210     }
 211 
 212     /*
 213     Values are from
 214     Paxson V, "A Program for Testing IEEE Decimal-Binary Conversion"
 215     tables 16 and 17
 216      */
 217     private static final float[] PaxsonSignificands = {
 218             12_676_506,
 219             15_445_013,
 220             13_734_123,
 221             12_428_269,
 222             12_676_506,
 223             15_334_037,
 224             11_518_287,
 225             12_584_953,
 226             15_961_084,
 227             14_915_817,
 228             10_845_484,
 229             16_431_059,
 230 
 231             16_093_626,
 232              9_983_778,
 233             12_745_034,
 234             12_706_553,
 235             11_005_028,
 236             15_059_547,
 237             16_015_691,
 238              8_667_859,
 239             14_855_922,
 240             14_855_922,
 241             10_144_164,
 242             13_248_074,
 243     };
 244 
 245     private static final int[] PaxsonExponents = {
 246             -102,
 247             -103,
 248               86,
 249             -138,
 250             -130,
 251             -146,
 252              -41,
 253             -145,
 254             -125,
 255             -146,
 256             -102,
 257              -61,
 258 
 259               69,
 260               25,
 261              104,
 262               72,
 263               45,
 264               71,
 265              -99,
 266               56,
 267              -82,
 268              -83,
 269             -110,
 270               95,
 271     };
 272 
 273     private static void testPaxson() {
 274         for (int i = 0; i < PaxsonSignificands.length; ++i) {
 275             toDec(scalb(PaxsonSignificands[i], PaxsonExponents[i]));
 276         }
 277     }
 278 
 279     /*
 280     Tests all positive integers below 2^23.
 281     These are all exact floats and exercise the fast path.
 282      */
 283     private static void testInts() {
 284         for (int i = 1; i < 1 << P - 1; ++i) {
 285             toDec(i);
 286         }
 287     }
 288 
 289     /*
 290     Random floats over the whole range.
 291      */
 292     private static void testRandom(int randomCount, Random r) {
 293         for (int i = 0; i < randomCount; ++i) {
 294             toDec(intBitsToFloat(r.nextInt()));
 295         }
 296     }
 297 
 298     /*
 299     All, really all, 2^32 possible floats. Takes between 90 and 120 minutes.
 300      */
 301     public static void testAll() {
 302         // Avoid wrapping around Integer.MAX_VALUE
 303         int bits = Integer.MIN_VALUE;
 304         for (; bits < Integer.MAX_VALUE; ++bits) {
 305             toDec(intBitsToFloat(bits));
 306         }
 307         toDec(intBitsToFloat(bits));
 308     }
 309 
 310     /*
 311     All positive 2^31 floats.
 312      */
 313     public static void testPositive() {
 314         // Avoid wrapping around Integer.MAX_VALUE
 315         int bits = 0;
 316         for (; bits < Integer.MAX_VALUE; ++bits) {
 317             toDec(intBitsToFloat(bits));
 318         }
 319         toDec(intBitsToFloat(bits));
 320     }
 321 
 322     private static void testConstants() {
 323         assertTrue(P == FloatToDecimal.P, "P");
 324         assertTrue((long) (float) C_MIN == C_MIN, "C_MIN");
 325         assertTrue((long) (float) C_MAX == C_MAX, "C_MAX");
 326         assertTrue(MIN_VALUE == Float.MIN_VALUE, "MIN_VALUE");
 327         assertTrue(MIN_NORMAL == Float.MIN_NORMAL, "MIN_NORMAL");
 328         assertTrue(MAX_VALUE == Float.MAX_VALUE, "MAX_VALUE");
 329 
 330         assertTrue(Q_MIN == FloatToDecimal.Q_MIN, "Q_MIN");
 331         assertTrue(Q_MAX == FloatToDecimal.Q_MAX, "Q_MAX");
 332 
 333         assertTrue(K_MIN == FloatToDecimal.K_MIN, "K_MIN");
 334         assertTrue(K_MAX == FloatToDecimal.K_MAX, "K_MAX");
 335         assertTrue(H == FloatToDecimal.H, "H");
 336 
 337         assertTrue(E_MIN == FloatToDecimal.E_MIN, "E_MIN");
 338         assertTrue(E_MAX == FloatToDecimal.E_MAX, "E_MAX");
 339         assertTrue(C_TINY == FloatToDecimal.C_TINY, "C_TINY");
 340     }
 341 
 342     public static void test(int randomCount, Random r) {
 343         testConstants();
 344         testExtremeValues();
 345         testSomeAnomalies();
 346         testPowersOf2();
 347         testPowersOf10();
 348         testPaxson();
 349         testInts();
 350         testRandom(randomCount, r);
 351     }
 352 
 353     public static void main(String[] args) {
 354         if (args.length > 0 && args[0].equals("all")) {
 355             testAll();
 356             return;
 357         }
 358         if (args.length > 0 && args[0].equals("positive")) {
 359             testPositive();
 360             return;
 361         }
 362         test(1_000_000, new Random());
 363     }
 364 
 365 }