aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Makefile2
-rw-r--r--src/Makefile.dep4
-rw-r--r--src/lib_base.c3
-rw-r--r--src/lib_io.c3
-rw-r--r--src/lj_buf.c2
-rw-r--r--src/lj_ctype.c14
-rw-r--r--src/lj_meta.c14
-rw-r--r--src/lj_strfmt.c108
-rw-r--r--src/lj_strfmt.h6
-rw-r--r--src/lj_strfmt_num.c591
-rw-r--r--src/ljamalg.c1
11 files changed, 627 insertions, 121 deletions
diff --git a/src/Makefile b/src/Makefile
index 1df39dc1..5d66f6eb 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -478,7 +478,7 @@ LJLIB_C= $(LJLIB_O:.o=.c)
478LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \ 478LJCORE_O= lj_gc.o lj_err.o lj_char.o lj_bc.o lj_obj.o lj_buf.o \
479 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \ 479 lj_str.o lj_tab.o lj_func.o lj_udata.o lj_meta.o lj_debug.o \
480 lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \ 480 lj_state.o lj_dispatch.o lj_vmevent.o lj_vmmath.o lj_strscan.o \
481 lj_strfmt.o lj_api.o lj_profile.o \ 481 lj_strfmt.o lj_strfmt_num.o lj_api.o lj_profile.o \
482 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \ 482 lj_lex.o lj_parse.o lj_bcread.o lj_bcwrite.o lj_load.o \
483 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \ 483 lj_ir.o lj_opt_mem.o lj_opt_fold.o lj_opt_narrow.o \
484 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \ 484 lj_opt_dce.o lj_opt_loop.o lj_opt_split.o lj_opt_sink.o \
diff --git a/src/Makefile.dep b/src/Makefile.dep
index 9aefb236..2c329f55 100644
--- a/src/Makefile.dep
+++ b/src/Makefile.dep
@@ -94,7 +94,7 @@ lj_crecord.o: lj_crecord.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
94 lj_crecord.h lj_strfmt.h 94 lj_crecord.h lj_strfmt.h
95lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 95lj_ctype.o: lj_ctype.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
96 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_strfmt.h lj_ctype.h \ 96 lj_gc.h lj_err.h lj_errmsg.h lj_str.h lj_tab.h lj_strfmt.h lj_ctype.h \
97 lj_ccallback.h 97 lj_ccallback.h lj_buf.h
98lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 98lj_debug.o: lj_debug.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
99 lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \ 99 lj_err.h lj_errmsg.h lj_debug.h lj_buf.h lj_gc.h lj_str.h lj_tab.h \
100 lj_state.h lj_frame.h lj_bc.h lj_strfmt.h lj_jit.h lj_ir.h 100 lj_state.h lj_frame.h lj_bc.h lj_strfmt.h lj_jit.h lj_ir.h
@@ -188,6 +188,8 @@ lj_str.o: lj_str.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
188 lj_err.h lj_errmsg.h lj_str.h lj_char.h 188 lj_err.h lj_errmsg.h lj_str.h lj_char.h
189lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 189lj_strfmt.o: lj_strfmt.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
190 lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h 190 lj_buf.h lj_gc.h lj_str.h lj_state.h lj_char.h lj_strfmt.h
191lj_strfmt_num.o: lj_strfmt_num.c lj_obj.h lua.h luaconf.h lj_def.h \
192 lj_arch.h lj_buf.h lj_gc.h lj_str.h lj_strfmt.h
191lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \ 193lj_strscan.o: lj_strscan.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h \
192 lj_char.h lj_strscan.h 194 lj_char.h lj_strscan.h
193lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \ 195lj_tab.o: lj_tab.c lj_obj.h lua.h luaconf.h lj_def.h lj_arch.h lj_gc.h \
diff --git a/src/lib_base.c b/src/lib_base.c
index ca268b1d..3c973265 100644
--- a/src/lib_base.c
+++ b/src/lib_base.c
@@ -495,11 +495,10 @@ LJLIB_CF(print)
495 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring); 495 shortcut = (tvisfunc(tv) && funcV(tv)->c.ffid == FF_tostring);
496 for (i = 0; i < nargs; i++) { 496 for (i = 0; i < nargs; i++) {
497 cTValue *o = &L->base[i]; 497 cTValue *o = &L->base[i];
498 char buf[STRFMT_MAXBUF_NUM];
499 const char *str; 498 const char *str;
500 size_t size; 499 size_t size;
501 MSize len; 500 MSize len;
502 if (shortcut && (str = lj_strfmt_wstrnum(buf, o, &len)) != NULL) { 501 if (shortcut && (str = lj_strfmt_wstrnum(L, o, &len)) != NULL) {
503 size = len; 502 size = len;
504 } else { 503 } else {
505 copyTV(L, L->top+1, o); 504 copyTV(L, L->top+1, o);
diff --git a/src/lib_io.c b/src/lib_io.c
index 2aa83474..501de568 100644
--- a/src/lib_io.c
+++ b/src/lib_io.c
@@ -232,9 +232,8 @@ static int io_file_write(lua_State *L, FILE *fp, int start)
232 cTValue *tv; 232 cTValue *tv;
233 int status = 1; 233 int status = 1;
234 for (tv = L->base+start; tv < L->top; tv++) { 234 for (tv = L->base+start; tv < L->top; tv++) {
235 char buf[STRFMT_MAXBUF_NUM];
236 MSize len; 235 MSize len;
237 const char *p = lj_strfmt_wstrnum(buf, tv, &len); 236 const char *p = lj_strfmt_wstrnum(L, tv, &len);
238 if (!p) 237 if (!p)
239 lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING); 238 lj_err_argt(L, (int)(tv - L->base) + 1, LUA_TSTRING);
240 status = status && (fwrite(p, 1, len, fp) == len); 239 status = status && (fwrite(p, 1, len, fp) == len);
diff --git a/src/lj_buf.c b/src/lj_buf.c
index 023bb9aa..7b6c2188 100644
--- a/src/lj_buf.c
+++ b/src/lj_buf.c
@@ -186,7 +186,7 @@ SBuf *lj_buf_puttab(SBuf *sb, GCtab *t, GCstr *sep, int32_t i, int32_t e)
186 } else if (tvisint(o)) { 186 } else if (tvisint(o)) {
187 p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o)); 187 p = lj_strfmt_wint(lj_buf_more(sb, STRFMT_MAXBUF_INT+seplen), intV(o));
188 } else if (tvisnum(o)) { 188 } else if (tvisnum(o)) {
189 p = lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM+seplen), o); 189 p = lj_buf_more(lj_strfmt_putfnum(sb, STRFMT_G14, numV(o)), seplen);
190 } else { 190 } else {
191 goto badtype; 191 goto badtype;
192 } 192 }
diff --git a/src/lj_ctype.c b/src/lj_ctype.c
index eda070ce..94159462 100644
--- a/src/lj_ctype.c
+++ b/src/lj_ctype.c
@@ -14,6 +14,7 @@
14#include "lj_strfmt.h" 14#include "lj_strfmt.h"
15#include "lj_ctype.h" 15#include "lj_ctype.h"
16#include "lj_ccallback.h" 16#include "lj_ccallback.h"
17#include "lj_buf.h"
17 18
18/* -- C type definitions -------------------------------------------------- */ 19/* -- C type definitions -------------------------------------------------- */
19 20
@@ -571,19 +572,18 @@ GCstr *lj_ctype_repr_int64(lua_State *L, uint64_t n, int isunsigned)
571/* Convert complex to string with 'i' or 'I' suffix. */ 572/* Convert complex to string with 'i' or 'I' suffix. */
572GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size) 573GCstr *lj_ctype_repr_complex(lua_State *L, void *sp, CTSize size)
573{ 574{
574 char buf[2*STRFMT_MAXBUF_NUM+2+1], *p = buf; 575 SBuf *sb = lj_buf_tmp_(L);
575 TValue re, im; 576 TValue re, im;
576 if (size == 2*sizeof(double)) { 577 if (size == 2*sizeof(double)) {
577 re.n = *(double *)sp; im.n = ((double *)sp)[1]; 578 re.n = *(double *)sp; im.n = ((double *)sp)[1];
578 } else { 579 } else {
579 re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1]; 580 re.n = (double)*(float *)sp; im.n = (double)((float *)sp)[1];
580 } 581 }
581 p = lj_strfmt_wnum(p, &re); 582 lj_strfmt_putfnum(sb, STRFMT_G14, re.n);
582 if (!(im.u32.hi & 0x80000000u) || im.n != im.n) *p++ = '+'; 583 if (!(im.u32.hi & 0x80000000u) || im.n != im.n) lj_buf_putchar(sb, '+');
583 p = lj_strfmt_wnum(p, &im); 584 lj_strfmt_putfnum(sb, STRFMT_G14, im.n);
584 *p = *(p-1) >= 'a' ? 'I' : 'i'; 585 lj_buf_putchar(sb, sbufP(sb)[-1] >= 'a' ? 'I' : 'i');
585 p++; 586 return lj_buf_str(L, sb);
586 return lj_str_new(L, buf, p-buf);
587} 587}
588 588
589/* -- C type state -------------------------------------------------------- */ 589/* -- C type state -------------------------------------------------------- */
diff --git a/src/lj_meta.c b/src/lj_meta.c
index 104ecf07..de229571 100644
--- a/src/lj_meta.c
+++ b/src/lj_meta.c
@@ -278,25 +278,25 @@ TValue *lj_meta_cat(lua_State *L, TValue *top, int left)
278 */ 278 */
279 TValue *e, *o = top; 279 TValue *e, *o = top;
280 uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; 280 uint64_t tlen = tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
281 char *p, *buf; 281 SBuf *sb;
282 do { 282 do {
283 o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM; 283 o--; tlen += tvisstr(o) ? strV(o)->len : STRFMT_MAXBUF_NUM;
284 } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1))); 284 } while (--left > 0 && (tvisstr(o-1) || tvisnumber(o-1)));
285 if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV); 285 if (tlen >= LJ_MAX_STR) lj_err_msg(L, LJ_ERR_STROV);
286 p = buf = lj_buf_tmp(L, (MSize)tlen); 286 sb = lj_buf_tmp_(L);
287 lj_buf_more(sb, (MSize)tlen);
287 for (e = top, top = o; o <= e; o++) { 288 for (e = top, top = o; o <= e; o++) {
288 if (tvisstr(o)) { 289 if (tvisstr(o)) {
289 GCstr *s = strV(o); 290 GCstr *s = strV(o);
290 MSize len = s->len; 291 MSize len = s->len;
291 p = lj_buf_wmem(p, strdata(s), len); 292 lj_buf_putmem(sb, strdata(s), len);
292 } else if (tvisint(o)) { 293 } else if (tvisint(o)) {
293 p = lj_strfmt_wint(p, intV(o)); 294 lj_strfmt_putint(sb, intV(o));
294 } else { 295 } else {
295 lua_assert(tvisnum(o)); 296 lj_strfmt_putfnum(sb, STRFMT_G14, numV(o));
296 p = lj_strfmt_wnum(p, o);
297 } 297 }
298 } 298 }
299 setstrV(L, top, lj_str_new(L, buf, (size_t)(p-buf))); 299 setstrV(L, top, lj_buf_str(L, sb));
300 } 300 }
301 } while (left >= 1); 301 } while (left >= 1);
302 if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) { 302 if (LJ_UNLIKELY(G(L)->gc.total >= G(L)->gc.threshold)) {
diff --git a/src/lj_strfmt.c b/src/lj_strfmt.c
index d54e796a..ba9e1ff8 100644
--- a/src/lj_strfmt.c
+++ b/src/lj_strfmt.c
@@ -18,7 +18,7 @@
18/* -- Format parser ------------------------------------------------------- */ 18/* -- Format parser ------------------------------------------------------- */
19 19
20static const uint8_t strfmt_map[('x'-'A')+1] = { 20static const uint8_t strfmt_map[('x'-'A')+1] = {
21 STRFMT_A,0,0,0,STRFMT_E,0,STRFMT_G,0,0,0,0,0,0, 21 STRFMT_A,0,0,0,STRFMT_E,STRFMT_F,STRFMT_G,0,0,0,0,0,0,
22 0,0,0,0,0,0,0,0,0,0,STRFMT_X,0,0, 22 0,0,0,0,0,0,0,0,0,0,STRFMT_X,0,0,
23 0,0,0,0,0,0, 23 0,0,0,0,0,0,
24 STRFMT_A,0,STRFMT_C,STRFMT_D,STRFMT_E,STRFMT_F,STRFMT_G,0,STRFMT_I,0,0,0,0, 24 STRFMT_A,0,STRFMT_C,STRFMT_D,STRFMT_E,STRFMT_F,STRFMT_G,0,STRFMT_I,0,0,0,0,
@@ -89,24 +89,6 @@ retlit:
89 89
90/* -- Raw conversions ----------------------------------------------------- */ 90/* -- Raw conversions ----------------------------------------------------- */
91 91
92/* Write number to bufer. */
93char * LJ_FASTCALL lj_strfmt_wnum(char *p, cTValue *o)
94{
95 if (LJ_LIKELY((o->u32.hi << 1) < 0xffe00000)) { /* Finite? */
96#if __BIONIC__
97 if (tvismzero(o)) { *p++ = '-'; *p++ = '0'; return p; }
98#endif
99 return p + lua_number2str(p, o->n);
100 } else if (((o->u32.hi & 0x000fffff) | o->u32.lo) != 0) {
101 *p++ = 'n'; *p++ = 'a'; *p++ = 'n';
102 } else if ((o->u32.hi & 0x80000000) == 0) {
103 *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
104 } else {
105 *p++ = '-'; *p++ = 'i'; *p++ = 'n'; *p++ = 'f';
106 }
107 return p;
108}
109
110#define WINT_R(x, sh, sc) \ 92#define WINT_R(x, sh, sc) \
111 { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); } 93 { uint32_t d = (x*(((1<<sh)+sc-1)/sc))>>sh; x -= d*sc; *p++ = (char)('0'+d); }
112 94
@@ -168,21 +150,22 @@ char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v)
168 return p; 150 return p;
169} 151}
170 152
171/* Return string or write number to buffer and return pointer to start. */ 153/* Return string or write number to tmp buffer and return pointer to start. */
172const char *lj_strfmt_wstrnum(char *buf, cTValue *o, MSize *lenp) 154const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp)
173{ 155{
156 SBuf *sb;
174 if (tvisstr(o)) { 157 if (tvisstr(o)) {
175 *lenp = strV(o)->len; 158 *lenp = strV(o)->len;
176 return strVdata(o); 159 return strVdata(o);
177 } else if (tvisint(o)) { 160 } else if (tvisint(o)) {
178 *lenp = (MSize)(lj_strfmt_wint(buf, intV(o)) - buf); 161 sb = lj_strfmt_putint(lj_buf_tmp_(L), intV(o));
179 return buf;
180 } else if (tvisnum(o)) { 162 } else if (tvisnum(o)) {
181 *lenp = (MSize)(lj_strfmt_wnum(buf, o) - buf); 163 sb = lj_strfmt_putfnum(lj_buf_tmp_(L), STRFMT_G14, o->n);
182 return buf;
183 } else { 164 } else {
184 return NULL; 165 return NULL;
185 } 166 }
167 *lenp = sbuflen(sb);
168 return sbufB(sb);
186} 169}
187 170
188/* -- Unformatted conversions to buffer ----------------------------------- */ 171/* -- Unformatted conversions to buffer ----------------------------------- */
@@ -198,8 +181,7 @@ SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k)
198/* Add number to buffer. */ 181/* Add number to buffer. */
199SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o) 182SBuf * LJ_FASTCALL lj_strfmt_putnum(SBuf *sb, cTValue *o)
200{ 183{
201 setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), o)); 184 return lj_strfmt_putfnum(sb, STRFMT_G14, o->n);
202 return sb;
203} 185}
204#endif 186#endif
205 187
@@ -360,63 +342,6 @@ SBuf *lj_strfmt_putfnum_uint(SBuf *sb, SFormat sf, lua_Number n)
360 return lj_strfmt_putfxint(sb, sf, (uint64_t)k); 342 return lj_strfmt_putfxint(sb, sf, (uint64_t)k);
361} 343}
362 344
363/* Max. sprintf buffer size needed. At least #string.format("%.99f", -1e308). */
364#define STRFMT_FMTNUMBUF 512
365
366/* Add formatted floating-point number to buffer. */
367SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n)
368{
369 TValue tv;
370 tv.n = n;
371 if (LJ_UNLIKELY((tv.u32.hi << 1) >= 0xffe00000)) {
372 /* Canonicalize output of non-finite values. */
373 MSize width = STRFMT_WIDTH(sf), len = 3;
374 int prefix = 0, ch = (sf & STRFMT_F_UPPER) ? 0x202020 : 0;
375 char *p;
376 if (((tv.u32.hi & 0x000fffff) | tv.u32.lo) != 0) {
377 ch ^= ('n' << 16) | ('a' << 8) | 'n';
378 if ((sf & STRFMT_F_SPACE)) prefix = ' ';
379 } else {
380 ch ^= ('i' << 16) | ('n' << 8) | 'f';
381 if ((tv.u32.hi & 0x80000000)) prefix = '-';
382 else if ((sf & STRFMT_F_PLUS)) prefix = '+';
383 else if ((sf & STRFMT_F_SPACE)) prefix = ' ';
384 }
385 if (prefix) len = 4;
386 p = lj_buf_more(sb, width > len ? width : len);
387 if (!(sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' ';
388 if (prefix) *p++ = prefix;
389 *p++ = (char)(ch >> 16); *p++ = (char)(ch >> 8); *p++ = (char)ch;
390 if ((sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' ';
391 setsbufP(sb, p);
392 } else { /* Delegate to sprintf() for now. */
393 uint8_t width = (uint8_t)STRFMT_WIDTH(sf), prec = (uint8_t)STRFMT_PREC(sf);
394 char fmt[1+5+2+3+1+1], *p = fmt;
395 *p++ = '%';
396 if ((sf & STRFMT_F_LEFT)) *p++ = '-';
397 if ((sf & STRFMT_F_PLUS)) *p++ = '+';
398 if ((sf & STRFMT_F_ZERO)) *p++ = '0';
399 if ((sf & STRFMT_F_SPACE)) *p++ = ' ';
400 if ((sf & STRFMT_F_ALT)) *p++ = '#';
401 if (width) {
402 uint8_t x = width / 10, y = width % 10;
403 if (x) *p++ = '0' + x;
404 *p++ = '0' + y;
405 }
406 if (prec != 255) {
407 uint8_t x = prec / 10, y = prec % 10;
408 *p++ = '.';
409 if (x) *p++ = '0' + x;
410 *p++ = '0' + y;
411 }
412 *p++ = (0x67666561 >> (STRFMT_FP(sf)<<3)) ^ ((sf & STRFMT_F_UPPER)?0x20:0);
413 *p = '\0';
414 p = lj_buf_more(sb, STRFMT_FMTNUMBUF);
415 setsbufP(sb, p + sprintf(p, fmt, n));
416 }
417 return sb;
418}
419
420/* -- Conversions to strings ---------------------------------------------- */ 345/* -- Conversions to strings ---------------------------------------------- */
421 346
422/* Convert integer to string. */ 347/* Convert integer to string. */
@@ -427,14 +352,6 @@ GCstr * LJ_FASTCALL lj_strfmt_int(lua_State *L, int32_t k)
427 return lj_str_new(L, buf, len); 352 return lj_str_new(L, buf, len);
428} 353}
429 354
430/* Convert number to string. */
431GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o)
432{
433 char buf[STRFMT_MAXBUF_NUM];
434 MSize len = (MSize)(lj_strfmt_wnum(buf, o) - buf);
435 return lj_str_new(L, buf, len);
436}
437
438/* Convert integer or number to string. */ 355/* Convert integer or number to string. */
439GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o) 356GCstr * LJ_FASTCALL lj_strfmt_number(lua_State *L, cTValue *o)
440{ 357{
@@ -510,12 +427,9 @@ const char *lj_strfmt_pushvf(lua_State *L, const char *fmt, va_list argp)
510 case STRFMT_UINT: 427 case STRFMT_UINT:
511 lj_strfmt_putfxint(sb, sf, va_arg(argp, uint32_t)); 428 lj_strfmt_putfxint(sb, sf, va_arg(argp, uint32_t));
512 break; 429 break;
513 case STRFMT_NUM: { 430 case STRFMT_NUM:
514 TValue tv; 431 lj_strfmt_putfnum(sb, STRFMT_G14, va_arg(argp, lua_Number));
515 tv.n = va_arg(argp, lua_Number);
516 setsbufP(sb, lj_strfmt_wnum(lj_buf_more(sb, STRFMT_MAXBUF_NUM), &tv));
517 break; 432 break;
518 }
519 case STRFMT_STR: { 433 case STRFMT_STR: {
520 const char *s = va_arg(argp, char *); 434 const char *s = va_arg(argp, char *);
521 if (s == NULL) s = "(null)"; 435 if (s == NULL) s = "(null)";
diff --git a/src/lj_strfmt.h b/src/lj_strfmt.h
index dcfaf2e3..f229f25c 100644
--- a/src/lj_strfmt.h
+++ b/src/lj_strfmt.h
@@ -64,11 +64,12 @@ typedef enum FormatType {
64#define STRFMT_S (STRFMT_STR) 64#define STRFMT_S (STRFMT_STR)
65#define STRFMT_U (STRFMT_UINT) 65#define STRFMT_U (STRFMT_UINT)
66#define STRFMT_X (STRFMT_UINT|STRFMT_T_HEX) 66#define STRFMT_X (STRFMT_UINT|STRFMT_T_HEX)
67#define STRFMT_G14 (STRFMT_G | ((14+1) << STRFMT_SH_PREC))
67 68
68/* Maximum buffer sizes for conversions. */ 69/* Maximum buffer sizes for conversions. */
69#define STRFMT_MAXBUF_XINT (1+22) /* '0' prefix + uint64_t in octal. */ 70#define STRFMT_MAXBUF_XINT (1+22) /* '0' prefix + uint64_t in octal. */
70#define STRFMT_MAXBUF_INT (1+10) /* Sign + int32_t in decimal. */ 71#define STRFMT_MAXBUF_INT (1+10) /* Sign + int32_t in decimal. */
71#define STRFMT_MAXBUF_NUM LUAI_MAXNUMBER2STR 72#define STRFMT_MAXBUF_NUM 32 /* Must correspond with STRFMT_G14. */
72#define STRFMT_MAXBUF_PTR (2+2*sizeof(ptrdiff_t)) /* "0x" + hex ptr. */ 73#define STRFMT_MAXBUF_PTR (2+2*sizeof(ptrdiff_t)) /* "0x" + hex ptr. */
73 74
74/* Format parser. */ 75/* Format parser. */
@@ -83,10 +84,9 @@ static LJ_AINLINE void lj_strfmt_init(FormatState *fs, const char *p, MSize len)
83 84
84/* Raw conversions. */ 85/* Raw conversions. */
85LJ_FUNC char * LJ_FASTCALL lj_strfmt_wint(char *p, int32_t k); 86LJ_FUNC char * LJ_FASTCALL lj_strfmt_wint(char *p, int32_t k);
86LJ_FUNC char * LJ_FASTCALL lj_strfmt_wnum(char *p, cTValue *o);
87LJ_FUNC char * LJ_FASTCALL lj_strfmt_wptr(char *p, const void *v); 87LJ_FUNC char * LJ_FASTCALL lj_strfmt_wptr(char *p, const void *v);
88LJ_FUNC char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v); 88LJ_FUNC char * LJ_FASTCALL lj_strfmt_wuleb128(char *p, uint32_t v);
89LJ_FUNC const char *lj_strfmt_wstrnum(char *buf, cTValue *o, MSize *lenp); 89LJ_FUNC const char *lj_strfmt_wstrnum(lua_State *L, cTValue *o, MSize *lenp);
90 90
91/* Unformatted conversions to buffer. */ 91/* Unformatted conversions to buffer. */
92LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k); 92LJ_FUNC SBuf * LJ_FASTCALL lj_strfmt_putint(SBuf *sb, int32_t k);
diff --git a/src/lj_strfmt_num.c b/src/lj_strfmt_num.c
new file mode 100644
index 00000000..577795e0
--- /dev/null
+++ b/src/lj_strfmt_num.c
@@ -0,0 +1,591 @@
1/*
2** String formatting for floating-point numbers.
3** Copyright (C) 2005-2015 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
28static const int16_t rescale_e[] = { RESCALE_EXPONENTS(-, +) };
29static 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*/
37static 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 */
55static 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. */
63static 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. */
73static 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). */
124static 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). */
157static 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). */
214static 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. */
246static 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. */
269static 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 t.u64 -= 2; /* Convert 2ulp below (later we convert 2ulp above). */
368 nd[0] = 0x100000 | (t.u32.hi & 0xfffff);
369 e = ((t.u32.hi >> 20) & 0x7ff) - 1075 - (ND_MUL2K_MAX_SHIFT < 29);
370 goto load_t_lo; rescale_failed:
371 t.n = n;
372 e = (t.u32.hi >> 20) & 0x7ff;
373 ndebias = ndhi = 0;
374 }
375 }
376 nd[0] = t.u32.hi & 0xfffff;
377 if (e == 0) e++; else nd[0] |= 0x100000;
378 e -= 1043;
379 if (t.u32.lo) {
380 e -= 32 + (ND_MUL2K_MAX_SHIFT < 29); load_t_lo:
381#if ND_MUL2K_MAX_SHIFT >= 29
382 nd[0] = (nd[0] << 3) | (t.u32.lo >> 29);
383 ndhi = nd_mul2k(nd, ndhi, 29, t.u32.lo & 0x1fffffff, sf);
384#elif ND_MUL2K_MAX_SHIFT >= 11
385 ndhi = nd_mul2k(nd, ndhi, 11, t.u32.lo >> 21, sf);
386 ndhi = nd_mul2k(nd, ndhi, 11, (t.u32.lo >> 10) & 0x7ff, sf);
387 ndhi = nd_mul2k(nd, ndhi, 11, (t.u32.lo << 1) & 0x7ff, sf);
388#else
389#error "ND_MUL2K_MAX_SHIFT too small"
390#endif
391 }
392 if (e >= 0) {
393 ndhi = nd_mul2k(nd, ndhi, (uint32_t)e, 0, sf);
394 ndlo = 0;
395 } else {
396 ndlo = nd_div2k(nd, ndhi, (uint32_t)-e, sf);
397 if (ndhi && !nd[ndhi]) ndhi--;
398 }
399 /* abs(n) == nd * 10^ndebias (for slightly loose interpretation of ==) */
400 if ((sf & STRFMT_T_FP_E)) {
401 /* %e or %g - assume %e and start by calculating nd's exponent (nde). */
402 char eprefix = '+';
403 int32_t nde = -1;
404 MSize hilen;
405 if (ndlo && !nd[ndhi]) {
406 ndhi = 64; do {} while (!nd[--ndhi]);
407 nde -= 64 * 9;
408 }
409 hilen = ndigits_dec(nd[ndhi]);
410 nde += ndhi * 9 + hilen;
411 if (ndebias) {
412 /*
413 ** Rescaling was performed, but this introduced some error, and might
414 ** have pushed us across a rounding boundary. We check whether this
415 ** error affected the result by introducing even more error (2ulp in
416 ** either direction), and seeing whether a roundary boundary was
417 ** crossed. Having already converted the -2ulp case, we save off its
418 ** most significant digits, convert the +2ulp case, and compare them.
419 */
420 int32_t eidx = e + 70 + (ND_MUL2K_MAX_SHIFT < 29)
421 + (t.u32.lo >= 0xfffffffe && !(~t.u32.hi << 12));
422 const int8_t *m_e = four_ulp_m_e + eidx * 2;
423 lua_assert(0 <= eidx && eidx < 128);
424 nd[33] = nd[ndhi];
425 nd[32] = nd[(ndhi - 1) & 0x3f];
426 nd[31] = nd[(ndhi - 2) & 0x3f];
427 nd_add_m10e(nd, ndhi, (uint8_t)*m_e, m_e[1]);
428 if (LJ_UNLIKELY(!nd_similar(nd, ndhi, nd + 33, hilen, prec + 1))) {
429 goto rescale_failed;
430 }
431 }
432 if ((int32_t)(prec - nde) < (0x3f & -(int32_t)ndlo) * 9) {
433 /* Precision is sufficiently low as to maybe require rounding. */
434 ndhi = nd_add_m10e(nd, ndhi, 5, nde - prec - 1);
435 nde += (hilen != ndigits_dec(nd[ndhi]));
436 }
437 nde += ndebias;
438 if ((sf & STRFMT_T_FP_F)) {
439 /* %g */
440 if ((int32_t)prec >= nde && nde >= -4) {
441 if (nde < 0) ndhi = 0;
442 prec -= nde;
443 goto g_format_like_f;
444 } else if (!(sf & STRFMT_F_ALT) && prec && width > 5) {
445 /* Decrease precision in order to strip trailing zeroes. */
446 char tail[9];
447 uint32_t maxprec = hilen - 1 + ((ndhi - ndlo) & 0x3f) * 9;
448 if (prec >= maxprec) prec = maxprec;
449 else ndlo = (ndhi - (((int32_t)(prec - hilen) + 9) / 9)) & 0x3f;
450 i = prec - hilen - (((ndhi - ndlo) & 0x3f) * 9) + 10;
451 lj_strfmt_wuint9(tail, nd[ndlo]);
452 while (prec && tail[--i] == '0') {
453 prec--;
454 if (!i) {
455 if (ndlo == ndhi) { prec = 0; break; }
456 lj_strfmt_wuint9(tail, nd[++ndlo]);
457 i = 9;
458 }
459 }
460 }
461 }
462 if (nde < 0) {
463 /* Make nde non-negative. */
464 eprefix = '-';
465 nde = -nde;
466 }
467 len = 3 + prec + (prefix != 0) + ndigits_dec((uint32_t)nde) + (nde < 10)
468 + ((prec | (sf & STRFMT_F_ALT)) != 0);
469 if (!p) p = lj_buf_more(sb, (width > len ? width : len) + 5);
470 if (!(sf & (STRFMT_F_LEFT | STRFMT_F_ZERO))) {
471 while (width-- > len) *p++ = ' ';
472 }
473 if (prefix) *p++ = prefix;
474 if ((sf & (STRFMT_F_LEFT | STRFMT_F_ZERO)) == STRFMT_F_ZERO) {
475 while (width-- > len) *p++ = '0';
476 }
477 q = lj_strfmt_wint(p + 1, nd[ndhi]);
478 p[0] = p[1]; /* Put leading digit in the correct place. */
479 if ((prec | (sf & STRFMT_F_ALT))) {
480 /* Emit fractional part. */
481 p[1] = '.'; p += 2;
482 prec -= (q - p); p = q; /* Account for the digits already emitted. */
483 /* Then emit chunks of 9 digits (this may emit 8 digits too many). */
484 for (i = ndhi; (int32_t)prec > 0 && i != ndlo; prec -= 9) {
485 i = (i - 1) & 0x3f;
486 p = lj_strfmt_wuint9(p, nd[i]);
487 }
488 if ((sf & STRFMT_T_FP_F) && !(sf & STRFMT_F_ALT)) {
489 /* %g (and not %#g) - strip trailing zeroes. */
490 p += (int32_t)prec & ((int32_t)prec >> 31);
491 while (p[-1] == '0') p--;
492 if (p[-1] == '.') p--;
493 } else {
494 /* %e (or %#g) - emit trailing zeroes. */
495 while ((int32_t)prec > 0) { *p++ = '0'; prec--; }
496 p += (int32_t)prec;
497 }
498 } else {
499 p++;
500 }
501 *p++ = (sf & STRFMT_F_UPPER) ? 'E' : 'e';
502 *p++ = eprefix; /* + or - */
503 if (nde < 10) *p++ = '0'; /* Always at least two digits of exponent. */
504 p = lj_strfmt_wint(p, nde);
505 } else {
506 /* %f (or, shortly, %g in %f style) */
507 if (prec < (MSize)(0x3f & -(int32_t)ndlo) * 9) {
508 /* Precision is sufficiently low as to maybe require rounding. */
509 ndhi = nd_add_m10e(nd, ndhi, 5, 0 - prec - 1);
510 }
511 g_format_like_f:
512 if ((sf & STRFMT_T_FP_E) && !(sf & STRFMT_F_ALT) && prec && width) {
513 /* Decrease precision in order to strip trailing zeroes. */
514 if (ndlo) {
515 /* nd has a fractional part; we need to look at its digits. */
516 char tail[9];
517 uint32_t maxprec = (64 - ndlo) * 9;
518 if (prec >= maxprec) prec = maxprec;
519 else ndlo = 64 - (prec + 8) / 9;
520 i = prec - ((63 - ndlo) * 9);
521 lj_strfmt_wuint9(tail, nd[ndlo]);
522 while (prec && tail[--i] == '0') {
523 prec--;
524 if (!i) {
525 if (ndlo == 63) { prec = 0; break; }
526 lj_strfmt_wuint9(tail, nd[++ndlo]);
527 i = 9;
528 }
529 }
530 } else {
531 /* nd has no fractional part, so precision goes straight to zero. */
532 prec = 0;
533 }
534 }
535 len = ndhi * 9 + ndigits_dec(nd[ndhi]) + prec + (prefix != 0)
536 + ((prec | (sf & STRFMT_F_ALT)) != 0);
537 if (!p) p = lj_buf_more(sb, (width > len ? width : len) + 8);
538 if (!(sf & (STRFMT_F_LEFT | STRFMT_F_ZERO))) {
539 while (width-- > len) *p++ = ' ';
540 }
541 if (prefix) *p++ = prefix;
542 if ((sf & (STRFMT_F_LEFT | STRFMT_F_ZERO)) == STRFMT_F_ZERO) {
543 while (width-- > len) *p++ = '0';
544 }
545 /* Emit integer part. */
546 p = lj_strfmt_wint(p, nd[ndhi]);
547 i = ndhi;
548 while (i) p = lj_strfmt_wuint9(p, nd[--i]);
549 if ((prec | (sf & STRFMT_F_ALT))) {
550 /* Emit fractional part. */
551 *p++ = '.';
552 /* Emit chunks of 9 digits (this may emit 8 digits too many). */
553 while ((int32_t)prec > 0 && i != ndlo) {
554 i = (i - 1) & 0x3f;
555 p = lj_strfmt_wuint9(p, nd[i]);
556 prec -= 9;
557 }
558 if ((sf & STRFMT_T_FP_E) && !(sf & STRFMT_F_ALT)) {
559 /* %g (and not %#g) - strip trailing zeroes. */
560 p += (int32_t)prec & ((int32_t)prec >> 31);
561 while (p[-1] == '0') p--;
562 if (p[-1] == '.') p--;
563 } else {
564 /* %f (or %#g) - emit trailing zeroes. */
565 while ((int32_t)prec > 0) { *p++ = '0'; prec--; }
566 p += (int32_t)prec;
567 }
568 }
569 }
570 }
571 if ((sf & STRFMT_F_LEFT)) while (width-- > len) *p++ = ' ';
572 return p;
573}
574
575/* Add formatted floating-point number to buffer. */
576SBuf *lj_strfmt_putfnum(SBuf *sb, SFormat sf, lua_Number n)
577{
578 setsbufP(sb, lj_strfmt_wfnum(sb, sf, n, NULL));
579 return sb;
580}
581
582/* -- Conversions to strings ---------------------------------------------- */
583
584/* Convert number to string. */
585GCstr * LJ_FASTCALL lj_strfmt_num(lua_State *L, cTValue *o)
586{
587 char buf[STRFMT_MAXBUF_NUM];
588 MSize len = (MSize)(lj_strfmt_wfnum(NULL, STRFMT_G14, o->n, buf) - buf);
589 return lj_str_new(L, buf, len);
590}
591
diff --git a/src/ljamalg.c b/src/ljamalg.c
index be0c52d7..93b81f2a 100644
--- a/src/ljamalg.c
+++ b/src/ljamalg.c
@@ -46,6 +46,7 @@
46#include "lj_vmmath.c" 46#include "lj_vmmath.c"
47#include "lj_strscan.c" 47#include "lj_strscan.c"
48#include "lj_strfmt.c" 48#include "lj_strfmt.c"
49#include "lj_strfmt_num.c"
49#include "lj_api.c" 50#include "lj_api.c"
50#include "lj_profile.c" 51#include "lj_profile.c"
51#include "lj_lex.c" 52#include "lj_lex.c"