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.io.IOException;
  26 
  27 import static java.lang.Double.*;
  28 import static java.lang.Long.*;
  29 import static java.lang.Math.multiplyHigh;
  30 import static jdk.internal.math.MathUtils.*;
  31 
  32 /**
  33  * This class exposes a method to render a {@code double} as a string.
  34  *
  35  * @author Raffaello Giulietti
  36  */
  37 final public class DoubleToDecimal {
  38     /*
  39     For full details about this code see the following references:
  40 
  41     [1] Giulietti, "The Schubfach way to render doubles",
  42         https://drive.google.com/open?id=1luHhyQF9zKlM8yJ1nebU0OgVYhfC6CBN
  43 
  44     [2] IEEE Computer Society, "IEEE Standard for Floating-Point Arithmetic"
  45 
  46     [3] Bouvier & Zimmermann, "Division-Free Binary-to-Decimal Conversion"
  47 
  48     Divisions are avoided altogether for the benefit of those architectures
  49     that do not provide specific machine instructions or where they are slow.
  50     This is discussed in section 10 of [1].
  51      */
  52 
  53     // The precision in bits.
  54     static final int P = 53;
  55 
  56     // Exponent width in bits.
  57     private static final int W = (Double.SIZE - 1) - (P - 1);
  58 
  59     // Minimum value of the exponent: -(2^(W-1)) - P + 3.
  60     static final int Q_MIN = (-1 << W - 1) - P + 3;
  61 
  62     // Maximum value of the exponent: 2^(W-1) - P.
  63     static final int Q_MAX = (1 << W - 1) - P;
  64 
  65     // 10^(E_MIN - 1) <= MIN_VALUE < 10^E_MIN
  66     static final int E_MIN = -323;
  67 
  68     // 10^(E_MAX - 1) <= MAX_VALUE < 10^E_MAX
  69     static final int E_MAX = 309;
  70 
  71     // Threshold to detect tiny values, as in section 8.1.1 of [1]
  72     static final long C_TINY = 3;
  73 
  74     // The minimum and maximum k, as in section 8 of [1]
  75     static final int K_MIN = -324;
  76     static final int K_MAX = 292;
  77 
  78     // H is as in section 8 of [1].
  79     static final int H = 17;
  80 
  81     // Minimum value of the significand of a normal value: 2^(P-1).
  82     private static final long C_MIN = 1L << P - 1;
  83 
  84     // Mask to extract the biased exponent.
  85     private static final int BQ_MASK = (1 << W) - 1;
  86 
  87     // Mask to extract the fraction bits.
  88     private static final long T_MASK = (1L << P - 1) - 1;
  89 
  90     // Used in rop().
  91     private static final long MASK_63 = (1L << 63) - 1;
  92 
  93     // Used for left-to-tight digit extraction.
  94     private static final int MASK_28 = (1 << 28) - 1;
  95 
  96     private static final int NON_SPECIAL = 0;
  97     private static final int PLUS_ZERO = 1;
  98     private static final int MINUS_ZERO = 2;
  99     private static final int PLUS_INF = 3;
 100     private static final int MINUS_INF = 4;
 101     private static final int NAN = 5;
 102 
 103     // For thread-safety, each thread gets its own instance of this class.
 104     private static final ThreadLocal<DoubleToDecimal> threadLocal =
 105             ThreadLocal.withInitial(DoubleToDecimal::new);
 106 
 107     /*
 108     Room for the longer of the forms
 109         -ddddd.dddddddddddd         H + 2 characters
 110         -0.00ddddddddddddddddd      H + 5 characters
 111         -d.ddddddddddddddddE-eee    H + 7 characters
 112     where there are H digits d
 113      */
 114     public final int MAX_CHARS = H + 7;
 115 
 116     // Numerical results are created here...
 117     private final byte[] bytes = new byte[MAX_CHARS];
 118 
 119     // ... and copied here in appendTo()
 120     private final char[] chars = new char[MAX_CHARS];
 121 
 122     // Index into bytes of rightmost valid character.
 123     private int index;
 124 
 125     private DoubleToDecimal() {
 126     }
 127 
 128     /**
 129      * Returns a string rendering of the {@code double} argument.
 130      *
 131      * <p>The characters of the result are all drawn from the ASCII set.
 132      * <ul>
 133      * <li> Any NaN, whether quiet or signaling, is rendered as
 134      * {@code "NaN"}, regardless of the sign bit.
 135      * <li> The infinities +&infin; and -&infin; are rendered as
 136      * {@code "Infinity"} and {@code "-Infinity"}, respectively.
 137      * <li> The positive and negative zeroes are rendered as
 138      * {@code "0.0"} and {@code "-0.0"}, respectively.
 139      * <li> A finite negative {@code v} is rendered as the sign
 140      * '{@code -}' followed by the rendering of the magnitude -{@code v}.
 141      * <li> A finite positive {@code v} is rendered in two stages:
 142      * <ul>
 143      * <li> <em>Selection of a decimal</em>: A well-defined
 144      * decimal <i>d</i><sub><code>v</code></sub> is selected
 145      * to represent {@code v}.
 146      * <li> <em>Formatting as a string</em>: The decimal
 147      * <i>d</i><sub><code>v</code></sub> is formatted as a string,
 148      * either in plain or in computerized scientific notation,
 149      * depending on its value.
 150      * </ul>
 151      * </ul>
 152      *
 153      * <p>A <em>decimal</em> is a number of the form
 154      * <i>d</i>&times;10<sup><i>i</i></sup>
 155      * for some (unique) integers <i>d</i> &gt; 0 and <i>i</i> such that
 156      * <i>d</i> is not a multiple of 10.
 157      * These integers are the <em>significand</em> and
 158      * the <em>exponent</em>, respectively, of the decimal.
 159      * The <em>length</em> of the decimal is the (unique)
 160      * integer <i>n</i> meeting
 161      * 10<sup><i>n</i>-1</sup> &le; <i>d</i> &lt; 10<sup><i>n</i></sup>.
 162      *
 163      * <p>The decimal <i>d</i><sub><code>v</code></sub>
 164      * for a finite positive {@code v} is defined as follows:
 165      * <ul>
 166      * <li>Let <i>R</i> be the set of all decimals that round to {@code v}
 167      * according to the usual round-to-closest rule of
 168      * IEEE 754 floating-point arithmetic.
 169      * <li>Let <i>m</i> be the minimal length over all decimals in <i>R</i>.
 170      * <li>When <i>m</i> &ge; 2, let <i>T</i> be the set of all decimals
 171      * in <i>R</i> with length <i>m</i>.
 172      * Otherwise, let <i>T</i> be the set of all decimals
 173      * in <i>R</i> with length 1 or 2.
 174      * <li>Define <i>d</i><sub><code>v</code></sub> as
 175      * the decimal in <i>T</i> that is closest to {@code v}.
 176      * Or if there are two such decimals in <i>T</i>,
 177      * select the one with the even significand (there is exactly one).
 178      * </ul>
 179      *
 180      * <p>The (uniquely) selected decimal <i>d</i><sub><code>v</code></sub>
 181      * is then formatted.
 182      *
 183      * <p>Let <i>d</i>, <i>i</i> and <i>n</i> be the significand, exponent and
 184      * length of <i>d</i><sub><code>v</code></sub>, respectively.
 185      * Further, let <i>e</i> = <i>n</i> + <i>i</i> - 1 and let
 186      * <i>d</i><sub>1</sub>&hellip;<i>d</i><sub><i>n</i></sub>
 187      * be the usual decimal expansion of the significand.
 188      * Note that <i>d</i><sub>1</sub> &ne; 0 &ne; <i>d</i><sub><i>n</i></sub>.
 189      * <ul>
 190      * <li>Case -3 &le; <i>e</i> &lt; 0:
 191      * <i>d</i><sub><code>v</code></sub> is formatted as
 192      * <code>0.0</code>&hellip;<code>0</code><!--
 193      * --><i>d</i><sub>1</sub>&hellip;<i>d</i><sub><i>n</i></sub>,
 194      * where there are exactly -(<i>n</i> + <i>i</i>) zeroes between
 195      * the decimal point and <i>d</i><sub>1</sub>.
 196      * For example, 123 &times; 10<sup>-4</sup> is formatted as
 197      * {@code 0.0123}.
 198      * <li>Case 0 &le; <i>e</i> &lt; 7:
 199      * <ul>
 200      * <li>Subcase <i>i</i> &ge; 0:
 201      * <i>d</i><sub><code>v</code></sub> is formatted as
 202      * <i>d</i><sub>1</sub>&hellip;<i>d</i><sub><i>n</i></sub><!--
 203      * --><code>0</code>&hellip;<code>0.0</code>,
 204      * where there are exactly <i>i</i> zeroes
 205      * between <i>d</i><sub><i>n</i></sub> and the decimal point.
 206      * For example, 123 &times; 10<sup>2</sup> is formatted as
 207      * {@code 12300.0}.
 208      * <li>Subcase <i>i</i> &lt; 0:
 209      * <i>d</i><sub><code>v</code></sub> is formatted as
 210      * <i>d</i><sub>1</sub>&hellip;<!--
 211      * --><i>d</i><sub><i>n</i>+<i>i</i></sub>.<!--
 212      * --><i>d</i><sub><i>n</i>+<i>i</i>+1</sub>&hellip;<!--
 213      * --><i>d</i><sub><i>n</i></sub>.
 214      * There are exactly -<i>i</i> digits to the right of
 215      * the decimal point.
 216      * For example, 123 &times; 10<sup>-1</sup> is formatted as
 217      * {@code 12.3}.
 218      * </ul>
 219      * <li>Case <i>e</i> &lt; -3 or <i>e</i> &ge; 7:
 220      * computerized scientific notation is used to format
 221      * <i>d</i><sub><code>v</code></sub>.
 222      * Here <i>e</i> is formatted as by {@link Integer#toString(int)}.
 223      * <ul>
 224      * <li>Subcase <i>n</i> = 1:
 225      * <i>d</i><sub><code>v</code></sub> is formatted as
 226      * <i>d</i><sub>1</sub><code>.0E</code><i>e</i>.
 227      * For example, 1 &times; 10<sup>23</sup> is formatted as
 228      * {@code 1.0E23}.
 229      * <li>Subcase <i>n</i> &gt; 1:
 230      * <i>d</i><sub><code>v</code></sub> is formatted as
 231      * <i>d</i><sub>1</sub><code>.</code><i>d</i><sub>2</sub><!--
 232      * -->&hellip;<i>d</i><sub><i>n</i></sub><code>E</code><i>e</i>.
 233      * For example, 123 &times; 10<sup>-21</sup> is formatted as
 234      * {@code 1.23E-19}.
 235      * </ul>
 236      * </ul>
 237      *
 238      * @param v the {@code double} to be rendered.
 239      * @return a string rendering of the argument.
 240      */
 241     public static String toString(double v) {
 242         return threadLocalInstance().toDecimalString(v);
 243     }
 244 
 245     /**
 246      * Appends the rendering of the {@code v} to {@code app}.
 247      *
 248      * <p>The outcome is the same as if {@code v} were first
 249      * {@link #toString(double) rendered} and the resulting string were then
 250      * {@link Appendable#append(CharSequence) appended} to {@code app}.
 251      *
 252      * @param v the {@code double} whose rendering is appended.
 253      * @param app the {@link Appendable} to append to.
 254      * @throws IOException If an I/O error occurs
 255      */
 256     public static Appendable appendTo(double v, Appendable app)
 257             throws IOException {
 258         return threadLocalInstance().appendDecimalTo(v, app);
 259     }
 260 
 261     private static DoubleToDecimal threadLocalInstance() {
 262         return threadLocal.get();
 263     }
 264 
 265     private String toDecimalString(double v) {
 266         switch (toDecimal(v)) {
 267             case NON_SPECIAL: return charsToString();
 268             case PLUS_ZERO: return "0.0";
 269             case MINUS_ZERO: return "-0.0";
 270             case PLUS_INF: return "Infinity";
 271             case MINUS_INF: return "-Infinity";
 272             default: return "NaN";
 273         }
 274     }
 275 
 276     private Appendable appendDecimalTo(double v, Appendable app)
 277             throws IOException {
 278         switch (toDecimal(v)) {
 279             case NON_SPECIAL:
 280                 for (int i = 0; i <= index; ++i) {
 281                     chars[i] = (char) bytes[i];
 282                 }
 283                 if (app instanceof StringBuilder) {
 284                     return ((StringBuilder) app).append(chars, 0, index + 1);
 285                 }
 286                 if (app instanceof StringBuffer) {
 287                     return ((StringBuffer) app).append(chars, 0, index + 1);
 288                 }
 289                 for (int i = 0; i <= index; ++i) {
 290                     app.append(chars[i]);
 291                 }
 292                 return app;
 293             case PLUS_ZERO: return app.append("0.0");
 294             case MINUS_ZERO: return app.append("-0.0");
 295             case PLUS_INF: return app.append("Infinity");
 296             case MINUS_INF: return app.append("-Infinity");
 297             default: return app.append("NaN");
 298         }
 299     }
 300 
 301     /*
 302     Returns
 303         PLUS_ZERO       iff v is 0.0
 304         MINUS_ZERO      iff v is -0.0
 305         PLUS_INF        iff v is POSITIVE_INFINITY
 306         MINUS_INF       iff v is NEGATIVE_INFINITY
 307         NAN             iff v is NaN
 308      */
 309     private int toDecimal(double v) {
 310         /*
 311         For full details see references [2] and [1].
 312 
 313         For finite v != 0, determine integers c and q such that
 314             |v| = c 2^q    and
 315             Q_MIN <= q <= Q_MAX    and
 316                 either    2^(P-1) <= c < 2^P                 (normal)
 317                 or        0 < c < 2^(P-1)  and  q = Q_MIN    (subnormal)
 318          */
 319         long bits = doubleToRawLongBits(v);
 320         long t = bits & T_MASK;
 321         int bq = (int) (bits >>> P - 1) & BQ_MASK;
 322         if (bq < BQ_MASK) {
 323             index = -1;
 324             if (bits < 0) {
 325                 append('-');
 326             }
 327             if (bq != 0) {
 328                 // normal value. Here mq = -q
 329                 int mq = -Q_MIN + 1 - bq;
 330                 long c = C_MIN | t;
 331                 // The fast path discussed in section 8.2 of [1].
 332                 if (0 < mq & mq < P) {
 333                     long f = c >> mq;
 334                     if (f << mq == c) {
 335                         return toChars(f, 0);
 336                     }
 337                 }
 338                 return toDecimal(-mq, c, 0);
 339             }
 340             if (t != 0) {
 341                 // subnormal value
 342                 return t < C_TINY
 343                        ? toDecimal(Q_MIN, 10 * t, -1)
 344                        : toDecimal(Q_MIN, t, 0);
 345             }
 346             return bits == 0 ? PLUS_ZERO : MINUS_ZERO;
 347         }
 348         if (t != 0) {
 349             return NAN;
 350         }
 351         return bits > 0 ? PLUS_INF : MINUS_INF;
 352     }
 353 
 354     private int toDecimal(int q, long c, int dk) {
 355         /*
 356         The skeleton corresponds to figure 4 of [1].
 357         The efficient computations are those summarized in figure 7.
 358 
 359         Here's a correspondence between Java names and names in [1],
 360         expressed as approximate LaTeX source code and informally.
 361         Other names are identical.
 362         cb:     \bar{c}     "c-bar"
 363         cbr:    \bar{c}_r   "c-bar-r"
 364         cbl:    \bar{c}_l   "c-bar-l"
 365 
 366         vb:     \bar{v}     "v-bar"
 367         vbr:    \bar{v}_r   "v-bar-r"
 368         vbl:    \bar{v}_l   "v-bar-l"
 369 
 370         rop:    r_o'        "r-o-prime"
 371          */
 372         int out = (int) c & 0x1;
 373         long cb = c << 2;
 374         long cbr = cb + 2;
 375         long cbl;
 376         int k;
 377         /*
 378         flog10pow2(e) = floor(log_10(2^e))
 379         flog10threeQuartersPow2(e) = floor(log_10(3/4 2^e))
 380         flog2pow10(e) = floor(log_2(10^e))
 381          */
 382         if (c != C_MIN | q == Q_MIN) {
 383             // regular spacing
 384             cbl = cb - 2;
 385             k = flog10pow2(q);
 386         } else {
 387             // irregular spacing
 388             cbl = cb - 1;
 389             k = flog10threeQuartersPow2(q);
 390         }
 391         int h = q + flog2pow10(-k) + 2;
 392 
 393         // g1 and g0 are as in section 9.9.3 of [1], so g = g1 2^63 + g0
 394         long g1 = g1(k);
 395         long g0 = g0(k);
 396 
 397         long vb = rop(g1, g0, cb << h);
 398         long vbl = rop(g1, g0, cbl << h);
 399         long vbr = rop(g1, g0, cbr << h);
 400 
 401         long s = vb >> 2;
 402         if (s >= 100) {
 403             /*
 404             For n = 17, m = 1 the table in section 10 of [1] shows
 405                 s' = floor(s / 10) = floor(s 115_292_150_460_684_698 / 2^60)
 406                    = floor(s 115_292_150_460_684_698 2^4 / 2^64)
 407 
 408             sp10 = 10 s'
 409             tp10 = 10 t'
 410             upin    iff    u' = sp10 10^k in Rv
 411             wpin    iff    w' = tp10 10^k in Rv
 412             See section 9.4 of [1].
 413              */
 414             long sp10 = 10 * multiplyHigh(s, 115_292_150_460_684_698L << 4);
 415             long tp10 = sp10 + 10;
 416             boolean upin = vbl + out <= sp10 << 2;
 417             boolean wpin = (tp10 << 2) + out <= vbr;
 418             if (upin != wpin) {
 419                 return toChars(upin ? sp10 : tp10, k);
 420             }
 421         }
 422 
 423         /*
 424         10 <= s < 100    or    s >= 100  and  u', w' not in Rv
 425         uin    iff    u = s 10^k in Rv
 426         win    iff    w = t 10^k in Rv
 427         See section 9.4 of [1].
 428          */
 429         long t = s + 1;
 430         boolean uin = vbl + out <= s << 2;
 431         boolean win = (t << 2) + out <= vbr;
 432         if (uin != win) {
 433             // Exactly one of u or w lies in Rv.
 434             return toChars(uin ? s : t, k + dk);
 435         }
 436         /*
 437         Both u and w lie in Rv: determine the one closest to v.
 438         See section 9.4 of [1].
 439          */
 440         long cmp = vb - (s + t << 1);
 441         return toChars(cmp < 0 || cmp == 0 && (s & 0x1) == 0 ? s : t, k + dk);
 442     }
 443 
 444     /*
 445     Computes rop(cp g 2^(-127)), where g = g1 2^63 + g0
 446     See section 9.10 and figure 5 of [1].
 447      */
 448     private static long rop(long g1, long g0, long cp) {
 449         long x1 = multiplyHigh(g0, cp);
 450         long y0 = g1 * cp;
 451         long y1 = multiplyHigh(g1, cp);
 452         long z = (y0 >>> 1) + x1;
 453         long vbp = y1 + (z >>> 63);
 454         return vbp | (z & MASK_63) + MASK_63 >>> 63;
 455     }
 456 
 457     /*
 458     Formats the decimal f 10^e.
 459      */
 460     private int toChars(long f, int e) {
 461         /*
 462         For details not discussed here see section 10 of [1].
 463 
 464         Determine len such that
 465             10^(len-1) <= f < 10^len
 466          */
 467         int len = flog10pow2(Long.SIZE - numberOfLeadingZeros(f));
 468         if (f >= pow10(len)) {
 469             len += 1;
 470         }
 471 
 472         /*
 473         Let fp and ep be the original f and e, respectively.
 474         Transform f and e to ensure
 475             10^(H-1) <= f < 10^H
 476             fp 10^ep = f 10^(e-H) = 0.f 10^e
 477          */
 478         f *= pow10(H - len);
 479         e += len;
 480 
 481         /*
 482         The toChars?() methods perform left-to-right digits extraction
 483         using ints, provided that the arguments are limited to 8 digits.
 484         Therefore, split the H = 17 digits of f into:
 485             h = the most significant digit of f
 486             m = the next 8 most significant digits of f
 487             l = the last 8, least significant digits of f
 488 
 489         For n = 17, m = 8 the table in section 10 of [1] shows
 490             floor(f / 10^8) = floor(193_428_131_138_340_668 f / 2^84) =
 491             floor(floor(193_428_131_138_340_668 f / 2^64) / 2^20)
 492         and for n = 9, m = 8
 493             floor(hm / 10^8) = floor(1_441_151_881 hm / 2^57)
 494          */
 495         long hm = multiplyHigh(f, 193_428_131_138_340_668L) >>> 20;
 496         int l = (int) (f - 100_000_000L * hm);
 497         int h = (int) (hm * 1_441_151_881L >>> 57);
 498         int m = (int) (hm - 100_000_000 * h);
 499 
 500         if (0 < e && e <= 7) {
 501             return toChars1(h, m, l, e);
 502         }
 503         if (-3 < e && e <= 0) {
 504             return toChars2(h, m, l, e);
 505         }
 506         return toChars3(h, m, l, e);
 507     }
 508 
 509     private int toChars1(int h, int m, int l, int e) {
 510         /*
 511         0 < e <= 7: plain format without leading zeroes.
 512         Left-to-right digits extraction:
 513         algorithm 1 in [3], with b = 10, k = 8, n = 28.
 514          */
 515         appendDigit(h);
 516         int y = y(m);
 517         int t;
 518         int i = 1;
 519         for (; i < e; ++i) {
 520             t = 10 * y;
 521             appendDigit(t >>> 28);
 522             y = t & MASK_28;
 523         }
 524         append('.');
 525         for (; i <= 8; ++i) {
 526             t = 10 * y;
 527             appendDigit(t >>> 28);
 528             y = t & MASK_28;
 529         }
 530         lowDigits(l);
 531         return NON_SPECIAL;
 532     }
 533 
 534     private int toChars2(int h, int m, int l, int e) {
 535         // -3 < e <= 0: plain format with leading zeroes.
 536         appendDigit(0);
 537         append('.');
 538         for (; e < 0; ++e) {
 539             appendDigit(0);
 540         }
 541         appendDigit(h);
 542         append8Digits(m);
 543         lowDigits(l);
 544         return NON_SPECIAL;
 545     }
 546 
 547     private int toChars3(int h, int m, int l, int e) {
 548         // -3 >= e | e > 7: computerized scientific notation
 549         appendDigit(h);
 550         append('.');
 551         append8Digits(m);
 552         lowDigits(l);
 553         exponent(e - 1);
 554         return NON_SPECIAL;
 555     }
 556 
 557     private void lowDigits(int l) {
 558         if (l != 0) {
 559             append8Digits(l);
 560         }
 561         removeTrailingZeroes();
 562     }
 563 
 564     private void append8Digits(int m) {
 565         /*
 566         Left-to-right digits extraction:
 567         algorithm 1 in [3], with b = 10, k = 8, n = 28.
 568          */
 569         int y = y(m);
 570         for (int i = 0; i < 8; ++i) {
 571             int t = 10 * y;
 572             appendDigit(t >>> 28);
 573             y = t & MASK_28;
 574         }
 575     }
 576 
 577     private void removeTrailingZeroes() {
 578         while (bytes[index] == '0') {
 579             --index;
 580         }
 581         // ... but do not remove the one directly to the right of '.'
 582         if (bytes[index] == '.') {
 583             ++index;
 584         }
 585     }
 586 
 587     private int y(int a) {
 588         /*
 589         Algorithm 1 in [3] needs computation of
 590             floor((a + 1) 2^n / b^k) - 1
 591         with a < 10^8, b = 10, k = 8, n = 28.
 592         Noting that
 593             (a + 1) 2^n <= 10^8 2^28 < 10^17
 594         For n = 17, m = 8 the table in section 10 of [1] leads to:
 595          */
 596         return (int) (multiplyHigh(
 597                 (long) (a + 1) << 28,
 598                 193_428_131_138_340_668L) >>> 20) - 1;
 599     }
 600 
 601     private void exponent(int e) {
 602         append('E');
 603         if (e < 0) {
 604             append('-');
 605             e = -e;
 606         }
 607         if (e < 10) {
 608             appendDigit(e);
 609             return;
 610         }
 611         int d;
 612         if (e >= 100) {
 613             /*
 614             For n = 3, m = 2 the table in section 10 of [1] shows
 615                 floor(e / 100) = floor(1_311 e / 2^17)
 616              */
 617             d = e * 1_311 >>> 17;
 618             appendDigit(d);
 619             e -= 100 * d;
 620         }
 621         /*
 622         For n = 2, m = 1 the table in section 10 of [1] shows
 623             floor(e / 10) = floor(103 e / 2^10)
 624          */
 625         d = e * 103 >>> 10;
 626         appendDigit(d);
 627         appendDigit(e - 10 * d);
 628     }
 629 
 630     private void append(int c) {
 631         bytes[++index] = (byte) c;
 632     }
 633 
 634     private void appendDigit(int d) {
 635         bytes[++index] = (byte) ('0' + d);
 636     }
 637 
 638     // Using the deprecated constructor enhances performance.
 639     @SuppressWarnings("deprecation")
 640     private String charsToString() {
 641         return new String(bytes, 0, 0, index + 1);
 642     }
 643 
 644 }