diff --git a/quickjs.c b/quickjs.c index 7916013..3936eec 100644 --- a/quickjs.c +++ b/quickjs.c @@ -67,6 +67,16 @@ #define CONFIG_PRINTF_RNDN #endif +#ifdef CONFIG_PRINTF_RNDN +#if !defined(FE_DOWNWARD) || !defined(FE_UPWARD) +#ifdef CONFIG_BIGNUM +#define CONFIG_DTOA_LIBBF +#else +#error "CONFIG_BIGNUM required if printf is RNDN and there is no fenv support" +#endif +#endif +#endif + /* define to include Atomics.* operations which depend on the OS threads */ #if !defined(EMSCRIPTEN) @@ -11299,6 +11309,11 @@ static char *i64toa(char *buf_end, int64_t n, unsigned int base) return q; } +/* maximum buffer size for js_dtoa */ +#define JS_DTOA_BUF_SIZE 128 + +#ifndef CONFIG_DTOA_LIBBF + /* buf1 contains the printf result */ static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf, int rounding_mode, char *buf1, int buf1_size) @@ -11318,9 +11333,6 @@ static void js_ecvt1(double d, int n_digits, int *decpt, int *sign, char *buf, *decpt = atoi(buf1 + n_digits + 2 + (n_digits > 1)) + 1; } -/* maximum buffer size for js_dtoa */ -#define JS_DTOA_BUF_SIZE 128 - /* needed because ecvt usually limits the number of digits to 17. Return the number of digits. */ static int js_ecvt(double d, int n_digits, int *decpt, int *sign, char *buf, @@ -11429,6 +11441,8 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits) js_fcvt1(buf, buf_size, d, n_digits, rounding_mode); } +#endif /* CONFIG_DTOA_LIBBF */ + /* radix != 10 is only supported with flags = JS_DTOA_VAR_FORMAT */ /* use as many digits as necessary */ #define JS_DTOA_VAR_FORMAT (0 << 0) @@ -11442,8 +11456,10 @@ static void js_fcvt(char *buf, int buf_size, double d, int n_digits) /* XXX: slow and maybe not fully correct. Use libbf when it is fast enough. XXX: radix != 10 is only supported for small integers */ -static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) +static JSValue js_dtoa(JSContext *ctx, + double d, int radix, int n_digits, int flags) { + char buf[JS_DTOA_BUF_SIZE]; char *q; if (!isfinite(d)) { @@ -11465,6 +11481,25 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) ptr = i64toa(buf1 + sizeof(buf1), i64, radix); strcpy(buf, ptr); } else { +#ifdef CONFIG_DTOA_LIBBF + bf_flags_t bf_flags; + generic_conv: + bf_flags = BF_RNDNA; + switch (flags & 3) { + case JS_DTOA_VAR_FORMAT: + bf_flags |= BF_FTOA_FORMAT_FREE_MIN; + break; + case JS_DTOA_FIXED_FORMAT: + bf_flags |= BF_FTOA_FORMAT_FIXED; + break; + case JS_DTOA_FRAC_FORMAT: + bf_flags |= BF_FTOA_FORMAT_FRAC; + break; + } + if (flags & JS_DTOA_FORCE_EXP) + bf_flags |= BF_FTOA_FORCE_EXP; + return js_ftoa(ctx, JS_NewFloat64(ctx, d), radix, n_digits, bf_flags); +#else /* CONFIG_DTOA_LIBBF */ if (d == 0.0) d = 0.0; /* convert -0 to 0 */ if (flags == JS_DTOA_FRAC_FORMAT) { @@ -11528,14 +11563,8 @@ static void js_dtoa1(char *buf, double d, int radix, int n_digits, int flags) sprintf(q, "%d", p); } } +#endif /* CONFIG_DTOA_LIBBF */ } -} - -static JSValue js_dtoa(JSContext *ctx, - double d, int radix, int n_digits, int flags) -{ - char buf[JS_DTOA_BUF_SIZE]; - js_dtoa1(buf, d, radix, n_digits, flags); return JS_NewString(ctx, buf); }