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.
This commit is contained in:
gdr-ftp 1998-03-24 16:20:30 +00:00
parent e9cd1d1fb9
commit 8c9a14c01e
1 changed files with 38 additions and 26 deletions

View File

@ -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 <sane.h>
#include <math.h>
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<ndigits; i++) {
*p++ = '0';
}
*p = '\0';
*decpt = *sign = 0;
return d.sig.text;
}
convert.digits = ndigits;
s_num2dec(&convert, number, &d);
*decpt = (int)d.sig.length + d.exp;
@ -35,21 +50,13 @@ ecvt (double number, size_t ndigits, int *decpt, int *sign)
}
char *
fcvt (double number, size_t ndigits, int *decpt, int *sign)
{
static DecForm convert;
static Decimal d;
ecvt (double number, size_t ndigits, int *decpt, int *sign) {
return _cvt (number, ndigits, decpt, sign, FLOATDECIMAL);
}
convert.style = FIXEDDECIMAL;
if (ndigits > 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 */