| // Copyright 2009 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| #include "go.h" | |
| /// uses arihmetic | |
| int | |
| mpcmpfixflt(Mpint *a, Mpflt *b) | |
| { | |
| char buf[500]; | |
| Mpflt c; | |
| sprint(buf, "%B", a); | |
| mpatoflt(&c, buf); | |
| return mpcmpfltflt(&c, b); | |
| } | |
| int | |
| mpcmpfltfix(Mpflt *a, Mpint *b) | |
| { | |
| char buf[500]; | |
| Mpflt c; | |
| sprint(buf, "%B", b); | |
| mpatoflt(&c, buf); | |
| return mpcmpfltflt(a, &c); | |
| } | |
| int | |
| mpcmpfixfix(Mpint *a, Mpint *b) | |
| { | |
| Mpint c; | |
| mpmovefixfix(&c, a); | |
| mpsubfixfix(&c, b); | |
| return mptestfix(&c); | |
| } | |
| int | |
| mpcmpfixc(Mpint *b, vlong c) | |
| { | |
| Mpint a; | |
| mpmovecfix(&a, c); | |
| return mpcmpfixfix(&a, b); | |
| } | |
| int | |
| mpcmpfltflt(Mpflt *a, Mpflt *b) | |
| { | |
| Mpflt c; | |
| mpmovefltflt(&c, a); | |
| mpsubfltflt(&c, b); | |
| return mptestflt(&c); | |
| } | |
| int | |
| mpcmpfltc(Mpflt *b, double c) | |
| { | |
| Mpflt a; | |
| mpmovecflt(&a, c); | |
| return mpcmpfltflt(&a, b); | |
| } | |
| void | |
| mpsubfixfix(Mpint *a, Mpint *b) | |
| { | |
| mpnegfix(b); | |
| mpaddfixfix(a, b); | |
| mpnegfix(b); | |
| } | |
| void | |
| mpsubfltflt(Mpflt *a, Mpflt *b) | |
| { | |
| mpnegflt(b); | |
| mpaddfltflt(a, b); | |
| mpnegflt(b); | |
| } | |
| void | |
| mpaddcfix(Mpint *a, vlong c) | |
| { | |
| Mpint b; | |
| mpmovecfix(&b, c); | |
| mpaddfixfix(a, &b); | |
| } | |
| void | |
| mpaddcflt(Mpflt *a, double c) | |
| { | |
| Mpflt b; | |
| mpmovecflt(&b, c); | |
| mpaddfltflt(a, &b); | |
| } | |
| void | |
| mpmulcfix(Mpint *a, vlong c) | |
| { | |
| Mpint b; | |
| mpmovecfix(&b, c); | |
| mpmulfixfix(a, &b); | |
| } | |
| void | |
| mpmulcflt(Mpflt *a, double c) | |
| { | |
| Mpflt b; | |
| mpmovecflt(&b, c); | |
| mpmulfltflt(a, &b); | |
| } | |
| void | |
| mpdivfixfix(Mpint *a, Mpint *b) | |
| { | |
| Mpint q, r; | |
| mpdivmodfixfix(&q, &r, a, b); | |
| mpmovefixfix(a, &q); | |
| } | |
| void | |
| mpmodfixfix(Mpint *a, Mpint *b) | |
| { | |
| Mpint q, r; | |
| mpdivmodfixfix(&q, &r, a, b); | |
| mpmovefixfix(a, &r); | |
| } | |
| void | |
| mpcomfix(Mpint *a) | |
| { | |
| Mpint b; | |
| mpmovecfix(&b, 1); | |
| mpnegfix(a); | |
| mpsubfixfix(a, &b); | |
| } | |
| void | |
| mpmovefixflt(Mpflt *a, Mpint *b) | |
| { | |
| mpmovecflt(a, mpgetfix(b)); | |
| } | |
| void | |
| mpmovefltfix(Mpint *a, Mpflt *b) | |
| { | |
| mpmovecfix(a, mpgetflt(b)); | |
| } | |
| void | |
| mpmovefixfix(Mpint *a, Mpint *b) | |
| { | |
| *a = *b; | |
| } | |
| void | |
| mpmovefltflt(Mpflt *a, Mpflt *b) | |
| { | |
| *a = *b; | |
| } | |
| // | |
| // power of ten | |
| // | |
| static double | |
| tentab[] = { 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9 }; | |
| static double | |
| dppow10(int n) | |
| { | |
| int i; | |
| if(n < 0) | |
| return 1.0/dppow10(-n); | |
| if(n < nelem(tentab)) | |
| return tentab[n]; | |
| i = n/2; | |
| return dppow10(i) * dppow10(n-i); | |
| } | |
| // | |
| // floating point input | |
| // required syntax is [+-]d*[.]d*[e[+-]d*] | |
| // | |
| void | |
| mpatoflt(Mpflt *a, char *as) | |
| { | |
| int dp, c, f, ef, ex, zer; | |
| char *s; | |
| s = as; | |
| dp = 0; /* digits after decimal point */ | |
| f = 0; /* sign */ | |
| ex = 0; /* exponent */ | |
| 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 '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(dp) | |
| dp--; | |
| if(mpcmpfltc(a, 0.0) != 0) | |
| mpmulcflt(a, dppow10(ex-dp)); | |
| if(f) | |
| mpnegflt(a); | |
| return; | |
| bad: | |
| warn("set ovf in mpatof"); | |
| mpmovecflt(a, 0.0); | |
| } | |
| // | |
| // fixed point input | |
| // required syntax is [+-][0[x]]d* | |
| // | |
| void | |
| mpatofix(Mpint *a, char *as) | |
| { | |
| int c, f; | |
| char *s; | |
| s = as; | |
| f = 0; | |
| mpmovecfix(a, 0); | |
| c = *s++; | |
| switch(c) { | |
| case '-': | |
| f = 1; | |
| case '+': | |
| c = *s++; | |
| if(c != '0') | |
| break; | |
| case '0': | |
| goto oct; | |
| } | |
| while(c) { | |
| if(c >= '0' && c <= '9') { | |
| mpmulcfix(a, 10); | |
| mpaddcfix(a, c-'0'); | |
| c = *s++; | |
| continue; | |
| } | |
| goto bad; | |
| } | |
| goto out; | |
| oct: | |
| c = *s++; | |
| if(c == 'x' || c == 'X') | |
| goto hex; | |
| while(c) { | |
| if(c >= '0' && c <= '7') { | |
| mpmulcfix(a, 8); | |
| mpaddcfix(a, c-'0'); | |
| c = *s++; | |
| continue; | |
| } | |
| goto bad; | |
| } | |
| goto out; | |
| hex: | |
| c = *s++; | |
| while(c) { | |
| if(c >= '0' && c <= '9') { | |
| mpmulcfix(a, 16); | |
| mpaddcfix(a, c-'0'); | |
| c = *s++; | |
| continue; | |
| } | |
| if(c >= 'a' && c <= 'f') { | |
| mpmulcfix(a, 16); | |
| mpaddcfix(a, c+10-'a'); | |
| c = *s++; | |
| continue; | |
| } | |
| if(c >= 'A' && c <= 'F') { | |
| mpmulcfix(a, 16); | |
| mpaddcfix(a, c+10-'A'); | |
| c = *s++; | |
| continue; | |
| } | |
| goto bad; | |
| } | |
| out: | |
| if(f) | |
| mpnegfix(a); | |
| return; | |
| bad: | |
| warn("set ovf in mpatov: %s", as); | |
| mpmovecfix(a, 0); | |
| } | |
| int | |
| Bconv(Fmt *fp) | |
| { | |
| char buf[500], *p; | |
| Mpint *xval, q, r, ten; | |
| int f; | |
| xval = va_arg(fp->args, Mpint*); | |
| mpmovefixfix(&q, xval); | |
| f = 0; | |
| if(mptestfix(&q) < 0) { | |
| f = 1; | |
| mpnegfix(&q); | |
| } | |
| mpmovecfix(&ten, 10); | |
| p = &buf[sizeof(buf)]; | |
| *--p = 0; | |
| for(;;) { | |
| mpdivmodfixfix(&q, &r, &q, &ten); | |
| *--p = mpgetfix(&r) + '0'; | |
| if(mptestfix(&q) <= 0) | |
| break; | |
| } | |
| if(f) | |
| *--p = '-'; | |
| return fmtstrcpy(fp, p); | |
| } |