From 8c9a14c01e7dd52776a2f97fdcc51b28288f6d49 Mon Sep 17 00:00:00 2001 From: gdr-ftp Date: Tue, 24 Mar 1998 16:20:30 +0000 Subject: [PATCH] cvt.c: The ecvt(), fcvt(), and __dtoa() routines were generally rewritten to address the problem of printing floating point numbers (they sometimes came out wrong, especially representations of zero). __dtoa was written from the description in the BSD sources (note that the comment of it being "like ecvt/fcvt other than truncating trailing zeros") is not quite accurate where it comes to the rve pointer or the printing of zero values. __dtoa is still expected to be wrong for any modes other than 2 and 3, however those modes are not used by anything in libc yet. Fix them when they pop up. BSD has not ecvt/fcvt routines, so these have been written based on the man page and observed behavior of the Linux implementation. There is no gcvt yet. --- lib/libc/stdlib/cvt.c | 64 +++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/lib/libc/stdlib/cvt.c b/lib/libc/stdlib/cvt.c index 411f76c..9d958fa 100644 --- a/lib/libc/stdlib/cvt.c +++ b/lib/libc/stdlib/cvt.c @@ -2,7 +2,7 @@ * Floating point conversion routines. * Devin Reade, 1997. * - * $Id: cvt.c,v 1.2 1997/09/21 06:20:37 gdr Exp $ + * $Id: cvt.c,v 1.3 1998/03/24 16:20:30 gdr-ftp Exp $ * * This file is formatted with tab stops every 8 columns. */ @@ -16,16 +16,31 @@ segment "libc_stdlb"; #include #include -char * -ecvt (double number, size_t ndigits, int *decpt, int *sign) +static char * +_cvt (double number, size_t ndigits, int *decpt, int *sign, short style) { static DecForm convert; static Decimal d; - - convert.style = FLOATDECIMAL; + int i; + char *p; + + convert.style = style; if (ndigits > SIGDIGLEN) { ndigits = SIGDIGLEN; } + if (!number) { + /* + * special case zero, for which SANE doesn't give the + * documented format. + */ + p = d.sig.text; + for (i=0; i SIGDIGLEN) { - ndigits = SIGDIGLEN; - } - convert.digits = ndigits; - s_num2dec(&convert, number, &d); - *decpt = (int)d.sig.length + d.exp; - *sign = d.sgn; - *(d.sig.text + (int)d.sig.length) = '\0'; /* depends on d.sig.unused */ - return d.sig.text; +char * +fcvt (double number, size_t ndigits, int *decpt, int *sign) { + return _cvt (number, ndigits, decpt, sign, FIXEDDECIMAL); } /* __dtoa: These are the comments from the BSD implementation of @@ -120,15 +127,20 @@ mode0: /* this label doesn't belong here */ goto mode0; /* TEMP KLUDGE */ } - /* truncate trailing zeros */ - p = result; - while (*p) p++; - p--; - while ((p > result) && (*p == '0')) { - *p-- = '\0'; + /* special case the exponent for 0.0 */ + if (*decpt == 0) { + *decpt = 1; } + + /* truncate trailing zeros */ if (rve != NULL) { - *rve = p + 1; + p = result; + while (*p) p++; + --p; + while ((p > result) && (*p == '0')) { + --p; + } + *rve = p+1; } /* set decimal point for NaNs and Infinities */