From 37da2899f40661e3e9631e497da8dc59b971cbd0 Mon Sep 17 00:00:00 2001 From: "Charles.Forsyth" Date: Fri, 22 Dec 2006 17:07:39 +0000 Subject: 20060303a --- libmath/gfltconv.c | 123 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 libmath/gfltconv.c (limited to 'libmath/gfltconv.c') diff --git a/libmath/gfltconv.c b/libmath/gfltconv.c new file mode 100644 index 00000000..497b71f9 --- /dev/null +++ b/libmath/gfltconv.c @@ -0,0 +1,123 @@ +#include "lib9.h" +#include "mathi.h" +extern char *dtoa(double, int, int, int *, int *, char **); +extern void freedtoa(char*); +extern int _fmtcpy(Fmt*, void*, int, int); + +enum +{ + NONE = -1000, + FDIGIT = 20, + FDEFLT = 6, + NSIGNIF = 17 +}; + +int +gfltconv(Fmt *f) +{ + int flags = f->flags; + int precision; + int fmt = f->r; + double d; + int echr, exponent, sign, ndig, nout, i; + char *digits, *edigits, ebuf[32], *eptr; + char out[64], *pout; + + d = va_arg(f->args, double); + echr = 'e'; + precision = FDEFLT; + if(f->flags & FmtPrec) + precision = f->prec; + if(precision > FDIGIT) + precision = FDIGIT; + switch(fmt){ + case 'f': + digits = dtoa(d, 3, precision, &exponent, &sign, &edigits); + break; + case 0x00c9: /* L'É' */ + case 'E': + echr = 'E'; + fmt = 'e'; + /* fall through */ + case 'e': + digits = dtoa(d, 2, 1+precision, &exponent, &sign, &edigits); + break; + case 'G': + echr = 'E'; + /* fall through */ + default: + case 'g': + if((flags&(FmtWidth|FmtPrec)) == 0){ + g_fmt(out, d, echr); + f->flags &= FmtWidth|FmtLeft; + return _fmtcpy(f, out, strlen(out), strlen(out)); + } + if (precision > 0) + digits = dtoa(d, 2, precision, &exponent, &sign, &edigits); + else { + digits = dtoa(d, 0, precision, &exponent, &sign, &edigits); + precision = edigits - digits; + if (exponent > precision && exponent <= precision + 4) + precision = exponent; + } + if(exponent >= -3 && exponent <= precision){ + fmt = 'f'; + precision -= exponent; + }else{ + fmt = 'e'; + --precision; + } + break; + } + if (exponent == 9999) { + /* Infinity or Nan */ + precision = 0; + exponent = edigits - digits; + fmt = 'f'; + } + ndig = edigits-digits; + if((f->r=='g' || f->r=='G') && !(flags&FmtSharp)){ /* knock off trailing zeros */ + if(fmt == 'f'){ + if(precision+exponent > ndig) { + precision = ndig - exponent; + if(precision < 0) + precision = 0; + } + } + else{ + if(precision > ndig-1) precision = ndig-1; + } + } + eptr = ebuf; + if(fmt != 'f'){ /* exponent */ + for(i=exponent<=0?1-exponent:exponent-1; i; i/=10) + *eptr++ = '0' + i%10; + while(eptr0 || flags&FmtSharp) *pout++ = '.'; + for(i=0; i!=precision; i++) + *pout++ = 0<=i+exponent && i+exponent0 || flags&FmtSharp) *pout++ = '.'; + for(i=0; i!=precision; i++) *pout++ = iebuf) *pout++ = *--eptr; + } + *pout = 0; + freedtoa(digits); + f->flags &= FmtWidth|FmtLeft; + nout = pout-out; + return _fmtcpy(f, out, nout, nout); +} -- cgit v1.2.3