From de47eb59bb829423b1d0f47ba13099073999b3cb Mon Sep 17 00:00:00 2001 From: Nicolas Planel Date: Wed, 29 Oct 2003 16:07:11 +0000 Subject: Corporate Server 2.1.1 release --- mdk-stage1/dietlibc/lib/__dtostr.c | 190 ++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 77 deletions(-) (limited to 'mdk-stage1/dietlibc/lib/__dtostr.c') diff --git a/mdk-stage1/dietlibc/lib/__dtostr.c b/mdk-stage1/dietlibc/lib/__dtostr.c index e9a8a83d3..580258936 100644 --- a/mdk-stage1/dietlibc/lib/__dtostr.c +++ b/mdk-stage1/dietlibc/lib/__dtostr.c @@ -1,104 +1,140 @@ -#include +#include +#include +#include /* convert double to string. Helper for sprintf. */ -int __dtostr(double d,char *buf,int maxlen,int prec) { +static int copystring(char* buf,int maxlen, const char* s) { + int i; + for (i=0; i<3&&i>63; signed long e=((*x>>52)&((1<<11)-1))-1023; +#else +#if __BYTE_ORDER == __LITTLE_ENDIAN + signed long e=(((((unsigned long*)&d)[1])>>20)&((1<<11)-1))-1023; +#else + signed long e=(((*((unsigned long*)&d))>>20)&((1<<11)-1))-1023; +#endif +#endif /* unsigned long long m=*x & ((1ull<<52)-1); */ /* step 2: exponent is base 2, compute exponent for base 10 */ - signed long e10=1+(long)(e*0.30102999566398119802); /* log10(2) */ + signed long e10; /* step 3: calculate 10^e10 */ - int i; - double tmp=10.0; + unsigned int i; + double backup=d; + double tmp; char *oldbuf=buf; - int initial=1; + if (isnan(d)) return copystring(buf,maxlen,"nan"); + if ((i=isinf(d))) return copystring(buf,maxlen,i>0?"inf":"-inf"); + e10=1+(long)(e*0.30102999566398119802); /* log10(2) */ + /* Wir iterieren von Links bis wir bei 0 sind oder maxlen erreicht + * ist. Wenn maxlen erreicht ist, machen wir das nochmal in + * scientific notation. Wenn dann von prec noch was übrig ist, geben + * wir einen Dezimalpunkt aus und geben prec2 Nachkommastellen aus. + * Wenn prec2 Null ist, geben wir so viel Stellen aus, wie von prec + * noch übrig ist. */ if (d==0.0) { - *buf='0'; ++buf; - goto done; + prec2=prec2==0?1:prec2+2; + prec2=prec2>maxlen?8:prec2; + for (i=0; i=0) { + if (e10>0) { + int first=1; /* are we about to write the first digit? */ + tmp = 10.0; i=e10; while (i>10) { tmp=tmp*1e10; i-=10; } while (i>1) { tmp=tmp*10; --i; } - } else { - i=(e10=-e10); - while (i>10) { tmp=tmp*1e-10; i-=10; } - while (i>1) { tmp=tmp/10; --i; } - } - while (d/tmp<1) { - --e10; - tmp/=10.0; - } - /* step 4: see if precision is sufficient to display all digits */ - if (e10>prec) { - /* use scientific notation */ - int len=__dtostr(d/tmp,buf,maxlen,prec); - if (len==0) return 0; - maxlen-=len; buf+=len; - if (--maxlen>=0) { - *buf='e'; - ++buf; - } - for (len=1000; len>0; len/=10) { - if (e10>=len || !initial) { - if (--maxlen>=0) { - *buf=(e10/len)+'0'; - ++buf; + /* the number is greater than 1. Iterate through digits before the + * decimal point until we reach the decimal point or maxlen is + * reached (in which case we switch to scientific notation). */ + while (tmp>0.9) { + char digit; + double fraction=d/tmp; + digit=(int)(fraction); /* floor() */ + if (!first || digit) { + first=0; + *buf=digit+'0'; ++buf; + if (!maxlen) { + /* use scientific notation */ + int len=__dtostr(backup/tmp,oldbuf,maxlen,prec,prec2); + int initial=1; + if (len==0) return 0; + maxlen-=len; buf+=len; + if (maxlen>0) { + *buf='e'; + ++buf; + } + --maxlen; + for (len=1000; len>0; len/=10) { + if (e10>=len || !initial) { + if (maxlen>0) { + *buf=(e10/len)+'0'; + ++buf; + } + --maxlen; + initial=0; + e10=e10%len; + } + } + if (maxlen>0) goto fini; + return 0; } - initial=0; - e10=e10%len; + d-=digit*tmp; + --maxlen; } + tmp/=10.0; } - if (maxlen>=0) return buf-oldbuf; - return 0; } - /* step 5: loop through the digits, inserting the decimal point when - * appropriate */ - if (d<1.0) { - double x=1.0; - int first=1; - do { - if (--maxlen<0) return buf-oldbuf; - *buf='0'; ++buf; - if (first) { - first=0; - *buf='.'; ++buf; - if (--maxlen<0) return buf-oldbuf; - } - x/=10.0; - } while (x>d); + else + { + tmp = 0.1; } - for (; prec>0; ) { - double tmp2=d/tmp; - char c; - d-=((int)tmp2*tmp); - c=((int)tmp2); - if ((!initial)||c) { - if (--maxlen>=0) { - initial=0; - *buf=c+'0'; - ++buf; - } else - return 0; + + if (buf==oldbuf) { + if (!maxlen) return 0; --maxlen; + *buf='0'; ++buf; + } + if (prec2 || prec>(unsigned int)(buf-oldbuf)+1) { /* more digits wanted */ + if (!maxlen) return 0; --maxlen; + *buf='.'; ++buf; + prec-=buf-oldbuf-1; + if (prec2) prec=prec2; + if (prec>maxlen) return 0; + while (prec>0) { + char digit; + double fraction=d/tmp; + digit=(int)(fraction); /* floor() */ + *buf=digit+'0'; ++buf; + d-=digit*tmp; + tmp/=10.0; --prec; } - if (tmp>0.5 && tmp<1.5) { - tmp=1e-1; - initial=0; - if (--maxlen>=0) { - *buf='.'; - ++buf; - } else - return 0; - } else - tmp/=10.0; } -done: +fini: *buf=0; return buf-oldbuf; } -- cgit v1.2.1