From 38e93ede2b5dd2de1d9a41bf5967387c082bc709 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 15 Feb 2019 09:59:50 -0600 Subject: [PATCH] Revert "libs/libc/stdio: Fix the %f floating point output format." The previous implementation was probably corect. On Cygwin with GCC I see this: int main(int argc, char **argv) { printf("Value 1.2 is: [%f]\n", 1.2); printf("Value 0.1 is: [%f]\n", 0.1); printf("Value 0.0: [%f]\n", 0.0); printf("Value 347.6872: [%f]\n", 347.6872); } Generates output Value 1.2 is: [1.200000] Value 0.1 is: [0.100000] Value 0.0: [0.000000] Value 347.6872: [347.687200] This reverts commit eb0223bc7febb4888b55bb0163803aa2404ef2e6. --- libs/libc/stdio/Kconfig | 5 +-- libs/libc/stdio/lib_libdtoa.c | 58 ++++++------------------------- libs/libc/stdio/lib_libvsprintf.c | 11 ++++++ 3 files changed, 24 insertions(+), 50 deletions(-) diff --git a/libs/libc/stdio/Kconfig b/libs/libc/stdio/Kconfig index 11d93e3893..fc30f34bfa 100644 --- a/libs/libc/stdio/Kconfig +++ b/libs/libc/stdio/Kconfig @@ -121,8 +121,9 @@ config NANO_PRINTF depends on !LIBC_LONG_LONG ---help--- Replace printf code with version from newlib-nano. This version - provides adds support for the 'g' format. However, it does not - include 'long long' support. + provides improved floating point output support, including 'g' mode + as well as making the default 'f' format include digits past the + decimal point. However, it does not include 'long long' support. config NANO_PRINTLEVEL int "Nano printf support level" diff --git a/libs/libc/stdio/lib_libdtoa.c b/libs/libc/stdio/lib_libdtoa.c index 1796393a65..861930b3f0 100644 --- a/libs/libc/stdio/lib_libdtoa.c +++ b/libs/libc/stdio/lib_libdtoa.c @@ -46,7 +46,6 @@ #include -#include #include #include @@ -68,17 +67,6 @@ # define MAX(a,b) (a > b ? a : b) #endif -/* Use (almost) the maximim precision with %f format if no precision is - * specified. We do not use the full precision beause the least significant - * digits are probably garbage. - * - * REVISIT: This should be smarter. 15 digits is the maximum size of the - * number. The maximum precision is really 15 minus the number of digits - * in the integer part. - */ - -#define DOUBLE_PRECISON_MAX 13 /* vs 15 which is the maximum */ - /**************************************************************************** * Private Functions ****************************************************************************/ @@ -144,7 +132,6 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, { FAR char *digits; /* String returned by __dtoa */ FAR char *rve; /* Points to the end of the return value */ - bool hasdot; /* True: precision specified */ int expt; /* Integer value of exponent */ int numlen; /* Actual number of digits returned by cvt */ int nchars; /* Number of characters to print */ @@ -162,14 +149,6 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, DEBUGASSERT(up_interrupt_context() == false); #endif - /* Set to default precision if none specified */ - - hasdot = IS_HASDOT(flags); - if (!hasdot && prec == 0) - { - prec = DOUBLE_PRECISON_MAX; - } - /* Special handling for NaN and Infinity */ if (isnan(value)) @@ -199,8 +178,8 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, /* Perform the conversion */ - digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve); - numlen = rve - digits; + digits = __dtoa(value, 3, prec, &expt, &dsgn, &rve); + numlen = rve - digits; /* Avoid precision error from missing trailing zeroes */ @@ -219,7 +198,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, * the print precision. */ - if (value == 0 || (expt < (hasdot ? -prec : 0))) + if (value == 0 || expt < -prec) { /* kludge for __dtoa irregularity */ @@ -229,20 +208,13 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, * particular precision is requested. */ - if ((prec > 0 && hasdot) || IS_ALTFORM(flags)) + if (prec > 0 || IS_ALTFORM(flags)) { obj->put(obj, '.'); /* Always print at least one digit to the right of the decimal point. */ - if (hasdot) - { - prec = MAX(1, prec); - } - else - { - prec = MAX(1, numlen); - } + prec = MAX(1, prec); } } @@ -250,6 +222,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, else { + /* Handle the case where the value is less than 1.0 (in magnitude) and * will need a leading zero. */ @@ -266,7 +239,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, /* Print any leading zeros to the right of the decimal point */ - if (expt < 0 || hasdot) + if (expt < 0) { nchars = MIN(-expt, prec); zeroes(obj, nchars); @@ -304,8 +277,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, * requested. */ - if (numlen > 0 || (prec > 0 && hasdot) || - IS_ALTFORM(flags)) + if (numlen > 0 || prec > 0 || IS_ALTFORM(flags)) { /* Print the decimal point */ @@ -315,14 +287,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, * point. */ - if (hasdot) - { - prec = MAX(1, prec); - } - else - { - prec = MAX(1, numlen); - } + prec = MAX(1, prec); } } @@ -354,10 +319,7 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec, /* Finally, print any trailing zeroes */ - if (hasdot) - { - zeroes(obj, prec); - } + zeroes(obj, prec); } /**************************************************************************** diff --git a/libs/libc/stdio/lib_libvsprintf.c b/libs/libc/stdio/lib_libvsprintf.c index d84b785486..2d8758a26e 100644 --- a/libs/libc/stdio/lib_libvsprintf.c +++ b/libs/libc/stdio/lib_libvsprintf.c @@ -118,6 +118,10 @@ # define FMT_PREV src-- /* Backup to the previous character */ #endif +/* Default precision to use with %f format if no precision is specified. */ + +#define FLOAT_PRECISION_DEFAULT 6 + /**************************************************************************** * Private Type Declarations ****************************************************************************/ @@ -1555,6 +1559,13 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const IPTR char *src, double dblval = va_arg(ap, double); int dblsize; + /* Set to default precision if none specified */ + + if (!IS_HASDOT(flags) && trunc == 0) + { + trunc = FLOAT_PRECISION_DEFAULT; + } + /* Get the width of the output */ dblsize = getdblsize(FMT_CHAR, trunc, flags, dblval);