1 /*
   2  * Copyright (c) 2018, Raffaello Giulietti. 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  * This particular file is subject to the "Classpath" exception as provided
   9  * in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  */
  21 
  22 package jdk.internal.math;
  23 
  24 import static java.lang.Float.*;
  25 import static java.lang.Long.numberOfLeadingZeros;
  26 import static java.lang.Math.multiplyHigh;
  27 import static jdk.internal.math.MathUtils.*;
  28 
  29 /**
  30  * This class exposes a method to render a {@code float} as a string.
  31 
  32  * @author Raffaello Giulietti
  33  */
  34 final public class FloatToDecimal {
  35 
  36     // Precision of normal values in bits.
  37     private static final int P = 24;
  38 
  39     // Length in bits of the exponent field.
  40     private static final int W = (Float.SIZE - 1) - (P - 1);
  41 
  42     // Minimum value of the exponent.
  43     private static final int Q_MIN = (-1 << W - 1) - P + 3;
  44 
  45     // Minimum value of the coefficient of a normal value.
  46     private static final int C_MIN = 1 << P - 1;
  47 
  48     // Mask to extract the IEEE 754-2008 biased exponent.
  49     private static final int BQ_MASK = (1 << W) - 1;
  50 
  51     // Mask to extract the IEEE 754-2008 fraction bits.
  52     private static final int T_MASK = (1 << P - 1) - 1;
  53 
  54     // H = min {n integer | 10^(n-1) > 2^P}
  55     private static final int H = 9;
  56 
  57     // used in the left-to-right extraction of the digits
  58     private static final int LTR = 28;
  59     private static final int MASK_LTR = (1 << LTR) - 1;
  60 
  61     private static final long MASK_63 = (1L << Long.SIZE - 1) - 1;
  62 
  63     // for thread-safety, each thread gets its own instance of this class
  64     private static final ThreadLocal<FloatToDecimal> threadLocal =
  65             ThreadLocal.withInitial(FloatToDecimal::new);
  66 
  67     /*
  68     Room for the longer of the forms
  69         -ddddd.dddd         H + 2 characters
  70         -0.00ddddddddd      H + 5 characters
  71         -d.ddddddddE-ee     H + 6 characters
  72     where there are H digits d
  73      */
  74     private final char[] buf = new char[H + 6];
  75 
  76     // index of rightmost valid character
  77     private int index;
  78 
  79     private FloatToDecimal() {
  80     }
  81 
  82     /*
  83     See Float::toString for javadoc.
  84      */
  85     public static String toString(float v) {
  86         return threadLocalInstance().toDecimal(v);
  87     }
  88 
  89     private static FloatToDecimal threadLocalInstance() {
  90         return threadLocal.get();
  91     }
  92 
  93     private String toDecimal(float v) {
  94         int bits = floatToRawIntBits(v);
  95         int bq = (bits >>> P - 1) & BQ_MASK;
  96         if (bq < BQ_MASK) {
  97             index = -1;
  98             if (bits < 0) {
  99                 append('-');
 100             }
 101             if (bq > 0) {
 102                 return toDecimal(Q_MIN - 1 + bq, C_MIN | bits & T_MASK);
 103             }
 104             if (bits == 0x0000_0000) {
 105                 return "0.0";
 106             }
 107             if (bits == 0x8000_0000) {
 108                 return "-0.0";
 109             }
 110             return toDecimal(Q_MIN, bits & T_MASK);
 111         }
 112         if (v != v) {
 113             return "NaN";
 114         }
 115         if (v == POSITIVE_INFINITY) {
 116             return "Infinity";
 117         }
 118         return "-Infinity";
 119     }
 120 
 121     // Let v = c * 2^q be the absolute value of the original float. Renders v.
 122     private String toDecimal(int q, int c) {
 123         /*
 124         out = 0, if the boundaries of the rounding interval are included
 125         out = 1, if they are excluded
 126         d = 1 for even, d = 2 for uneven spacing around v.
 127         v = cb * 2^qb
 128         predecessor(v) = cbl * 2^qb
 129         successor(v) = cbr * 2^qb
 130          */
 131         int out = c & 0x1;
 132 
 133         long cb;
 134         long cbr;
 135         long cbl;
 136         int k;
 137         int ord2alpha;
 138         if (c != C_MIN | q == Q_MIN) {
 139             cb = c << 1;
 140             cbr = cb + 1;
 141             k = flog10pow2(q);
 142             ord2alpha = q + flog2pow10(-k) + 1;
 143         } else {
 144             cb = c << 2;
 145             cbr = cb + 2;
 146             k = flog10threeQuartersPow2(q);
 147             ord2alpha = q + flog2pow10(-k);
 148         }
 149         cbl = cb - 1;
 150         long mask = (1L << 63 - ord2alpha) - 1;
 151         long threshold = 1L << 62 - ord2alpha;
 152 
 153         // pow5 = pow51*2^63 + pow50
 154         long pow51 = ceilPow5dHigh(-k);
 155         long pow50 = ceilPow5dLow(-k);
 156 
 157         // p = p2*2^126 + p1*2^63 + p0 and p = pow5 * cb
 158         long x0 = pow50 * cb;
 159         long x1 = multiplyHigh(pow50, cb);
 160         long y0 = pow51 * cb;
 161         long y1 = multiplyHigh(pow51, cb);
 162         long z = (x1 << 1 | x0 >>> 63) + (y0 & MASK_63);
 163         long p0 = x0 & MASK_63;
 164         long p1 = z & MASK_63;
 165         long p2 = (y1 << 1 | y0 >>> 63) + (z >>> 63);
 166         long vn = p2 << 1 + ord2alpha | p1 >>> 62 - ord2alpha;
 167         if ((p1 & mask) != 0 || p0 >= threshold) {
 168             vn |= 1;
 169         }
 170 
 171         // Similarly as above, with p = pow5 * cbl
 172         x0 = pow50 * cbl;
 173         x1 = multiplyHigh(pow50, cbl);
 174         y0 = pow51 * cbl;
 175         y1 = multiplyHigh(pow51, cbl);
 176         z = (x1 << 1 | x0 >>> 63) + (y0 & MASK_63);
 177         p0 = x0 & MASK_63;
 178         p1 = z & MASK_63;
 179         p2 = (y1 << 1 | y0 >>> 63) + (z >>> 63);
 180         long vnl = p2 << ord2alpha | p1 >>> 63 - ord2alpha;
 181         if ((p1 & mask) != 0 || p0 >= threshold) {
 182             vnl |= 1;
 183         }
 184 
 185         // Similarly as above, with p = pow5 * cbr
 186         x0 = pow50 * cbr;
 187         x1 = multiplyHigh(pow50, cbr);
 188         y0 = pow51 * cbr;
 189         y1 = multiplyHigh(pow51, cbr);
 190         z = (x1 << 1 | x0 >>> 63) + (y0 & MASK_63);
 191         p0 = x0 & MASK_63;
 192         p1 = z & MASK_63;
 193         p2 = (y1 << 1 | y0 >>> 63) + (z >>> 63);
 194         long vnr = p2 << ord2alpha | p1 >>> 63 - ord2alpha;
 195         if ((p1 & mask) != 0 || p0 >= threshold) {
 196             vnr |= 1;
 197         }
 198 
 199         long s = vn >> 2;
 200         if (s >= 100) {
 201             long s10 = s - s % 10;
 202             long t10 = s10 + 10;
 203             boolean uin10 = vnl + out <= s10 << 1;
 204             boolean win10 = (t10 << 1) + out <= vnr;
 205             if (uin10 | win10) {
 206                 if (!win10) {
 207                     return toChars(s10, k);
 208                 }
 209                 if (!uin10) {
 210                     return toChars(t10, k);
 211                 }
 212             }
 213         } else if (s < 10) {
 214             /*
 215             Special cases that need to be made artificially longer to meet
 216             the specification
 217              */
 218             switch ((int) s) {
 219                 case 1: return toChars(14, -46); // 1.4 * 10^-45
 220                 case 2: return toChars(28, -46); // 2.8 * 10^-45
 221                 case 4: return toChars(42, -46); // 4.2 * 10^-45
 222                 case 5: return toChars(56, -46); // 5.6 * 10^-45
 223                 case 7: return toChars(70, -46); // 7.0 * 10^-45
 224                 case 8: return toChars(84, -46); // 8.4 * 10^-45
 225                 case 9: return toChars(98, -46); // 9.8 * 10^-45
 226             }
 227         }
 228         long t = s + 1;
 229         boolean uin = vnl + out <= s << 1;
 230         boolean win = (t << 1) + out <= vnr;
 231         if (!win) {
 232             return toChars(s, k);
 233         }
 234         if (!uin) {
 235             return toChars(t, k);
 236         }
 237         long cmp = vn - (s + t << 1);
 238         if (cmp < 0) {
 239             return toChars(s, k);
 240         }
 241         if (cmp > 0) {
 242             return toChars(t, k);
 243         }
 244         if ((s & 1) == 0) {
 245             return toChars(s, k);
 246         }
 247         return toChars(t, k);
 248     }
 249 
 250     /*
 251     The method formats the number f * 10^e
 252 
 253     Division is avoided altogether by replacing it with multiplications
 254     and shifts. This has a noticeable impact on performance.
 255     For more in-depth readings, see for example
 256     * Moeller & Granlund, "Improved division by invariant integers"
 257     * ridiculous_fish, "Labor of Division (Episode III): Faster Unsigned
 258         Division by Constants"
 259 
 260     Also, once the quotient is known, the remainder is computed indirectly.
 261      */
 262     private String toChars(long f, int e) {
 263         // Normalize f to lie in the f-independent interval [10^(H-1), 10^H)
 264         int len10 = flog10pow2(Long.SIZE - numberOfLeadingZeros(f));
 265         if (f >= pow10[len10]) {
 266             len10 += 1;
 267         }
 268         // 10^(len10-1) <= f < 10^len10
 269         f *= pow10[H - len10];
 270         e += len10;
 271 
 272         /*
 273         Split the H = 9 digits of f into:
 274             h = the most significant digit of f
 275             l = the last 8, least significant digits of f
 276 
 277         Pictorially, the selected decimal to format as String is
 278             0.hllllllll * 10^e
 279         Depending on the value of e, plain or computerized scientific notation
 280         is used.
 281          */
 282         int h = (int) (f * 1_441_151_881L >>> 57);
 283         int l = (int) (f - 100_000_000 * h);
 284 
 285         /*
 286         The left-to-right digits generation in toChars_* is inspired by
 287         * Bouvier & Zimmermann, "Division-Free Binary-to-Decimal Conversion"
 288          */
 289         if (0 < e && e <= 7) {
 290             return toChars_1(h, l, e);
 291         }
 292         if (-3 < e && e <= 0) {
 293             return toChars_2(h, l, e);
 294         }
 295         return toChars_3(h, l, e);
 296     }
 297 
 298     // 0 < e <= 7: plain format without leading zeroes.
 299     private String toChars_1(int h, int l, int e) {
 300         appendDigit(h);
 301         // y = (l + 1) * 2^LTR / 100_000_000 - 1;
 302         int y = (int) (multiplyHigh(
 303                 (long) (l + 1) << LTR,
 304                 48_357_032_784_585_167L) >>> 18) - 1;
 305         int t;
 306         int i = 1;
 307         for (; i < e; ++i) {
 308             t = 10 * y;
 309             appendDigit(t >>> LTR);
 310             y = t & MASK_LTR;
 311         }
 312         append('.');
 313         for (; i <= 8; ++i) {
 314             t = 10 * y;
 315             appendDigit(t >>> LTR);
 316             y = t & MASK_LTR;
 317         }
 318         removeTrailingZeroes();
 319         return charsToString();
 320     }
 321 
 322     // -3 < e <= 0: plain format with leading zeroes.
 323     private String toChars_2(int h, int l, int e) {
 324         appendDigit(0);
 325         append('.');
 326         for (; e < 0; ++e) {
 327           appendDigit(0);
 328         }
 329         appendDigit(h);
 330         append8Digits(l);
 331         removeTrailingZeroes();
 332         return charsToString();
 333     }
 334 
 335     // -3 >= e | e > 7: computerized scientific notation
 336     private String toChars_3(int h, int l, int e) {
 337         appendDigit(h);
 338         append('.');
 339         append8Digits(l);
 340         removeTrailingZeroes();
 341         exponent(e - 1);
 342         return charsToString();
 343     }
 344 
 345     private void append8Digits(int v) {
 346         // y = (v + 1) * 2^LTR / 100_000_000 - 1;
 347         int y = (int) (multiplyHigh((long) (v + 1) << LTR,
 348                 48_357_032_784_585_167L) >>> 18) - 1;
 349         for (int i = 0; i < 8; ++i) {
 350             int t = 10 * y;
 351             appendDigit(t >>> LTR);
 352             y = t & MASK_LTR;
 353         }
 354     }
 355 
 356     private void removeTrailingZeroes() {
 357         while (buf[index] == '0') {
 358             --index;
 359         }
 360         if (buf[index] == '.') {
 361             ++index;
 362         }
 363     }
 364 
 365     private void exponent(int e) {
 366         append('E');
 367         if (e < 0) {
 368             append('-');
 369             e = -e;
 370         }
 371         if (e < 10) {
 372             appendDigit(e);
 373             return;
 374         }
 375         // d = e / 10
 376         int d = e * 205 >>> 11;
 377         appendDigit(d);
 378         appendDigit(e - 10 * d);
 379     }
 380 
 381     private void append(int c) {
 382         buf[++index] = (char) c;
 383     }
 384 
 385     private void appendDigit(int d) {
 386         buf[++index] = (char) ('0' + d);
 387     }
 388 
 389     private String charsToString() {
 390         return new String(buf, 0, index + 1);
 391     }
 392 
 393 }