summaryrefslogtreecommitdiff
path: root/src/cmd/gc/mparith1.c
diff options
context:
space:
mode:
authorMichael Stapelberg <stapelberg@debian.org>2013-03-04 21:27:36 +0100
committerMichael Stapelberg <michael@stapelberg.de>2013-03-04 21:27:36 +0100
commit04b08da9af0c450d645ab7389d1467308cfc2db8 (patch)
treedb247935fa4f2f94408edc3acd5d0d4f997aa0d8 /src/cmd/gc/mparith1.c
parent917c5fb8ec48e22459d77e3849e6d388f93d3260 (diff)
downloadgolang-upstream/1.1_hg20130304.tar.gz
Imported Upstream version 1.1~hg20130304upstream/1.1_hg20130304
Diffstat (limited to 'src/cmd/gc/mparith1.c')
-rw-r--r--src/cmd/gc/mparith1.c176
1 files changed, 140 insertions, 36 deletions
diff --git a/src/cmd/gc/mparith1.c b/src/cmd/gc/mparith1.c
index 33fa90e2e..e25044a8b 100644
--- a/src/cmd/gc/mparith1.c
+++ b/src/cmd/gc/mparith1.c
@@ -43,10 +43,10 @@ mpcmpfixfix(Mpint *a, Mpint *b)
int
mpcmpfixc(Mpint *b, vlong c)
{
- Mpint a;
+ Mpint c1;
- mpmovecfix(&a, c);
- return mpcmpfixfix(&a, b);
+ mpmovecfix(&c1, c);
+ return mpcmpfixfix(b, &c1);
}
int
@@ -232,16 +232,78 @@ mppow10flt(Mpflt *a, int p)
mpmulcflt(a, 10);
}
+static void
+mphextofix(Mpint *a, char *s, int n)
+{
+ char *hexdigitp, *end, c;
+ long d;
+ int bit;
+
+ while(*s == '0') {
+ s++;
+ n--;
+ }
+
+ // overflow
+ if(4*n > Mpscale*Mpprec) {
+ a->ovf = 1;
+ return;
+ }
+
+ end = s+n-1;
+ for(hexdigitp=end; hexdigitp>=s; hexdigitp--) {
+ c = *hexdigitp;
+ if(c >= '0' && c <= '9')
+ d = c-'0';
+ else if(c >= 'A' && c <= 'F')
+ d = c-'A'+10;
+ else
+ d = c-'a'+10;
+
+ bit = 4*(end - hexdigitp);
+ while(d > 0) {
+ if(d & 1)
+ a->a[bit/Mpscale] |= (long)1 << (bit%Mpscale);
+ bit++;
+ d = d >> 1;
+ }
+ }
+}
+
//
// floating point input
-// required syntax is [+-]d*[.]d*[e[+-]d*]
+// 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;
- char *s;
+ 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 */
@@ -250,6 +312,37 @@ mpatoflt(Mpflt *a, char *as)
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:
@@ -259,11 +352,13 @@ mpatoflt(Mpflt *a, char *as)
f = 1;
case ' ':
- case '\t':
- case '+':
+ case '\t':
+ case '+':
continue;
case '.':
+ if(base == 16)
+ goto bad;
dp = 1;
continue;
@@ -355,7 +450,7 @@ void
mpatofix(Mpint *a, char *as)
{
int c, f;
- char *s;
+ char *s, *s0;
s = as;
f = 0;
@@ -402,28 +497,19 @@ oct:
goto out;
hex:
- c = *s++;
+ s0 = s;
+ 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++;
+ if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
+ s++;
+ c = *s;
continue;
}
goto bad;
}
+ mphextofix(a, s0, s-s0);
+ if(a->ovf)
+ goto bad;
out:
if(f)
@@ -439,8 +525,8 @@ int
Bconv(Fmt *fp)
{
char buf[500], *p;
- Mpint *xval, q, r, ten;
- int f;
+ Mpint *xval, q, r, ten, sixteen;
+ int f, digit;
xval = va_arg(fp->args, Mpint*);
mpmovefixfix(&q, xval);
@@ -449,15 +535,33 @@ Bconv(Fmt *fp)
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(fp->flags & FmtSharp) {
+ // Hexadecimal
+ mpmovecfix(&sixteen, 16);
+ for(;;) {
+ mpdivmodfixfix(&q, &r, &q, &sixteen);
+ digit = mpgetfix(&r);
+ if(digit < 10)
+ *--p = digit + '0';
+ else
+ *--p = digit - 10 + 'A';
+ if(mptestfix(&q) <= 0)
+ break;
+ }
+ *--p = 'x';
+ *--p = '0';
+ } else {
+ // Decimal
+ mpmovecfix(&ten, 10);
+ for(;;) {
+ mpdivmodfixfix(&q, &r, &q, &ten);
+ *--p = mpgetfix(&r) + '0';
+ if(mptestfix(&q) <= 0)
+ break;
+ }
}
if(f)
*--p = '-';
@@ -501,10 +605,10 @@ Fconv(Fmt *fp)
}
if(fv.exp >= 0) {
- snprint(buf, sizeof(buf), "%Bp+%d", &fv.val, fv.exp);
+ snprint(buf, sizeof(buf), "%#Bp+%d", &fv.val, fv.exp);
goto out;
}
- snprint(buf, sizeof(buf), "%Bp-%d", &fv.val, -fv.exp);
+ snprint(buf, sizeof(buf), "%#Bp-%d", &fv.val, -fv.exp);
out:
return fmtstrcpy(fp, buf);