int Fconv(Fmt *fp) { char buf[500]; Mpflt *fvp, fv; double d; fvp = va_arg(fp->args, Mpflt*); if(fp->flags & FmtSharp) { // alternate form - decimal for error messages. // for well in range, convert to double and use print's %g if(-900 < fvp->exp && fvp->exp < 900) { d = mpgetflt(fvp); if(d >= 0 && (fp->flags & FmtSign)) fmtprint(fp, "+"); return fmtprint(fp, "%g", d); } // TODO(rsc): for well out of range, print // an approximation like 1.234e1000 } if(sigfig(fvp) == 0) { snprint(buf, sizeof(buf), "0p+0"); goto out; } fv = *fvp; while(fv.val.a[0] == 0) { mpshiftfix(&fv.val, -Mpscale); fv.exp += Mpscale; } while((fv.val.a[0]&1) == 0) { mpshiftfix(&fv.val, -1); fv.exp += 1; } if(fv.exp >= 0) { snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp); goto out; } snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp); out: return fmtstrcpy(fp, buf); }
// convert (truncate) b to a. // return -1 (but still convert) if b was non-integer. int mpmovefltfix(Mpint *a, Mpflt *b) { Mpflt f; *a = b->val; mpshiftfix(a, b->exp); if(b->exp < 0) { f.val = *a; f.exp = 0; mpnorm(&f); if(mpcmpfltflt(b, &f) != 0) return -1; } return 0; }
void mplshfixfix(Mpint *a, Mpint *b) { vlong s; if(a->ovf || b->ovf) { yyerror("ovf in mporfixfix"); mpmovecfix(a, 0); a->ovf = 1; return; } s = mpgetfix(b); if(s < 0 || s >= Mpprec*Mpscale) { yyerror("stupid shift: %lld", s); mpmovecfix(a, 0); return; } mpshiftfix(a, s); }
int Fconv(Fmt *fp) { char buf[500]; Mpflt *fvp, fv; double d, dexp; int exp; fvp = va_arg(fp->args, Mpflt*); if(fp->flags & FmtSharp) { // alternate form - decimal for error messages. // for well in range, convert to double and use print's %g exp = fvp->exp + sigfig(fvp)*Mpscale; if(-900 < exp && exp < 900) { d = mpgetflt(fvp); if(d >= 0 && (fp->flags & FmtSign)) fmtprint(fp, "+"); return fmtprint(fp, "%g", d, exp, fvp); } // very out of range. compute decimal approximation by hand. // decimal exponent dexp = fvp->exp * 0.301029995663981195; // log_10(2) exp = (int)dexp; // decimal mantissa fv = *fvp; fv.val.neg = 0; fv.exp = 0; d = mpgetflt(&fv); d *= pow(10, dexp-exp); while(d >= 9.99995) { d /= 10; exp++; } if(fvp->val.neg) fmtprint(fp, "-"); else if(fp->flags & FmtSign) fmtprint(fp, "+"); return fmtprint(fp, "%.5fe+%d", d, exp); } if(sigfig(fvp) == 0) { snprint(buf, sizeof(buf), "0p+0"); goto out; } fv = *fvp; while(fv.val.a[0] == 0) { mpshiftfix(&fv.val, -Mpscale); fv.exp += Mpscale; } while((fv.val.a[0]&1) == 0) { mpshiftfix(&fv.val, -1); fv.exp += 1; } if(fv.exp >= 0) { snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp); goto out; } snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp); out: return fmtstrcpy(fp, buf); }