root/lj_strfmt_num.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ndigits_dec
  2. lj_strfmt_wuint9
  3. nd_mul2k
  4. nd_div2k
  5. nd_add_m10e
  6. nd_similar
  7. lj_strfmt_wfnum
  8. lj_strfmt_putfnum
  9. lj_strfmt_num

   1 /*
   2 ** String formatting for floating-point numbers.
   3 ** Copyright (C) 2005-2017 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 

/* [<][>][^][v][top][bottom][index][help] */