From b61380aa733a69c6bf2840758d58b6f47f33a3f8 Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 21 Aug 2021 05:52:17 +0300 Subject: [PATCH] better number formatting --- src/builtins/sysfn.c | 6 ++---- src/core/stuff.c | 26 ++++++++++++++++++-------- src/core/stuff.h | 2 ++ 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 62ee84f5..f11800bf 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -68,11 +68,9 @@ B glyph_c1(B t, B x) { } B repr_c1(B t, B x) { - #define BL 100 if (isF64(x)) { - char buf[BL]; - snprintf(buf, BL, "%.14g", x.f); - return m_str8(strlen(buf), buf); + NUM_FMT_BUF(buf, x.f); + return fromUTF8(buf, strlen(buf)); } else { #if FORMATTER return bqn_repr(x); diff --git a/src/core/stuff.c b/src/core/stuff.c index c70244c3..0bf33fbf 100644 --- a/src/core/stuff.c +++ b/src/core/stuff.c @@ -107,7 +107,8 @@ NOINLINE void arr_print(B x) { // should accept refc=0 arguments for debugging p NOINLINE void print(B x) { if (isF64(x)) { - printf("%.14g", x.f); + NUM_FMT_BUF(buf, x.f); + printf("%s", buf); } else if (isC32(x)) { if ((u32)x.u>=32) { printf("'"); printUTF8((u32)x.u); printf("'"); } else if((u32)x.u>15) printf("\\x%x", (u32)x.u); @@ -139,7 +140,7 @@ NOINLINE void print(B x) { NOINLINE void printRaw(B x) { if (isAtm(x)) { - if (isF64(x)) printf("%.14g", x.f); + if (isF64(x)) { NUM_FMT_BUF(buf, x.f); printf("%s", buf); } else if (isC32(x)) printUTF8((u32)x.u); else thrM("bad printRaw argument: atom arguments should be either numerical or characters"); } else { @@ -155,6 +156,20 @@ NOINLINE void printRaw(B x) { } } } +i32 num_fmt(char buf[30], f64 x) { + snprintf(buf, 30, "%.16g", x); // should be %.17g to (probably?) never lose precision, but that also makes things ugly + i32 len = strlen(buf); + if (buf[0] == 'i') { + buf[0] = 0xE2; buf[1] = 0x88; buf[2] = 0x9E; buf[3] = 0; + } else if (buf[buf[0]=='-'?1:0] == 'n') { + buf[0] = 'N'; buf[1] = 'a'; buf[2] = 'N'; buf[3] = 0; + } else if (buf[0] == '-') { + memmove(buf+2, buf+1, len+1); + buf[0] = 0xC2; buf[1] = 0xAF; // "¯"" + len+= 1; + } + return len; +} NOINLINE B do_fmt(B s, char* p, va_list a) { char buf[30]; char c; @@ -230,12 +245,7 @@ NOINLINE B do_fmt(B s, char* p, va_list a) { break; } case 'f': { - f64 f = va_arg(a, f64); - if (f<0) { - AU("¯"); - f=-f; - } - snprintf(buf, 30, "%.14g", f); + NUM_FMT_BUF(buf, va_arg(a, f64)); A8(buf); break; } diff --git a/src/core/stuff.h b/src/core/stuff.h index 2d572f6d..8c9bbdc9 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -96,6 +96,8 @@ static bool isNumEl(u8 elt) { return elt==el_i32 | elt==el_f64; } B m_str8l(char* s); B fromUTF8l(char* x); +i32 num_fmt(char buf[30], f64 x); +#define NUM_FMT_BUF(N,X) char N[30]; num_fmt(N, X); B append_fmt(B s, char* p, ...); B make_fmt(char* p, ...); #define AJOIN(X) s = vec_join(s,X) // consumes X