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 }