ljx

FORK: LuaJIT with native 5.2 and 5.3 support
git clone https://git.neptards.moe/neptards/ljx.git
Log | Files | Refs | README

lj_strfmt_num.c (20353B)


      1 /*
      2 ** String formatting for floating-point numbers.
      3 ** Copyright (C) 2005-2016 Mike Pall. See Copyright Notice in luajit.h
      4 ** Contributed by Peter Cawley.
      5 */
      6 
      7 #include <stdio.h>
      8 
      9 #define lj_strfmt_num_c
     10 #define LUA_CORE
     11 
     12 #include "lj_obj.h"
     13 #include "lj_buf.h"
     14 #include "lj_str.h"
     15 #include "lj_strfmt.h"
     16 
     17 /* -- Precomputed tables -------------------------------------------------- */
     18 
     19 /* Rescale factors to push the exponent of a number towards zero. */
     20 #define RESCALE_EXPONENTS(P, N) \
     21   P(308), P(289), P(270), P(250), P(231), P(212), P(193), P(173), P(154), \
     22   P(135), P(115), P(96), P(77), P(58), P(38), P(0), P(0), P(0), N(39), N(58), \
     23   N(77), N(96), N(116), N(135), N(154), N(174), N(193), N(212), N(231), \
     24   N(251), N(270), N(289)
     25 
     26 #define ONE_E_P(X) 1e+0 ## X
     27 #define ONE_E_N(X) 1e-0 ## X
     28 static const int16_t rescale_e[] = { RESCALE_EXPONENTS(-, +) };
     29 static const double rescale_n[] = { RESCALE_EXPONENTS(ONE_E_P, ONE_E_N) };
     30 #undef ONE_E_N
     31 #undef ONE_E_P
     32 
     33 /*
     34 ** For p in range -70 through 57, this table encodes pairs (m, e) such that
     35 ** 4*2^p <= (uint8_t)m*10^e, and is the smallest value for which this holds.
     36 */
     37 static const int8_t four_ulp_m_e[] = {
     38   34, -21, 68, -21, 14, -20, 28, -20, 55, -20, 2, -19, 3, -19, 5, -19, 9, -19,
     39   -82, -18, 35, -18, 7, -17, -117, -17, 28, -17, 56, -17, 112, -16, -33, -16,
     40   45, -16, 89, -16, -78, -15, 36, -15, 72, -15, -113, -14, 29, -14, 57, -14,
     41   114, -13, -28, -13, 46, -13, 91, -12, -74, -12, 37, -12, 73, -12, 15, -11, 3,
     42   -11, 59, -11, 2, -10, 3, -10, 5, -10, 1, -9, -69, -9, 38, -9, 75, -9, 15, -7,
     43   3, -7, 6, -7, 12, -6, -17, -7, 48, -7, 96, -7, -65, -6, 39, -6, 77, -6, -103,
     44   -5, 31, -5, 62, -5, 123, -4, -11, -4, 49, -4, 98, -4, -60, -3, 4, -2, 79, -3,
     45   16, -2, 32, -2, 63, -2, 2, -1, 25, 0, 5, 1, 1, 2, 2, 2, 4, 2, 8, 2, 16, 2,
     46   32, 2, 64, 2, -128, 2, 26, 2, 52, 2, 103, 3, -51, 3, 41, 4, 82, 4, -92, 4,
     47   33, 4, 66, 4, -124, 5, 27, 5, 53, 5, 105, 6, 21, 6, 42, 6, 84, 6, 17, 7, 34,
     48   7, 68, 7, 2, 8, 3, 8, 6, 8, 108, 9, -41, 9, 43, 10, 86, 9, -84, 10, 35, 10,
     49   69, 10, -118, 11, 28, 11, 55, 12, 11, 13, 22, 13, 44, 13, 88, 13, -80, 13,
     50   36, 13, 71, 13, -115, 14, 29, 14, 57, 14, 113, 15, -30, 15, 46, 15, 91, 15,
     51   19, 16, 37, 16, 73, 16, 2, 17, 3, 17, 6, 17
     52 };
     53 
     54 /* min(2^32-1, 10^e-1) for e in range 0 through 10 */
     55 static uint32_t ndigits_dec_threshold[] = {
     56   0, 9U, 99U, 999U, 9999U, 99999U, 999999U,
     57   9999999U, 99999999U, 999999999U, 0xffffffffU
     58 };
     59 
     60 /* -- Helper functions ---------------------------------------------------- */
     61 
     62 /* Compute the number of digits in the decimal representation of x. */
     63 static MSize ndigits_dec(uint32_t x)
     64 {
     65   MSize t = ((lj_fls(x | 1) * 77) >> 8) + 1; /* 2^8/77 is roughly log2(10) */
     66   return t + (x > ndigits_dec_threshold[t]);
     67 }
     68 
     69 #define WINT_R(x, sh, sc) \
     70   { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); }
     71 
     72 /* Write 9-digit unsigned integer to buffer. */
     73 static char *lj_strfmt_wuint9(char *p, uint32_t u)
     74 {
     75   uint32_t v = u / 10000, w;
     76   u -= v * 10000;
     77   w = v / 10000;
     78   v -= w * 10000;
     79   *p++ = (char)('0'+w);
     80   WINT_R(v, 23, 1000)
     81   WINT_R(v, 12, 100)
     82   WINT_R(v, 10, 10)
     83   *p++ = (char)('0'+v);
     84   WINT_R(u, 23, 1000)
     85   WINT_R(u, 12, 100)
     86   WINT_R(u, 10, 10)
     87   *p++ = (char)('0'+u);
     88   return p;
     89 }
     90 #undef WINT_R
     91 
     92 /* -- Extended precision arithmetic --------------------------------------- */
     93 
     94 /*
     95 ** The "nd" format is a fixed-precision decimal representation for numbers. It
     96 ** consists of up to 64 uint32_t values, with each uint32_t storing a value
     97 ** in the range [0, 1e9). A number in "nd" format consists of three variables:
     98 **
     99 **  uint32_t nd[64];
    100 **  uint32_t ndlo;
    101 **  uint32_t ndhi;
    102 **
    103 ** The integral part of the number is stored in nd[0 ... ndhi], the value of
    104 ** which is sum{i in [0, ndhi] | nd[i] * 10^(9*i)}. If the fractional part of
    105 ** the number is zero, ndlo is zero. Otherwise, the fractional part is stored
    106 ** in nd[ndlo ... 63], the value of which is taken to be
    107 ** sum{i in [ndlo, 63] | nd[i] * 10^(9*(i-64))}.
    108 **
    109 ** If the array part had 128 elements rather than 64, then every double would
    110 ** have an exact representation in "nd" format. With 64 elements, all integral
    111 ** doubles have an exact representation, and all non-integral doubles have
    112 ** enough digits to make both %.99e and %.99f do the right thing.
    113 */
    114 
    115 #if LJ_64
    116 #define ND_MUL2K_MAX_SHIFT	29
    117 #define ND_MUL2K_DIV1E9(val)	((uint32_t)((val) / 1000000000))
    118 #else
    119 #define ND_MUL2K_MAX_SHIFT	11
    120 #define ND_MUL2K_DIV1E9(val)	((uint32_t)((val) >> 9) / 1953125)
    121 #endif
    122 
    123 /* Multiply nd by 2^k and add carry_in (ndlo is assumed to be zero). */
    124 static uint32_t nd_mul2k(uint32_t* nd, uint32_t ndhi, uint32_t k,
    125 			 uint32_t carry_in, SFormat sf)
    126 {
    127   uint32_t i, ndlo = 0, start = 1;
    128   /* Performance hacks. */
    129   if (k > ND_MUL2K_MAX_SHIFT*2 && STRFMT_FP(sf) != STRFMT_FP(STRFMT_T_FP_F)) {
    130     start = ndhi - (STRFMT_PREC(sf) + 17) / 8;
    131   }
    132   /* Real logic. */
    133   while (k >= ND_MUL2K_MAX_SHIFT) {
    134     for (i = ndlo; i <= ndhi; i++) {
    135       uint64_t val = ((uint64_t)nd[i] << ND_MUL2K_MAX_SHIFT) | carry_in;
    136       carry_in = ND_MUL2K_DIV1E9(val);
    137       nd[i] = (uint32_t)val - carry_in * 1000000000;
    138     }
    139     if (carry_in) {
    140       nd[++ndhi] = carry_in; carry_in = 0;
    141       if(start++ == ndlo) ++ndlo;
    142     }
    143     k -= ND_MUL2K_MAX_SHIFT;
    144   }
    145   if (k) {
    146     for (i = ndlo; i <= ndhi; i++) {
    147       uint64_t val = ((uint64_t)nd[i] << k) | carry_in;
    148       carry_in = ND_MUL2K_DIV1E9(val);
    149       nd[i] = (uint32_t)val - carry_in * 1000000000;
    150     }
    151     if (carry_in) nd[++ndhi] = carry_in;
    152   }
    153   return ndhi;
    154 }
    155 
    156 /* Divide nd by 2^k (ndlo is assumed to be zero). */
    157 static uint32_t nd_div2k(uint32_t* nd, uint32_t ndhi, uint32_t k, SFormat sf)
    158 {
    159   uint32_t ndlo = 0, stop1 = ~0, stop2 = ~0;
    160   /* Performance hacks. */
    161   if (!ndhi) {
    162     if (!nd[0]) {
    163       return 0;
    164     } else {
    165       uint32_t s = lj_ffs(nd[0]);
    166       if (s >= k) { nd[0] >>= k; return 0; }
    167       nd[0] >>= s; k -= s;
    168     }
    169   }
    170   if (k > 18) {
    171     if (STRFMT_FP(sf) == STRFMT_FP(STRFMT_T_FP_F)) {
    172       stop1 = 63 - (int32_t)STRFMT_PREC(sf) / 9;
    173     } else {
    174       int32_t floorlog2 = ndhi * 29 + lj_fls(nd[ndhi]) - k;
    175       int32_t floorlog10 = (int32_t)(floorlog2 * 0.30102999566398114);
    176       stop1 = 62 + (floorlog10 - (int32_t)STRFMT_PREC(sf)) / 9;
    177       stop2 = 61 + ndhi - (int32_t)STRFMT_PREC(sf) / 8;
    178     }
    179   }
    180   /* Real logic. */
    181   while (k >= 9) {
    182     uint32_t i = ndhi, carry = 0;
    183     for (;;) {
    184       uint32_t val = nd[i];
    185       nd[i] = (val >> 9) + carry;
    186       carry = (val & 0x1ff) * 1953125;
    187       if (i == ndlo) break;
    188       i = (i - 1) & 0x3f;
    189     }
    190     if (ndlo != stop1 && ndlo != stop2) {
    191       if (carry) { ndlo = (ndlo - 1) & 0x3f; nd[ndlo] = carry; }
    192       if (!nd[ndhi]) { ndhi = (ndhi - 1) & 0x3f; stop2--; }
    193     } else if (!nd[ndhi]) {
    194       if (ndhi != ndlo) { ndhi = (ndhi - 1) & 0x3f; stop2--; }
    195       else return ndlo;
    196     }
    197     k -= 9;
    198   }
    199   if (k) {
    200     uint32_t mask = (1U << k) - 1, mul = 1000000000 >> k, i = ndhi, carry = 0;
    201     for (;;) {
    202       uint32_t val = nd[i];
    203       nd[i] = (val >> k) + carry;
    204       carry = (val & mask) * mul;
    205       if (i == ndlo) break;
    206       i = (i - 1) & 0x3f;
    207     }
    208     if (carry) { ndlo = (ndlo - 1) & 0x3f; nd[ndlo] = carry; }
    209   }
    210   return ndlo;
    211 }
    212 
    213 /* Add m*10^e to nd (assumes ndlo <= e/9 <= ndhi and 0 <= m <= 9). */
    214 static uint32_t nd_add_m10e(uint32_t* nd, uint32_t ndhi, uint8_t m, int32_t e)
    215 {
    216   uint32_t i, carry;
    217   if (e >= 0) {
    218     i = (uint32_t)e/9;
    219     carry = m * (ndigits_dec_threshold[e - (int32_t)i*9] + 1);
    220   } else {
    221     int32_t f = (e-8)/9;
    222     i = (uint32_t)(64 + f);
    223     carry = m * (ndigits_dec_threshold[e - f*9] + 1);
    224   }
    225   for (;;) {
    226     uint32_t val = nd[i] + carry;
    227     if (LJ_UNLIKELY(val >= 1000000000)) {
    228       val -= 1000000000;
    229       nd[i] = val;
    230       if (LJ_UNLIKELY(i == ndhi)) {
    231 	ndhi = (ndhi + 1) & 0x3f;
    232 	nd[ndhi] = 1;
    233 	break;
    234       }
    235       carry = 1;
    236       i = (i + 1) & 0x3f;
    237     } else {
    238       nd[i] = val;
    239       break;
    240     }
    241   }
    242   return ndhi;
    243 }
    244 
    245 /* Test whether two "nd" values are equal in their most significant digits. */
    246 static int nd_similar(uint32_t* nd, uint32_t ndhi, uint32_t* ref, MSize hilen,
    247 		      MSize prec)
    248 {
    249   char nd9[9], ref9[9];
    250   if (hilen <= prec) {
    251     if (LJ_UNLIKELY(nd[ndhi] != *ref)) return 0;
    252     prec -= hilen; ref--; ndhi = (ndhi - 1) & 0x3f;
    253     if (prec >= 9) {
    254       if (LJ_UNLIKELY(nd[ndhi] != *ref)) return 0;
    255       prec -= 9; ref--; ndhi = (ndhi - 1) & 0x3f;
    256     }
    257   } else {
    258     prec -= hilen - 9;
    259   }
    260   lua_assert(prec < 9);
    261   lj_strfmt_wuint9(nd9, nd[ndhi]);
    262   lj_strfmt_wuint9(ref9, *ref);
    263   return !memcmp(nd9, ref9, prec) && (nd9[prec] < '5') == (ref9[prec] < '5');
    264 }
    265 
    266 /* -- Formatted conversions to buffer ------------------------------------- */
    267 
    268 /* Write formatted floating-point number to either sb or p. */
    269 static char *lj_strfmt_wfnum(SBuf *sb, SFormat sf, lua_Number n, char *p)
    270 {
    271   MSize width = STRFMT_WIDTH(sf), prec = STRFMT_PREC(sf), len;
    272   TValue t;
    273   t.n = n;
    274   if (LJ_UNLIKELY((t.u32.hi << 1) >= 0xffe00000)) {
    275     /* Handle non-finite values uniformly for %a, %e, %f, %g. */
    276     int prefix = 0, ch = (sf & STRFMT_F_UPPER) ? 0x202020 : 0;
    277     if (((t.u32.hi & 0x000fffff) | t.u32.lo) != 0) {
    278       ch ^= ('n' << 16) | ('a' << 8) | 'n';
    279       if ((sf & STRFMT_F_SPACE)) prefix = ' ';
    280     } else {
    281       ch ^= ('i' << 16) | ('n' << 8) | 'f';
    282       if ((t.u32.hi & 0x80000000)) prefix = '-';
    283       else if ((sf & STRFMT_F_PLUS)) prefix = '+';
    284       else if ((sf & STRFMT_F_SPACE)) prefix = ' ';
    285     }
    286     len = 3 + (prefix != 0);
    287     if (!p) p = lj_buf_more(sb, width > len ? width : len);
    288     if (!(sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' ';
    289     if (prefix) *p++ = prefix;
    290     *p++ = (char)(ch >> 16); *p++ = (char)(ch >> 8); *p++ = (char)ch;
    291   } else if (STRFMT_FP(sf) == STRFMT_FP(STRFMT_T_FP_A)) {
    292     /* %a */
    293     const char *hexdig = (sf & STRFMT_F_UPPER) ? "0123456789ABCDEFPX"
    294 					       : "0123456789abcdefpx";
    295     int32_t e = (t.u32.hi >> 20) & 0x7ff;
    296     char prefix = 0, eprefix = '+';
    297     if (t.u32.hi & 0x80000000) prefix = '-';
    298     else if ((sf & STRFMT_F_PLUS)) prefix = '+';
    299     else if ((sf & STRFMT_F_SPACE)) prefix = ' ';
    300     t.u32.hi &= 0xfffff;
    301     if (e) {
    302       t.u32.hi |= 0x100000;
    303       e -= 1023;
    304     } else if (t.u32.lo | t.u32.hi) {
    305       /* Non-zero denormal - normalise it. */
    306       uint32_t shift = t.u32.hi ? 20-lj_fls(t.u32.hi) : 52-lj_fls(t.u32.lo);
    307       e = -1022 - shift;
    308       t.u64 <<= shift;
    309     }
    310     /* abs(n) == t.u64 * 2^(e - 52) */
    311     /* If n != 0, bit 52 of t.u64 is set, and is the highest set bit. */
    312     if ((int32_t)prec < 0) {
    313       /* Default precision: use smallest precision giving exact result. */
    314       prec = t.u32.lo ? 13-lj_ffs(t.u32.lo)/4 : 5-lj_ffs(t.u32.hi|0x100000)/4;
    315     } else if (prec < 13) {
    316       /* Precision is sufficiently low as to maybe require rounding. */
    317       t.u64 += (((uint64_t)1) << (51 - prec*4));
    318     }
    319     if (e < 0) {
    320       eprefix = '-';
    321       e = -e;
    322     }
    323     len = 5 + ndigits_dec((uint32_t)e) + prec + (prefix != 0)
    324 	    + ((prec | (sf & STRFMT_F_ALT)) != 0);
    325     if (!p) p = lj_buf_more(sb, width > len ? width : len);
    326     if (!(sf & (STRFMT_F_LEFT | STRFMT_F_ZERO))) {
    327       while (width-- > len) *p++ = ' ';
    328     }
    329     if (prefix) *p++ = prefix;
    330     *p++ = '0';
    331     *p++ = hexdig[17]; /* x or X */
    332     if ((sf & (STRFMT_F_LEFT | STRFMT_F_ZERO)) == STRFMT_F_ZERO) {
    333       while (width-- > len) *p++ = '0';
    334     }
    335     *p++ = '0' + (t.u32.hi >> 20); /* Usually '1', sometimes '0' or '2'. */
    336     if ((prec | (sf & STRFMT_F_ALT))) {
    337       /* Emit fractional part. */
    338       char *q = p + 1 + prec;
    339       *p = '.';
    340       if (prec < 13) t.u64 >>= (52 - prec*4);
    341       else while (prec > 13) p[prec--] = '0';
    342       while (prec) { p[prec--] = hexdig[t.u64 & 15]; t.u64 >>= 4; }
    343       p = q;
    344     }
    345     *p++ = hexdig[16]; /* p or P */
    346     *p++ = eprefix; /* + or - */
    347     p = lj_strfmt_wint(p, e);
    348   } else {
    349     /* %e or %f or %g - begin by converting n to "nd" format. */
    350     uint32_t nd[64];
    351     uint32_t ndhi = 0, ndlo, i;
    352     int32_t e = (t.u32.hi >> 20) & 0x7ff, ndebias = 0;
    353     char prefix = 0, *q;
    354     if (t.u32.hi & 0x80000000) prefix = '-';
    355     else if ((sf & STRFMT_F_PLUS)) prefix = '+';
    356     else if ((sf & STRFMT_F_SPACE)) prefix = ' ';
    357     prec += ((int32_t)prec >> 31) & 7; /* Default precision is 6. */
    358     if (STRFMT_FP(sf) == STRFMT_FP(STRFMT_T_FP_G)) {
    359       /* %g - decrement precision if non-zero (to make it like %e). */
    360       prec--;
    361       prec ^= (uint32_t)((int32_t)prec >> 31);
    362     }
    363     if ((sf & STRFMT_T_FP_E) && prec < 14 && n != 0) {
    364       /* Precision is sufficiently low that rescaling will probably work. */
    365       if ((ndebias = rescale_e[e >> 6])) {
    366 	t.n = n * rescale_n[e >> 6];
    367 	if (LJ_UNLIKELY(!e)) t.n *= 1e10, ndebias -= 10;
    368 	t.u64 -= 2; /* Convert 2ulp below (later we convert 2ulp above). */
    369 	nd[0] = 0x100000 | (t.u32.hi & 0xfffff);
    370 	e = ((t.u32.hi >> 20) & 0x7ff) - 1075 - (ND_MUL2K_MAX_SHIFT < 29);
    371 	goto load_t_lo; rescale_failed:
    372 	t.n = n;
    373 	e = (t.u32.hi >> 20) & 0x7ff;
    374 	ndebias = ndhi = 0;
    375       }
    376     }
    377     nd[0] = t.u32.hi & 0xfffff;
    378     if (e == 0) e++; else nd[0] |= 0x100000;
    379     e -= 1043;
    380     if (t.u32.lo) {
    381       e -= 32 + (ND_MUL2K_MAX_SHIFT < 29); load_t_lo:
    382 #if ND_MUL2K_MAX_SHIFT >= 29
    383       nd[0] = (nd[0] << 3) | (t.u32.lo >> 29);
    384       ndhi = nd_mul2k(nd, ndhi, 29, t.u32.lo & 0x1fffffff, sf);
    385 #elif ND_MUL2K_MAX_SHIFT >= 11
    386       ndhi = nd_mul2k(nd, ndhi, 11, t.u32.lo >> 21, sf);
    387       ndhi = nd_mul2k(nd, ndhi, 11, (t.u32.lo >> 10) & 0x7ff, sf);
    388       ndhi = nd_mul2k(nd, ndhi, 11, (t.u32.lo <<  1) & 0x7ff, sf);
    389 #else
    390 #error "ND_MUL2K_MAX_SHIFT too small"
    391 #endif
    392     }
    393     if (e >= 0) {
    394       ndhi = nd_mul2k(nd, ndhi, (uint32_t)e, 0, sf);
    395       ndlo = 0;
    396     } else {
    397       ndlo = nd_div2k(nd, ndhi, (uint32_t)-e, sf);
    398       if (ndhi && !nd[ndhi]) ndhi--;
    399     }
    400     /* abs(n) == nd * 10^ndebias (for slightly loose interpretation of ==) */
    401     if ((sf & STRFMT_T_FP_E)) {
    402       /* %e or %g - assume %e and start by calculating nd's exponent (nde). */
    403       char eprefix = '+';
    404       int32_t nde = -1;
    405       MSize hilen;
    406       if (ndlo && !nd[ndhi]) {
    407 	ndhi = 64; do {} while (!nd[--ndhi]);
    408 	nde -= 64 * 9;
    409       }
    410       hilen = ndigits_dec(nd[ndhi]);
    411       nde += ndhi * 9 + hilen;
    412       if (ndebias) {
    413 	/*
    414 	** Rescaling was performed, but this introduced some error, and might
    415 	** have pushed us across a rounding boundary. We check whether this
    416 	** error affected the result by introducing even more error (2ulp in
    417 	** either direction), and seeing whether a roundary boundary was
    418 	** crossed. Having already converted the -2ulp case, we save off its
    419 	** most significant digits, convert the +2ulp case, and compare them.
    420 	*/
    421 	int32_t eidx = e + 70 + (ND_MUL2K_MAX_SHIFT < 29)
    422 			 + (t.u32.lo >= 0xfffffffe && !(~t.u32.hi << 12));
    423 	const int8_t *m_e = four_ulp_m_e + eidx * 2;
    424 	lua_assert(0 <= eidx && eidx < 128);
    425 	nd[33] = nd[ndhi];
    426 	nd[32] = nd[(ndhi - 1) & 0x3f];
    427 	nd[31] = nd[(ndhi - 2) & 0x3f];
    428 	nd_add_m10e(nd, ndhi, (uint8_t)*m_e, m_e[1]);
    429 	if (LJ_UNLIKELY(!nd_similar(nd, ndhi, nd + 33, hilen, prec + 1))) {
    430 	  goto rescale_failed;
    431 	}
    432       }
    433       if ((int32_t)(prec - nde) < (0x3f & -(int32_t)ndlo) * 9) {
    434 	/* Precision is sufficiently low as to maybe require rounding. */
    435 	ndhi = nd_add_m10e(nd, ndhi, 5, nde - prec - 1);
    436 	nde += (hilen != ndigits_dec(nd[ndhi]));
    437       }
    438       nde += ndebias;
    439       if ((sf & STRFMT_T_FP_F)) {
    440 	/* %g */
    441 	if ((int32_t)prec >= nde && nde >= -4) {
    442 	  if (nde < 0) ndhi = 0;
    443 	  prec -= nde;
    444 	  goto g_format_like_f;
    445 	} else if (!(sf & STRFMT_F_ALT) && prec && width > 5) {
    446 	  /* Decrease precision in order to strip trailing zeroes. */
    447 	  char tail[9];
    448 	  uint32_t maxprec = hilen - 1 + ((ndhi - ndlo) & 0x3f) * 9;
    449 	  if (prec >= maxprec) prec = maxprec;
    450 	  else ndlo = (ndhi - (((int32_t)(prec - hilen) + 9) / 9)) & 0x3f;
    451 	  i = prec - hilen - (((ndhi - ndlo) & 0x3f) * 9) + 10;
    452 	  lj_strfmt_wuint9(tail, nd[ndlo]);
    453 	  while (prec && tail[--i] == '0') {
    454 	    prec--;
    455 	    if (!i) {
    456 	      if (ndlo == ndhi) { prec = 0; break; }
    457 	      lj_strfmt_wuint9(tail, nd[++ndlo]);
    458 	      i = 9;
    459 	    }
    460 	  }
    461 	}
    462       }
    463       if (nde < 0) {
    464 	/* Make nde non-negative. */
    465 	eprefix = '-';
    466 	nde = -nde;
    467       }
    468       len = 3 + prec + (prefix != 0) + ndigits_dec((uint32_t)nde) + (nde < 10)
    469 	      + ((prec | (sf & STRFMT_F_ALT)) != 0);
    470       if (!p) p = lj_buf_more(sb, (width > len ? width : len) + 5);
    471       if (!(sf & (STRFMT_F_LEFT | STRFMT_F_ZERO))) {
    472 	while (width-- > len) *p++ = ' ';
    473       }
    474       if (prefix) *p++ = prefix;
    475       if ((sf & (STRFMT_F_LEFT | STRFMT_F_ZERO)) == STRFMT_F_ZERO) {
    476 	while (width-- > len) *p++ = '0';
    477       }
    478       q = lj_strfmt_wint(p + 1, nd[ndhi]);
    479       p[0] = p[1]; /* Put leading digit in the correct place. */
    480       if ((prec | (sf & STRFMT_F_ALT))) {
    481 	/* Emit fractional part. */
    482 	p[1] = '.'; p += 2;
    483 	prec -= (MSize)(q - p); p = q; /* Account for digits already emitted. */
    484 	/* Then emit chunks of 9 digits (this may emit 8 digits too many). */
    485 	for (i = ndhi; (int32_t)prec > 0 && i != ndlo; prec -= 9) {
    486 	  i = (i - 1) & 0x3f;
    487 	  p = lj_strfmt_wuint9(p, nd[i]);
    488 	}
    489 	if ((sf & STRFMT_T_FP_F) && !(sf & STRFMT_F_ALT)) {
    490 	  /* %g (and not %#g) - strip trailing zeroes. */
    491 	  p += (int32_t)prec & ((int32_t)prec >> 31);
    492 	  while (p[-1] == '0') p--;
    493 	  if (p[-1] == '.') p--;
    494 	} else {
    495 	  /* %e (or %#g) - emit trailing zeroes. */
    496 	  while ((int32_t)prec > 0) { *p++ = '0'; prec--; }
    497 	  p += (int32_t)prec;
    498 	}
    499       } else {
    500 	p++;
    501       }
    502       *p++ = (sf & STRFMT_F_UPPER) ? 'E' : 'e';
    503       *p++ = eprefix; /* + or - */
    504       if (nde < 10) *p++ = '0'; /* Always at least two digits of exponent. */
    505       p = lj_strfmt_wint(p, nde);
    506     } else {
    507       /* %f (or, shortly, %g in %f style) */
    508       if (prec < (MSize)(0x3f & -(int32_t)ndlo) * 9) {
    509 	/* Precision is sufficiently low as to maybe require rounding. */
    510 	ndhi = nd_add_m10e(nd, ndhi, 5, 0 - prec - 1);
    511       }
    512       g_format_like_f:
    513       if ((sf & STRFMT_T_FP_E) && !(sf & STRFMT_F_ALT) && prec && width) {
    514 	/* Decrease precision in order to strip trailing zeroes. */
    515 	if (ndlo) {
    516 	  /* nd has a fractional part; we need to look at its digits. */
    517 	  char tail[9];
    518 	  uint32_t maxprec = (64 - ndlo) * 9;
    519 	  if (prec >= maxprec) prec = maxprec;
    520 	  else ndlo = 64 - (prec + 8) / 9;
    521 	  i = prec - ((63 - ndlo) * 9);
    522 	  lj_strfmt_wuint9(tail, nd[ndlo]);
    523 	  while (prec && tail[--i] == '0') {
    524 	    prec--;
    525 	    if (!i) {
    526 	      if (ndlo == 63) { prec = 0; break; }
    527 	      lj_strfmt_wuint9(tail, nd[++ndlo]);
    528 	      i = 9;
    529 	    }
    530 	  }
    531 	} else {
    532 	  /* nd has no fractional part, so precision goes straight to zero. */
    533 	  prec = 0;
    534 	}
    535       }
    536       len = ndhi * 9 + ndigits_dec(nd[ndhi]) + prec + (prefix != 0)
    537 		     + ((prec | (sf & STRFMT_F_ALT)) != 0);
    538       if (!p) p = lj_buf_more(sb, (width > len ? width : len) + 8);
    539       if (!(sf & (STRFMT_F_LEFT | STRFMT_F_ZERO))) {
    540 	while (width-- > len) *p++ = ' ';
    541       }
    542       if (prefix) *p++ = prefix;
    543       if ((sf & (STRFMT_F_LEFT | STRFMT_F_ZERO)) == STRFMT_F_ZERO) {
    544 	while (width-- > len) *p++ = '0';
    545       }
    546       /* Emit integer part. */
    547       p = lj_strfmt_wint(p, nd[ndhi]);
    548       i = ndhi;
    549       while (i) p = lj_strfmt_wuint9(p, nd[--i]);
    550       if ((prec | (sf & STRFMT_F_ALT))) {
    551 	/* Emit fractional part. */
    552 	*p++ = '.';
    553 	/* Emit chunks of 9 digits (this may emit 8 digits too many). */
    554 	while ((int32_t)prec > 0 && i != ndlo) {
    555 	  i = (i - 1) & 0x3f;
    556 	  p = lj_strfmt_wuint9(p, nd[i]);
    557 	  prec -= 9;
    558 	}
    559 	if ((sf & STRFMT_T_FP_E) && !(sf & STRFMT_F_ALT)) {
    560 	  /* %g (and not %#g) - strip trailing zeroes. */
    561 	  p += (int32_t)prec & ((int32_t)prec >> 31);
    562 	  while (p[-1] == '0') p--;
    563 	  if (p[-1] == '.') p--;
    564 	} else {
    565 	  /* %f (or %#g) - emit trailing zeroes. */
    566 	  while ((int32_t)prec > 0) { *p++ = '0'; prec--; }
    567 	  p += (int32_t)prec;
    568 	}
    569       }
    570     }
    571   }
    572   if ((sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' ';
    573   return p;
    574 }
    575 
    576 /* Add formatted floating-point number to buffer. */
    577 SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n)
    578 {
    579   setsbufP(sb, lj_strfmt_wfnum(sb, sf, n, NULL));
    580   return sb;
    581 }
    582 
    583 /* -- Conversions to strings ---------------------------------------------- */
    584 
    585 /* Convert number to string. */
    586 GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o)
    587 {
    588   char buf[STRFMT_MAXBUF_NUM];
    589   MSize len = (MSize)(lj_strfmt_wfnum(NULL, STRFMT_G14, o->n, buf) - buf);
    590   return lj_str_new(L, buf, len);
    591 }
    592