On Fri, Oct 19, 2018 at 3:43 PM Bernhard Reutner-Fischer <rep.dot....@gmail.com> wrote: > On Fri, 19 Oct 2018 at 15:30, Bernhard Reutner-Fischer > <rep.dot....@gmail.com> wrote: > > On Fri, 19 Oct 2018 at 11:03, Cristian Ionescu-Idbohrn > > <cristian.ionescu-idbo...@axis.com> wrote: > > Oh, an I should mention that on a 64bit box we diverge from coreutils printf: > > $ printf "%f\n" ' +18446744073709551614' > 18446744073709551614.000000 > $ ./busybox printf "%f\n" ' +18446744073709551614' > 18446744073709551616.000000
It's far worse than that: $ ./busybox printf "%f\n" 18446744073709550592 18446744073709553665 18446744073709551616.000000 18446744073709551616.000000 64-bit double's mantissa is only 53 bits... With "long double" shenanigans, I managed to "improve" this to: $ ./busybox printf "%f\n" 18446744073709550592 18446744073709553665 18446744073709550591.500000 18446744073709553663.500000 at this cost: function old new delta printf_main 909 976 +67 strtold - 19 +19 print_direc 457 475 +18 conv_strtod 54 61 +7 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 3/0 up/down: 130/0) Total: 111 bytes See attached. Do you think it's worth it?
diff --git a/coreutils/printf.c b/coreutils/printf.c index 67d3b2eda..215f4fef9 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -120,12 +120,18 @@ static void FAST_FUNC conv_strtoll(const char *arg, void *result) static void FAST_FUNC conv_strtod(const char *arg, void *result) { char *end; - /* Well, this one allows leading whitespace... so what? */ - /* What I like much less is that "-" accepted too! :( */ - *(double*)result = strtod(arg, &end); + + /* If long double is no different than double, avoid using strtold() */ + if (sizeof(double) == sizeof(long double)) + /* Well, this one allows leading whitespace... so what? */ + /* What I like much less is that "-" accepted too! :( */ + *(long double*)result = strtod(arg, &end); + else + *(long double*)result = strtold(arg, &end); + if (end[0]) { errno = ERANGE; - *(double*)result = 0; + *(long double*)result = 0; } } @@ -144,9 +150,9 @@ static long long my_xstrtoll(const char *arg) result = 0; return result; } -static double my_xstrtod(const char *arg) +static long double my_xstrtod(const char *arg) { - double result; + long double result; multiconvert(arg, &result, conv_strtod); return result; } @@ -187,7 +193,6 @@ static void print_direc(char *format, unsigned fmt_length, const char *argument) { long long llv; - double dv; char saved; char *have_prec, *have_width; @@ -255,17 +260,35 @@ static void print_direc(char *format, unsigned fmt_length, case 'E': case 'g': case 'G': - dv = my_xstrtod(argument); - if (!have_width) { - if (!have_prec) - printf(format, dv); - else - printf(format, precision, dv); + if (sizeof(double) == sizeof(long double)) { + double dv; + dv = my_xstrtod(argument); + if (!have_width) { + if (!have_prec) + printf(format, dv); + else + printf(format, precision, dv); + } else { + if (!have_prec) + printf(format, field_width, dv); + else + printf(format, field_width, precision, dv); + } } else { - if (!have_prec) - printf(format, field_width, dv); - else - printf(format, field_width, precision, dv); + /* Parsing code added "L" prefix (a-la "%Lf") */ + long double dv; + dv = my_xstrtod(argument); + if (!have_width) { + if (!have_prec) + printf(format, dv); + else + printf(format, precision, dv); + } else { + if (!have_prec) + printf(format, field_width, dv); + else + printf(format, field_width, precision, dv); + } } break; } /* switch */ @@ -371,6 +394,18 @@ static char **print_formatted(char *f, char **argv, int *conv_err) //bb_error_msg("<%s>", p); direc_length += 2; direc_start = p; + } else + if (sizeof(double) < sizeof(long double) + && p - format_chars <= 10 + ) { + /* it is one of "feEgG" */ + p = xmalloc(direc_length + 2); + memcpy(p, direc_start, direc_length); + p[direc_length] = p[direc_length - 1]; + p[direc_length - 1] = 'L'; + //bb_error_msg("<%s>", p); + direc_length += 1; + direc_start = p; } else { p = NULL; }
_______________________________________________ busybox mailing list busybox@busybox.net http://lists.busybox.net/mailman/listinfo/busybox