Introduction
Introduction Statistics Contact Development Disclaimer Help
tpick up plan 9 fltfmt changes - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
commit a76c0fd4a9a9a9a64893db614dd146a5819a6e0c
parent 3f1a2197698858e42a9176ca6e8cd57f6ea8eb30
Author: rsc <devnull@localhost>
Date: Sun, 26 Dec 2004 22:36:52 +0000
pick up plan 9 fltfmt changes
Diffstat:
M src/lib9/fmt/fltfmt.c | 463 +++++++++--------------------…
1 file changed, 138 insertions(+), 325 deletions(-)
---
diff --git a/src/lib9/fmt/fltfmt.c b/src/lib9/fmt/fltfmt.c
t@@ -25,6 +25,7 @@
enum
{
+ FDIGIT = 30,
FDEFLT = 6,
NSIGNIF = 17
};
t@@ -129,67 +130,47 @@ xsub(char *a, int n, int v)
}
static void
-xaddexp(char *p, int e)
+xdtoa(Fmt *fmt, char *s2, double f)
{
- char se[9];
- int i;
+ char s1[NSIGNIF+10];
+ double g, h;
+ int e, d, i, n;
+ int c1, c2, c3, c4, ucase, sign, chr, prec;
- *p++ = 'e';
- if(e < 0) {
- *p++ = '-';
- e = -e;
- }
- i = 0;
- while(e) {
- se[i++] = e % 10 + '0';
- e /= 10;
+ prec = FDEFLT;
+ if(fmt->flags & FmtPrec)
+ prec = fmt->prec;
+ if(prec > FDIGIT)
+ prec = FDIGIT;
+ if(isNaN(f)) {
+ strcpy(s2, "NaN");
+ return;
}
- if(i == 0) {
- *p++ = '0';
- } else {
- while(i > 0)
- *p++ = se[--i];
+ if(isInf(f, 1)) {
+ strcpy(s2, "+Inf");
+ return;
}
- *p++ = '\0';
-}
-
-static char*
-xdodtoa(char *s1, double f, int chr, int prec, int *decpt, int *rsign)
-{
- char s2[NSIGNIF+10];
- double g, h;
- int e, d, i;
- int c2, sign, oerr;
-
- if(chr == 'F')
- chr = 'f';
- if(prec > NSIGNIF)
- prec = NSIGNIF;
- if(prec < 0)
- prec = 0;
- if(__isNaN(f)) {
- *decpt = 9999;
- *rsign = 0;
- strcpy(s1, "nan");
- return &s1[3];
+ if(isInf(f, -1)) {
+ strcpy(s2, "-Inf");
+ return;
}
sign = 0;
if(f < 0) {
f = -f;
sign++;
}
- *rsign = sign;
- if(__isInf(f, 1) || __isInf(f, -1)) {
- *decpt = 9999;
- strcpy(s1, "inf");
- return &s1[3];
+ ucase = 0;
+ chr = fmt->r;
+ if(isupper(chr)) {
+ ucase = 1;
+ chr = tolower(chr);
}
e = 0;
g = f;
if(g != 0) {
frexp(f, &e);
- e = (int)(e * .301029995664);
+ e = e * .301029995664;
if(e >= -150 && e <= +150) {
d = 0;
h = f;
t@@ -213,7 +194,7 @@ xdodtoa(char *s1, double f, int chr, int prec, int *decpt,…
* back to get accuracy.
*/
for(i=0; i<NSIGNIF; i++) {
- d = (int)g;
+ d = g;
s1[i] = d + '0';
g = (g - d) * 10;
}
t@@ -225,21 +206,20 @@ xdodtoa(char *s1, double f, int chr, int prec, int *decp…
c2 = prec + 1;
if(chr == 'f')
c2 += e;
- oerr = errno;
if(c2 >= NSIGNIF-2) {
strcpy(s2, s1);
d = e;
s1[NSIGNIF-2] = '0';
s1[NSIGNIF-1] = '0';
- xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
- g = fmtstrtod(s1, nil);
+ sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
+ g = strtod(s1, nil);
if(g == f)
goto found;
if(xadd(s1, NSIGNIF-3, 1)) {
e++;
- xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
+ sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
}
- g = fmtstrtod(s1, nil);
+ g = strtod(s1, nil);
if(g == f)
goto found;
strcpy(s1, s2);
t@@ -249,9 +229,9 @@ xdodtoa(char *s1, double f, int chr, int prec, int *decpt,…
/*
* convert back so s1 gets exact answer
*/
- for(d = 0; d < 10; d++) {
- xaddexp(s1+NSIGNIF, e-NSIGNIF+1);
- g = fmtstrtod(s1, nil);
+ for(;;) {
+ sprint(s1+NSIGNIF, "e%d", e-NSIGNIF+1);
+ g = strtod(s1, nil);
if(f > g) {
if(xadd(s1, NSIGNIF-1, 1))
e--;
t@@ -266,179 +246,17 @@ xdodtoa(char *s1, double f, int chr, int prec, int *dec…
}
found:
- errno = oerr;
-
/*
* sign
*/
d = 0;
i = 0;
-
- /*
- * round & adjust 'f' digits
- */
- c2 = prec + 1;
- if(chr == 'f'){
- if(xadd(s1, c2+e, 5))
- e++;
- c2 += e;
- if(c2 < 0){
- c2 = 0;
- e = -prec - 1;
- }
- }else{
- if(xadd(s1, c2, 5))
- e++;
- }
- if(c2 > NSIGNIF){
- c2 = NSIGNIF;
- }
-
- *decpt = e + 1;
-
- /*
- * terminate the converted digits
- */
- s1[c2] = '\0';
- return &s1[c2];
-}
-
-/*
- * this function works like the standard dtoa, if you want it.
- */
-#if 0
-static char*
-__dtoa(double f, int mode, int ndigits, int *decpt, int *rsign, char **rve)
-{
- static char s2[NSIGNIF + 10];
- char *es;
- int chr, prec;
-
- switch(mode) {
- /* like 'e' */
- case 2:
- case 4:
- case 6:
- case 8:
- chr = 'e';
- break;
- /* like 'g' */
- case 0:
- case 1:
- default:
- chr = 'g';
- break;
- /* like 'f' */
- case 3:
- case 5:
- case 7:
- case 9:
- chr = 'f';
- break;
- }
-
- if(chr != 'f' && ndigits){
- ndigits--;
- }
- prec = ndigits;
- if(prec > NSIGNIF)
- prec = NSIGNIF;
- if(ndigits == 0)
- prec = NSIGNIF;
- es = xdodtoa(s2, f, chr, prec, decpt, rsign);
-
- /*
- * strip trailing 0
- */
- for(; es > s2 + 1; es--){
- if(es[-1] != '0'){
- break;
- }
- }
- *es = '\0';
- if(rve != NULL)
- *rve = es;
- return s2;
-}
-#endif
-
-static int
-fmtzdotpad(Fmt *f, int n, int pt)
-{
- char *t, *s;
- int i;
- Rune *rt, *rs;
-
- if(f->runes){
- rt = (Rune*)f->to;
- rs = (Rune*)f->stop;
- for(i = 0; i < n; i++){
- if(i == pt){
- FMTRCHAR(f, rt, rs, '.');
- }
- FMTRCHAR(f, rt, rs, '0');
- }
- f->nfmt += rt - (Rune*)f->to;
- f->to = rt;
- }else{
- t = (char*)f->to;
- s = (char*)f->stop;
- for(i = 0; i < n; i++){
- if(i == pt){
- FMTCHAR(f, t, s, '.');
- }
- FMTCHAR(f, t, s, '0');
- }
- f->nfmt += t - (char *)f->to;
- f->to = t;
- }
- return 0;
-}
-
-int
-__efgfmt(Fmt *fmt)
-{
- double f;
- char s1[NSIGNIF+10];
- int e, d, n;
- int c1, c2, c3, c4, ucase, sign, chr, prec, fl;
-
- f = va_arg(fmt->args, double);
- prec = FDEFLT;
- fl = fmt->flags;
- fmt->flags = 0;
- if(fl & FmtPrec)
- prec = fmt->prec;
- chr = fmt->r;
- ucase = 0;
- if(chr == 'E'){
- chr = 'e';
- ucase = 1;
- }else if(chr == 'F'){
- chr = 'f';
- ucase = 1;
- }else if(chr == 'G'){
- chr = 'g';
- ucase = 1;
- }
- if(prec > 0 && chr == 'g')
- prec--;
- if(prec < 0)
- prec = 0;
-
- xdodtoa(s1, f, chr, prec, &e, &sign);
- e--;
- if(*s1 == 'i' || *s1 == 'n'){
- if(ucase){
- if(*s1 == 'i'){
- strcpy(s1, "INF");
- }else{
- strcpy(s1, "NAN");
- }
- }
- fmt->flags = fl & (FmtWidth|FmtLeft);
- return __fmtcpy(fmt, (const void*)s1, 3, 3);
- }
+ if(sign)
+ s2[d++] = '-';
+ else if(fmt->flags & FmtSign)
+ s2[d++] = '+';
+ else if(fmt->flags & FmtSpace)
+ s2[d++] = ' ';
/*
* copy into final place
t@@ -453,22 +271,27 @@ __efgfmt(Fmt *fmt)
c4 = prec;
switch(chr) {
default:
- chr = 'e';
+ if(xadd(s1, c2, 5))
+ e++;
break;
case 'g':
/*
* decide on 'e' of 'f' style convers
*/
- if(e >= -4 && e <= prec) {
- c1 = -e;
+ if(xadd(s1, c2, 5))
+ e++;
+ if(e >= -5 && e <= prec) {
+ c1 = -e - 1;
c4 = prec - e;
- chr = 'h'; /* flag for 'f' style */
+ chr = 'h'; // flag for 'f' style
}
break;
case 'f':
+ if(xadd(s1, c2+e, 5))
+ e++;
c1 = -e;
if(c1 > prec)
- c1 = prec + 1;
+ c1 = c2;
c2 += e;
break;
}
t@@ -486,126 +309,116 @@ __efgfmt(Fmt *fmt)
}
/*
- * trim trailing zeros for %g
- */
- if(!(fl & FmtSharp)
- && (chr == 'g' || chr == 'h')){
- if(c4 >= c3){
- c4 -= c3;
- c3 = 0;
- }else{
- c3 -= c4;
- c4 = 0;
- }
- while(c4 && c2 > 1 && s1[c2 - 1] == '0'){
- c4--;
- c2--;
- }
- }
-
- /*
- * calculate the total length
- */
- n = c1 + c2 + c3;
- if(sign || (fl & (FmtSign|FmtSpace)))
- n++;
- if(c4 || (fl & FmtSharp)){
- n++;
- }
- if(chr == 'e' || chr == 'g'){
- n += 4;
- if(e >= 100)
- n++;
- }
-
- /*
- * pad to width if right justified
- */
- if((fl & (FmtWidth|FmtLeft)) == FmtWidth && n < fmt->width){
- if(fl & FmtZero){
- c1 += fmt->width - n;
- }else{
- if(__fmtpad(fmt, fmt->width - n) < 0){
- return -1;
- }
- }
- }
-
- /*
- * sign
- */
- d = 0;
- if(sign)
- d = '-';
- else if(fl & FmtSign)
- d = '+';
- else if(fl & FmtSpace)
- d = ' ';
- if(d && fmtrune(fmt, d) < 0){
- return -1;
- }
-
- /*
* copy digits
*/
- c4 = c1 + c2 + c3 - c4;
- if(c1 > 0){
- if(fmtzdotpad(fmt, c1, c4) < 0){
- return -1;
- }
- c4 -= c1;
+ while(c1 > 0) {
+ if(c1+c2+c3 == c4)
+ s2[d++] = '.';
+ s2[d++] = '0';
+ c1--;
}
- d = 0;
- if(c4 >= 0 && c4 < c2){
- if(__fmtcpy(fmt, s1, c4, c4) < 0 || fmtrune(fmt, '.') < 0)
- return -1;
- d = c4;
- c2 -= c4;
- c4 = -1;
+ while(c2 > 0) {
+ if(c2+c3 == c4)
+ s2[d++] = '.';
+ s2[d++] = s1[i++];
+ c2--;
}
- if(__fmtcpy(fmt, (const void*)(s1 + d), c2, c2) < 0){
- return -1;
- }
- c4 -= c2;
- if(c3 > 0){
- if(fmtzdotpad(fmt, c3, c4) < 0){
- return -1;
- }
- c4 -= c3;
+ while(c3 > 0) {
+ if(c3 == c4)
+ s2[d++] = '.';
+ s2[d++] = '0';
+ c3--;
}
/*
* strip trailing '0' on g conv
*/
- if((fl & FmtSharp) && c4 == 0 && fmtrune(fmt, '.') < 0){
- return -1;
+ if(fmt->flags & FmtSharp) {
+ if(0 == c4)
+ s2[d++] = '.';
+ } else
+ if(chr == 'g' || chr == 'h') {
+ for(n=d-1; n>=0; n--)
+ if(s2[n] != '0')
+ break;
+ for(i=n; i>=0; i--)
+ if(s2[i] == '.') {
+ d = n;
+ if(i != n)
+ d++;
+ break;
+ }
}
if(chr == 'e' || chr == 'g') {
- d = 0;
if(ucase)
- s1[d++] = 'E';
+ s2[d++] = 'E';
else
- s1[d++] = 'e';
+ s2[d++] = 'e';
c1 = e;
if(c1 < 0) {
- s1[d++] = '-';
+ s2[d++] = '-';
c1 = -c1;
} else
- s1[d++] = '+';
+ s2[d++] = '+';
if(c1 >= 100) {
- s1[d++] = c1/100 + '0';
+ s2[d++] = c1/100 + '0';
c1 = c1%100;
}
- s1[d++] = c1/10 + '0';
- s1[d++] = c1%10 + '0';
- if(__fmtcpy(fmt, s1, d, d) < 0){
- return -1;
- }
+ s2[d++] = c1/10 + '0';
+ s2[d++] = c1%10 + '0';
}
- if((fl & (FmtWidth|FmtLeft)) == (FmtWidth|FmtLeft) && n < fmt->width){
- if(__fmtpad(fmt, fmt->width - n) < 0){
- return -1;
+ s2[d] = 0;
+}
+
+static int
+fmtzdotpad(Fmt *f, int n, int pt)
+{
+ char *t, *s;
+ int i;
+ Rune *rt, *rs;
+
+ if(f->runes){
+ rt = (Rune*)f->to;
+ rs = (Rune*)f->stop;
+ for(i = 0; i < n; i++){
+ if(i == pt){
+ FMTRCHAR(f, rt, rs, '.');
+ }
+ FMTRCHAR(f, rt, rs, '0');
+ }
+ f->nfmt += rt - (Rune*)f->to;
+ f->to = rt;
+ }else{
+ t = (char*)f->to;
+ s = (char*)f->stop;
+ for(i = 0; i < n; i++){
+ if(i == pt){
+ FMTCHAR(f, t, s, '.');
+ }
+ FMTCHAR(f, t, s, '0');
}
+ f->nfmt += t - (char *)f->to;
+ f->to = t;
}
return 0;
}
+
+static int
+floatfmt(Fmt *fmt, double f)
+{
+ char s[FDIGIT+10];
+
+ xdtoa(fmt, s, f);
+ fmt->flags &= FmtWidth|FmtLeft;
+ __fmtcpy(fmt, s, strlen(s), strlen(s));
+ return 0;
+}
+
+int
+__efgfmt(Fmt *f)
+{
+ double d;
+
+ d = va_arg(f->args, double);
+ return floatfmt(f, d);
+}
You are viewing proxied material from mx1.adamsgaard.dk. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.