void mpsubfltflt(Mpflt *a, Mpflt *b) { mpnegflt(a); mpaddfltflt(a, b); mpnegflt(a); }
// // floating point input // required syntax is [+-]d*[.]d*[e[+-]d*] or [+-]0xH*[e[+-]d*] // void mpatoflt(Mpflt *a, char *as) { Mpflt b; int dp, c, f, ef, ex, eb, base; char *s, *start; while(*as == ' ' || *as == '\t') as++; /* determine base */ s = as; base = -1; while(base == -1) { switch(*s++) { case '-': case '+': break; case '0': if(*s == 'x') base = 16; else base = 10; break; default: base = 10; } } s = as; dp = 0; /* digits after decimal point */ f = 0; /* sign */ ex = 0; /* exponent */ eb = 0; /* binary point */ mpmovecflt(a, 0.0); if(base == 16) { start = nil; for(;;) { c = *s; if(c == '-') { f = 1; s++; } else if(c == '+') { s++; } else if(c == '0' && s[1] == 'x') { s += 2; start = s; } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) { s++; } else { break; } } if(start == nil) goto bad; mphextofix(&a->val, start, s-start); if(a->val.ovf) goto bad; a->exp = 0; mpnorm(a); } for(;;) { switch(c = *s++) { default: goto bad; case '-': f = 1; case ' ': case '\t': case '+': continue; case '.': if(base == 16) goto bad; dp = 1; continue; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case '0': mpmulcflt(a, 10); mpaddcflt(a, c-'0'); if(dp) dp++; continue; case 'P': case 'p': eb = 1; case 'E': case 'e': ex = 0; ef = 0; for(;;) { c = *s++; if(c == '+' || c == ' ' || c == '\t') continue; if(c == '-') { ef = 1; continue; } if(c >= '0' && c <= '9') { ex = ex*10 + (c-'0'); if(ex > 1e8) { yyerror("constant exponent out of range: %s", as); errorexit(); } continue; } break; } if(ef) ex = -ex; case 0: break; } break; } if(eb) { if(dp) goto bad; mpsetexp(a, a->exp+ex); goto out; } if(dp) dp--; if(mpcmpfltc(a, 0.0) != 0) { if(ex >= dp) { mppow10flt(&b, ex-dp); mpmulfltflt(a, &b); } else { // 4 approximates least_upper_bound(log2(10)). if(dp-ex >= (1<<(8*sizeof(dp)-3)) || (short)(4*(dp-ex)) != 4*(dp-ex)) { mpmovecflt(a, 0.0); } else { mppow10flt(&b, dp-ex); mpdivfltflt(a, &b); } } } out: if(f) mpnegflt(a); return; bad: yyerror("constant too large: %s", as); mpmovecflt(a, 0.0); }
// // floating point input // required syntax is [+-]d*[.]d*[e[+-]d*] // void mpatoflt(Mpflt *a, char *as) { Mpflt b; int dp, c, f, ef, ex, eb, zer; char *s; s = as; dp = 0; /* digits after decimal point */ f = 0; /* sign */ ex = 0; /* exponent */ eb = 0; /* binary point */ zer = 1; /* zero */ mpmovecflt(a, 0.0); for(;;) { switch(c = *s++) { default: goto bad; case '-': f = 1; case ' ': case '\t': case '+': continue; case '.': dp = 1; continue; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': zer = 0; case '0': mpmulcflt(a, 10); mpaddcflt(a, c-'0'); if(dp) dp++; continue; case 'P': case 'p': eb = 1; case 'E': case 'e': ex = 0; ef = 0; for(;;) { c = *s++; if(c == '+' || c == ' ' || c == '\t') continue; if(c == '-') { ef = 1; continue; } if(c >= '0' && c <= '9') { ex = ex*10 + (c-'0'); continue; } break; } if(ef) ex = -ex; case 0: break; } break; } if(eb) { if(dp) goto bad; a->exp += ex; goto out; } if(dp) dp--; if(mpcmpfltc(a, 0.0) != 0) { if(ex >= dp) { mppow10flt(&b, ex-dp); mpmulfltflt(a, &b); } else { mppow10flt(&b, dp-ex); mpdivfltflt(a, &b); } } out: if(f) mpnegflt(a); return; bad: yyerror("set ovf in mpatof"); mpmovecflt(a, 0.0); }