From 26d20001b6e9077a6d67ab2305fc96966d156518 Mon Sep 17 00:00:00 2001 From: Vsevolod Stakhov Date: Sun, 19 May 2019 10:35:34 +0100 Subject: [PATCH] [Fix] Fix some more corner cases for fpconv --- contrib/fpconv/fpconv.c | 46 +++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/contrib/fpconv/fpconv.c b/contrib/fpconv/fpconv.c index 4ec2e3560..3b96af270 100644 --- a/contrib/fpconv/fpconv.c +++ b/contrib/fpconv/fpconv.c @@ -236,26 +236,24 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg, return ndigits + 2 + offset; } else { - /* Overflow */ - dest[2] = '0'; - return 3; + goto scientific_fallback; } /* fp > 1.0 */ } else { - memcpy(dest, digits, offset); - /* Overflow check */ if (ndigits <= 23) { + memcpy(dest, digits, offset); dest[offset] = '.'; memcpy(dest + offset + 1, digits + offset, ndigits - offset); return ndigits + 1; } - return offset; + goto scientific_fallback; } } +scientific_fallback: /* write decimal w/ scientific notation */ ndigits = minv(ndigits, 18 - neg); @@ -296,9 +294,18 @@ static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg, static int filter_special(double fp, char* dest) { + int nchars = 3; + if(fp == 0.0) { - dest[0] = '0'; - return 1; + if(get_dbits(fp) & signmask) { + dest[0] = '-'; + dest[1] = '0'; + return 2; + } + else { + dest[0] = '0'; + return 1; + } } uint64_t bits = get_dbits(fp); @@ -311,12 +318,18 @@ static int filter_special(double fp, char* dest) if(bits & fracmask) { dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n'; - } else { - dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f'; + if(get_dbits(fp) & signmask) { + dest[0] = '-'; + dest[1] = 'i'; dest[2] = 'n'; dest[3] = 'f'; + nchars = 4; + } + else { + dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f'; + } } - return 3; + return nchars; } int fpconv_dtoa(double d, char dest[24], bool scientific) @@ -326,11 +339,6 @@ int fpconv_dtoa(double d, char dest[24], bool scientific) int str_len = 0; bool neg = false; - if(get_dbits(d) & signmask) { - dest[0] = '-'; - str_len++; - neg = true; - } int spec = filter_special(d, dest + str_len); @@ -338,6 +346,12 @@ int fpconv_dtoa(double d, char dest[24], bool scientific) return str_len + spec; } + if(get_dbits(d) & signmask) { + dest[0] = '-'; + str_len++; + neg = true; + } + int K = 0; int ndigits = grisu2(d, digits, &K); -- 2.39.5