]> Cypherpunks repositories - gostls13.git/commitdiff
adding and deleting files
authorKen Thompson <ken@golang.org>
Sun, 10 Aug 2008 00:33:35 +0000 (17:33 -0700)
committerKen Thompson <ken@golang.org>
Sun, 10 Aug 2008 00:33:35 +0000 (17:33 -0700)
R=r
DELTA=1685  (920 added, 765 deleted, 0 changed)
OCL=14030
CL=14030

src/cmd/gc/mparith1.c [moved from src/cmd/gc/mparith.c with 73% similarity]
src/cmd/gc/mparith2.c [new file with mode: 0644]
src/cmd/gc/mparith3.c [new file with mode: 0644]
src/cmd/gc/mpatof.c [deleted file]

similarity index 73%
rename from src/cmd/gc/mparith.c
rename to src/cmd/gc/mparith1.c
index 7295493d7ef23e91db41a869f518edbe83faf645..6c625f3fd9f6ec0a531a12eebf8086666f7d258a 100644 (file)
@@ -1,17 +1,19 @@
-// Copyright 2009 The Go Authors.  All rights reserved.
+// 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
 mpcmpfixfix(Mpint *a, Mpint *b)
 {
-       if(a->val > b->val)
-               return +1;
-       if(a->val < b->val)
-               return -1;
-       return 0;
+       Mpint c;
+
+       mpmovefixfix(&c, a);
+       mpsubfixfix(&c, b);
+       return mptestfix(&c);
 }
 
 int
@@ -26,206 +28,124 @@ mpcmpfixc(Mpint *b, vlong c)
 int
 mpcmpfltflt(Mpflt *a, Mpflt *b)
 {
-       if(a->val > b->val)
-               return +1;
-       if(a->val < b->val)
-               return -1;
-       return 0;
+       Mpflt c;
+
+       mpmovefltflt(&c, a);
+       mpsubfltflt(&c, b);
+       return mptestflt(&c);
 }
 
 int
-mpcmpfltc(Mpint *b, double c)
+mpcmpfltc(Mpflt *b, double c)
 {
-       Mpint a;
+       Mpflt a;
 
        mpmovecflt(&a, c);
        return mpcmpfltflt(&a, b);
 }
 
-void
-mpaddfixfix(Mpint *a, Mpint *b)
-{
-       a->val += b->val;
-}
-
 void
 mpsubfixfix(Mpint *a, Mpint *b)
 {
-       a->val -= b->val;
+       mpnegfix(b);
+       mpaddfixfix(a, b);
+       mpnegfix(b);
 }
 
 void
-mpmulfixfix(Mpint *a, Mpint *b)
-{
-       a->val *= b->val;
-}
-
-void
-mpdivfixfix(Mpint *a, Mpint *b)
-{
-       a->val /= b->val;
-}
-
-void
-mpmodfixfix(Mpint *a, Mpint *b)
+mpsubfltflt(Mpflt *a, Mpflt *b)
 {
-       a->val %= b->val;
+       mpnegflt(b);
+       mpaddfltflt(a, b);
+       mpnegflt(b);
 }
 
 void
-mporfixfix(Mpint *a, Mpint *b)
+mpaddcfix(Mpint *a, vlong c)
 {
-       a->val |= b->val;
-}
+       Mpint b;
 
-void
-mpandfixfix(Mpint *a, Mpint *b)
-{
-       a->val &= b->val;
+       mpmovecfix(&b, c);
+       mpaddfixfix(a, &b);
 }
 
 void
-mpxorfixfix(Mpint *a, Mpint *b)
+mpaddcflt(Mpflt *a, double c)
 {
-       a->val ^= b->val;
-}
+       Mpflt b;
 
-void
-mplshfixfix(Mpint *a, Mpint *b)
-{
-       a->val <<= b->val;
+       mpmovecflt(&b, c);
+       mpaddfltflt(a, &b);
 }
 
 void
-mprshfixfix(Mpint *a, Mpint *b)
+mpmulcfix(Mpint *a, vlong c)
 {
-       a->val >>= b->val;
-}
+       Mpint b;
 
-void
-mpnegfix(Mpint *a)
-{
-       a->val = -a->val;
+       mpmovecfix(&b, c);
+       mpmulfixfix(a, &b);
 }
 
 void
-mpcomfix(Mpint *a)
+mpmulcflt(Mpflt *a, double c)
 {
-       a->val = ~a->val;
-}
+       Mpflt b;
 
-void
-mpaddfltflt(Mpflt *a, Mpflt *b)
-{
-       a->val += b->val;
+       mpmovecflt(&b, c);
+       mpmulfltflt(a, &b);
 }
 
 void
-mpsubfltflt(Mpflt *a, Mpflt *b)
+mpdivfixfix(Mpint *a, Mpint *b)
 {
-       a->val -= b->val;
-}
+       Mpint q, r;
 
-void
-mpmulfltflt(Mpflt *a, Mpflt *b)
-{
-       a->val *= b->val;
+       mpdivmodfixfix(&q, &r, a, b);
+       mpmovefixfix(a, &q);
 }
 
 void
-mpdivfltflt(Mpflt *a, Mpflt *b)
-{
-       a->val /= b->val;
-}
-
-vlong
-mpgetfix(Mpint *a)
+mpmodfixfix(Mpint *a, Mpint *b)
 {
-       return a->val;
-}
+       Mpint q, r;
 
-double
-mpgetflt(Mpflt *a)
-{
-       return a->val;
+       mpdivmodfixfix(&q, &r, a, b);
+       mpmovefixfix(a, &r);
 }
 
 void
-mpmovefixfix(Mpint *a, Mpint *b)
+mpcomfix(Mpint *a)
 {
-       *a = *b;
-}
+       Mpint b;
 
-void
-mpmovefltflt(Mpflt *a, Mpflt *b)
-{
-       *a = *b;
+       mpmovecfix(&b, 1);
+       mpnegfix(a);
+       mpsubfixfix(a, &b);
 }
 
 void
 mpmovefixflt(Mpflt *a, Mpint *b)
 {
-       a->val = b->val;
-}
-
-void
-mpmovecfix(Mpint *a, vlong c)
-{
-       a->val = c;
-}
-
-void
-mpmovecflt(Mpflt *a, double c)
-{
-       a->val = c;
+       mpmovecflt(a, mpgetfix(b));
 }
 
 void
 mpmovefltfix(Mpint *a, Mpflt *b)
 {
-       a->val = b->val;
-}
-
-void
-mpnegflt(Mpflt *a)
-{
-       a->val = -a->val;
+       mpmovecfix(a, mpgetflt(b));
 }
 
 void
-mpaddcflt(Mpflt *a, double c)
-{
-       Mpflt b;
-
-       mpmovecflt(&b, c);
-       mpaddfltflt(a, &b);
-}
-
-void
-mpmulcflt(Mpflt *a, double c)
-{
-       Mpflt b;
-
-       mpmovecflt(&b, c);
-       mpmulfltflt(a, &b);
-}
-
-void
-mpaddcfix(Mpint *a, vlong c)
+mpmovefixfix(Mpint *a, Mpint *b)
 {
-       Mpint b;
-
-       mpmovecfix(&b, c);
-       mpaddfixfix(a, &b);
+       *a = *b;
 }
 
 void
-mpmulcfix(Mpint *a, vlong c)
+mpmovefltflt(Mpflt *a, Mpflt *b)
 {
-       Mpint b;
-
-       mpmovecfix(&b, c);
-       mpmulfixfix(a, &b);
+       *a = *b;
 }
 
 //
@@ -265,7 +185,7 @@ mpatoflt(Mpflt *a, char *as)
        ex = 0;         /* exponent */
        zer = 1;        /* zero */
 
-       mpmovecflt(a, 0);
+       mpmovecflt(a, 0.0);
        for(;;) {
                switch(c = *s++) {
                default:
@@ -348,7 +268,6 @@ bad:
 void
 mpatofix(Mpint *a, char *as)
 {
-
        int c, f;
        char *s;
 
diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c
new file mode 100644 (file)
index 0000000..ecc4c1d
--- /dev/null
@@ -0,0 +1,529 @@
+// 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"
+
+//
+// return the significant
+// words of the argument
+//
+static int
+mplen(Mpint *a)
+{
+       int i, n;
+       long *a1;
+
+       n = -1;
+       a1 = &a->a[0];
+       for(i=0; i<Mpprec; i++) {
+               if(*a1++ != 0)
+                       n = i;
+       }
+       return n+1;
+}
+
+//
+// left shift mpint by one
+// ignores sign and overflow
+//
+static void
+mplsh(Mpint *a)
+{
+       long *a1, x;
+       int i, c;
+
+       c = 0;
+       a1 = &a->a[0];
+       for(i=0; i<Mpprec; i++) {
+               x = (*a1 << 1) + c;
+               c = 0;
+               if(x >= Mpbase) {
+                       x -= Mpbase;
+                       c = 1;
+               }
+               *a1++ = x;
+       }
+}
+
+//
+// left shift mpint by Mpscale
+// ignores sign and overflow
+//
+static void
+mplshw(Mpint *a)
+{
+       long *a1;
+       int i;
+
+       a1 = &a->a[Mpprec-1];
+       for(i=1; i<Mpprec; i++) {
+               a1[0] = a1[-1];
+               *a1--;
+       }
+       a1[0] = 0;
+}
+
+//
+// right shift mpint by one
+// ignores sign and overflow
+//
+static void
+mprsh(Mpint *a)
+{
+       long *a1, x;
+       int i, c;
+
+       c = 0;
+       a1 = &a->a[Mpprec];
+       for(i=0; i<Mpprec; i++) {
+               x = *--a1;
+               *a1 = (x + c) >> 1;
+               c = 0;
+               if(x & 1)
+                       c = Mpbase;
+       }
+}
+
+//
+// right shift mpint by Mpscale
+// ignores sign and overflow
+//
+static void
+mprshw(Mpint *a)
+{
+       long *a1;
+       int i;
+
+       a1 = &a->a[0];
+       for(i=1; i<Mpprec; i++) {
+               a1[0] = a1[1];
+               *a1++;
+       }
+       a1[0] = 0;
+}
+
+//
+// return the sign of (abs(a)-abs(b))
+//
+static int
+mpcmp(Mpint *a, Mpint *b)
+{
+       long x, *a1, *b1;
+       int i;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in cmp");
+               return 0;
+       }
+
+       a1 = &a->a[0] + Mpprec;
+       b1 = &b->a[0] + Mpprec;
+
+       for(i=0; i<Mpprec; i++) {
+               x = *--a1 - *--b1;
+               if(x > 0)
+                       return +1;
+               if(x < 0)
+                       return -1;
+       }
+       return 0;
+}
+
+//
+// negate a
+// ignore sign and ovf
+//
+static void
+mpneg(Mpint *a)
+{
+       long x, *a1;
+       int i, c;
+
+       a1 = &a->a[0];
+       c = 0;
+       for(i=0; i<Mpprec; i++) {
+               x = c - *a1;
+               *a1++ = x;
+
+               c = 0;
+               if(x < 0)
+                       c = 1;
+       }
+}
+
+/// implements fix arihmetic
+
+void
+mpaddfixfix(Mpint *a, Mpint *b)
+{
+       int i, c;
+       long x, *a1, *b1;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mpaddxx");
+               a->ovf = 1;
+               return;
+       }
+
+       c = 0;
+       a1 = &a->a[0];
+       b1 = &b->a[0];
+       if(a->neg != b->neg)
+               goto sub;
+
+       // perform a+b
+       for(i=0; i<Mpprec; i++) {
+               x = *a1 + *b1++ + c;
+               c = 0;
+               if(x >= Mpbase) {
+                       x -= Mpbase;
+                       c = 1;
+               }
+               *a1++ = x;
+       }
+       a->ovf = c;
+       if(a->ovf)
+               warn("set ovf in mpaddxx");
+
+       return;
+
+sub:
+       // perform a-b
+       switch(mpcmp(a, b)) {
+       case 0:
+               mpmovecfix(a, 0);
+               break;
+
+       case 1:
+               for(i=0; i<Mpprec; i++) {
+                       x = *a1 - *b1++ - c;
+                       c = 0;
+                       if(x < 0) {
+                               x += Mpbase;
+                               c = 1;
+                       }
+                       *a1++ = x;
+               }
+               break;
+
+       case -1:
+               a->neg ^= 1;
+               for(i=0; i<Mpprec; i++) {
+                       x = *b1++ - *a1 - c;
+                       c = 0;
+                       if(x < 0) {
+                               x += Mpbase;
+                               c = 1;
+                       }
+                       *a1++ = x;
+               }
+               break;
+       }
+}
+
+void
+mpmulfixfix(Mpint *a, Mpint *b)
+{
+
+       int i, j, na, nb;
+       long *a1, x;
+       Mpint s, q;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mpmulfixfix");
+               a->ovf = 1;
+               return;
+       }
+
+       // pick the smaller
+       // to test for bits
+       na = mplen(a);
+       nb = mplen(b);
+       if(na > nb) {
+               mpmovefixfix(&s, a);
+               a1 = &b->a[0];
+               na = nb;
+       } else {
+               mpmovefixfix(&s, b);
+               a1 = &a->a[0];
+       }
+       s.neg = 0;
+
+       mpmovecfix(&q, 0);
+       for(i=0; i<na; i++) {
+               x = *a1++;
+               for(j=0; j<Mpscale; j++) {
+                       if(x & 1)
+                               mpaddfixfix(&q, &s);
+                       mplsh(&s);
+                       x >>= 1;
+               }
+       }
+
+       q.neg = a->neg ^ b->neg;
+       mpmovefixfix(a, &q);
+       if(a->ovf)
+               warn("set ovf in mpmulfixfix");
+}
+
+void
+mporfixfix(Mpint *a, Mpint *b)
+{
+       int i;
+       long x, *a1, *b1;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mporfixfix");
+               mpmovecfix(a, 0);
+               a->ovf = 1;
+               return;
+       }
+       if(a->neg) {
+               a->neg = 0;
+               mpneg(a);
+       }
+       if(b->neg)
+               mpneg(b);
+
+       a1 = &a->a[0];
+       b1 = &b->a[0];
+       for(i=0; i<Mpprec; i++) {
+               x = *a1;
+               *a1++ = x | *b1++;
+       }
+
+       if(b->neg)
+               mpneg(b);
+       if(x & Mpsign) {
+               a->neg = 1;
+               mpneg(a);
+       }
+}
+
+void
+mpandfixfix(Mpint *a, Mpint *b)
+{
+       int i;
+       long x, *a1, *b1;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mpandfixfix");
+               mpmovecfix(a, 0);
+               a->ovf = 1;
+               return;
+       }
+       if(a->neg) {
+               a->neg = 0;
+               mpneg(a);
+       }
+       if(b->neg)
+               mpneg(b);
+
+       a1 = &a->a[0];
+       b1 = &b->a[0];
+       for(i=0; i<Mpprec; i++) {
+               x = *a1;
+               *a1++ = x & *b1++;
+       }
+
+       if(b->neg)
+               mpneg(b);
+       if(x & Mpsign) {
+               a->neg = 1;
+               mpneg(a);
+       }
+}
+
+void
+mpxorfixfix(Mpint *a, Mpint *b)
+{
+       int i;
+       long x, *a1, *b1;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mporfixfix");
+               mpmovecfix(a, 0);
+               a->ovf = 1;
+               return;
+       }
+       if(a->neg) {
+               a->neg = 0;
+               mpneg(a);
+       }
+       if(b->neg)
+               mpneg(b);
+
+       a1 = &a->a[0];
+       b1 = &b->a[0];
+       for(i=0; i<Mpprec; i++) {
+               x = *a1;
+               *a1++ = x ^ *b1++;
+       }
+
+       if(b->neg)
+               mpneg(b);
+       if(x & Mpsign) {
+               a->neg = 1;
+               mpneg(a);
+       }
+}
+
+void
+mplshfixfix(Mpint *a, Mpint *b)
+{
+       vlong s;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mporfixfix");
+               mpmovecfix(a, 0);
+               a->ovf = 1;
+               return;
+       }
+       s = mpgetfix(b);
+       if(s < 0 || s >= Mpprec*Mpscale) {
+               warn("stupid shift: %lld", s);
+               mpmovecfix(a, 0);
+               return;
+       }
+
+       while(s >= Mpscale) {
+               mplshw(a);
+               s -= Mpscale;
+       }
+       while(s > 0) {
+               mplsh(a);
+               s--;
+       }
+}
+
+void
+mprshfixfix(Mpint *a, Mpint *b)
+{
+       vlong s;
+
+       if(a->ovf || b->ovf) {
+               warn("ovf in mprshfixfix");
+               mpmovecfix(a, 0);
+               a->ovf = 1;
+               return;
+       }
+       s = mpgetfix(b);
+       if(s < 0 || s >= Mpprec*Mpscale) {
+               warn("stupid shift: %lld", s);
+               mpmovecfix(a, 0);
+               return;
+       }
+
+       while(s >= Mpscale) {
+               mprshw(a);
+               s -= Mpscale;
+       }
+       while(s > 0) {
+               mprsh(a);
+               s--;
+       }
+}
+
+void
+mpnegfix(Mpint *a)
+{
+       a->neg ^= 1;
+}
+
+vlong
+mpgetfix(Mpint *a)
+{
+       vlong v;
+
+       if(a->ovf) {
+               warn("ovf in mpgetfix");
+               return 0;
+       }
+
+       v = (vlong)a->a[0];
+       v |= (vlong)a->a[1] << Mpscale;
+       v |= (vlong)a->a[2] << (Mpscale+Mpscale);
+       if(a->neg)
+               v = -v;
+       return v;
+}
+
+void
+mpmovecfix(Mpint *a, vlong c)
+{
+       int i;
+       long *a1;
+       vlong x;
+
+       a->neg = 0;
+       a->ovf = 0;
+
+       x = c;
+       if(x < 0) {
+               a->neg = 1;
+               x = -x;
+       }
+
+       a1 = &a->a[0];
+       for(i=0; i<Mpprec; i++) {
+               *a1++ = x&Mpmask;
+               x >>= Mpscale;
+       }
+}
+
+void
+mpdivmodfixfix(Mpint *q, Mpint *r, Mpint *n, Mpint *d)
+{
+       int i, nn, dn;
+
+       mpmovefixfix(r, n);
+       mpmovecfix(q, 0);
+
+       // shift denominator until it
+       // is larger than numerator
+       for(i=0; i<Mpprec*Mpscale; i++) {
+               if(mpcmp(d, r) > 0)
+                       break;
+               mplsh(d);
+       }
+
+       // if it never happens
+       // denominator is probably zero
+       if(i >= Mpprec*Mpscale) {
+               q->ovf = 1;
+               r->ovf = 1;
+               warn("set ovf in mpdivmodfixfix");
+               return;
+       }
+
+       // shift denominator back creating
+       // quotient a bit at a time
+       // when done the remaining numerator
+       // will be the remainder
+       for(; i>0; i--) {
+               mplsh(q);
+               mprsh(d);
+               if(mpcmp(d, r) <= 0) {
+                       mpaddcfix(q, 1);
+                       mpsubfixfix(r, d);
+               }
+       }
+}
+
+int
+mptestfix(Mpint *a)
+{
+       Mpint b;
+       int r;
+
+       mpmovecfix(&b, 0);
+       r = mpcmp(a, &b);
+       if(a->neg) {
+               if(r > 0)
+                       return -1;
+               if(r < 0)
+                       return +1;
+       }
+       return r;
+}
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
new file mode 100644 (file)
index 0000000..2a0a1c6
--- /dev/null
@@ -0,0 +1,53 @@
+// 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"
+
+/// implements float arihmetic
+
+void
+mpaddfltflt(Mpflt *a, Mpflt *b)
+{
+       a->val += b->val;
+}
+
+void
+mpmulfltflt(Mpflt *a, Mpflt *b)
+{
+       a->val *= b->val;
+}
+
+void
+mpdivfltflt(Mpflt *a, Mpflt *b)
+{
+       a->val /= b->val;
+}
+
+double
+mpgetflt(Mpflt *a)
+{
+       return a->val;
+}
+
+void
+mpmovecflt(Mpflt *a, double c)
+{
+       a->val = c;
+}
+
+void
+mpnegflt(Mpflt *a)
+{
+       a->val = -a->val;
+}
+
+int
+mptestflt(Mpflt *a)
+{
+       if(a->val < 0)
+               return -1;
+       if(a->val > 0)
+               return +1;
+       return 0;
+}
diff --git a/src/cmd/gc/mpatof.c b/src/cmd/gc/mpatof.c
deleted file mode 100644 (file)
index 3ddc613..0000000
+++ /dev/null
@@ -1,342 +0,0 @@
-// 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       <u.h>
-#include       <libc.h>
-
-int    mpatof(char*, double*);
-int    mpatov(char *s, vlong *v);
-
-enum
-{
-       Mpscale = 29,           /* safely smaller than bits in a int32 */
-       Mpprec  = 36,           /* Mpscale*Mpprec sb > largest fp exp */
-       Mpbase  = 1L<<Mpscale,
-};
-
-typedef
-struct
-{
-       int32   a[Mpprec];
-       char    ovf;
-} Mp;
-
-static void    mpint(Mp*, int);
-static void    mppow(Mp*, int, int);
-static void    mpmul(Mp*, int);
-static void    mpadd(Mp*, Mp*);
-static int     mptof(Mp*, double*);
-
-/*
- * convert a string, s, to floating in *d
- * return conversion overflow.
- * required syntax is [+-]d*[.]d*[e[+-]d*]
- */
-int
-mpatof(char *s, double *d)
-{
-       Mp a, b;
-       int dp, c, f, ef, ex, zer;
-       double d1, d2;
-
-       dp = 0;         /* digits after decimal point */
-       f = 0;          /* sign */
-       ex = 0;         /* exponent */
-       zer = 1;        /* zero */
-       memset(&a, 0, sizeof(a));
-       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':
-                       mpint(&b, c-'0');
-                       mpmul(&a, 10);
-                       mpadd(&a, &b);
-                       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(a.ovf)
-               goto bad;
-       if(zer) {
-               *d = 0;
-               return 0;
-       }
-       if(dp)
-               dp--;
-       dp -= ex;
-       if(dp > 0) {
-               /*
-                * must divide by 10**dp
-                */
-               if(mptof(&a, &d1))
-                       goto bad;
-
-               /*
-                * trial exponent of 8**dp
-                * 8 (being between 5 and 10)
-                * should pick up all underflows
-                * in the division of 5**dp.
-                */
-               d2 = frexp(d1, &ex);
-               d2 = ldexp(d2, ex-3*dp);
-               if(d2 == 0)
-                       goto bad;
-
-               /*
-                * decompose each 10 into 5*2.
-                * create 5**dp in fixed point
-                * and then play with the exponent
-                * for the remaining 2**dp.
-                * note that 5**dp will overflow
-                * with as few as 134 input digits.
-                */
-               mpint(&a, 1);
-               mppow(&a, 5, dp);
-               if(mptof(&a, &d2))
-                       goto bad;
-               d1 = frexp(d1/d2, &ex);
-               d1 = ldexp(d1, ex-dp);
-               if(d1 == 0)
-                       goto bad;
-       } else {
-               /*
-                * must multiply by 10**|dp| --
-                * just do it in fixed point.
-                */
-               mppow(&a, 10, -dp);
-               if(mptof(&a, &d1))
-                       goto bad;
-       }
-       if(f)
-               d1 = -d1;
-       *d = d1;
-       return 0;
-
-bad:
-       return 1;
-}
-
-/*
- * convert a to floating in *d
- * return conversion overflow
- */
-static int
-mptof(Mp *a, double *d)
-{
-       double f, g;
-       int32 x, *a1;
-       int i;
-
-       if(a->ovf)
-               return 1;
-       a1 = a->a;
-       f = ldexp(*a1++, 0);
-       for(i=Mpscale; i<Mpprec*Mpscale; i+=Mpscale)
-               if(x = *a1++) {
-                       g = ldexp(x, i);
-                       /*
-                        * NOTE: the test (g==0) is plan9
-                        * specific. ansi compliant overflow
-                        * is signaled by HUGE and errno==ERANGE.
-                        * change this for your particular ldexp.
-                        */
-                       if(g == 0)
-                               return 1;
-                       f += g;         /* this could bomb! */
-               }
-       *d = f;
-       return 0;
-}
-
-/*
- * return a += b
- */
-static void
-mpadd(Mp *a, Mp *b)
-{
-       int i, c;
-       int32 x, *a1, *b1;
-
-       if(b->ovf)
-               a->ovf = 1;
-       if(a->ovf)
-               return;
-       c = 0;
-       a1 = a->a;
-       b1 = b->a;
-       for(i=0; i<Mpprec; i++) {
-               x = *a1 + *b1++ + c;
-               c = 0;
-               if(x >= Mpbase) {
-                       x -= Mpbase;
-                       c = 1;
-               }
-               *a1++ = x;
-       }
-       a->ovf = c;
-}
-
-/*
- * return a = c
- */
-static void
-mpint(Mp *a, int c)
-{
-
-       memset(a, 0, sizeof(*a));
-       a->a[0] = c;
-}
-
-/*
- * return a *= c
- */
-static void
-mpmul(Mp *a, int c)
-{
-       Mp p;
-       int b;
-       memmove(&p, a, sizeof(p));
-       if(!(c & 1))
-               memset(a, 0, sizeof(*a));
-       c &= ~1;
-       for(b=2; c; b<<=1) {
-               mpadd(&p, &p);
-               if(c & b) {
-                       mpadd(a, &p);
-                       c &= ~b;
-               }
-       }
-}
-
-/*
- * return a *= b**e
- */
-static void
-mppow(Mp *a, int b, int e)
-{
-       int b1;
-
-       b1 = b*b;
-       b1 = b1*b1;
-       while(e >= 4) {
-               mpmul(a, b1);
-               e -= 4;
-               if(a->ovf)
-                       return;
-       }
-       while(e > 0) {
-               mpmul(a, b);
-               e--;
-       }
-}
-
-/*
- * convert a string, s, to vlong in *v
- * return conversion overflow.
- * required syntax is [0[x]]d*
- */
-int
-mpatov(char *s, vlong *v)
-{
-       vlong n, nn;
-       int c;
-       n = 0;
-       c = *s;
-       if(c == '0')
-               goto oct;
-       while(c = *s++) {
-               if(c >= '0' && c <= '9')
-                       nn = n*10 + c-'0';
-               else
-                       goto bad;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-       goto out;
-oct:
-       s++;
-       c = *s;
-       if(c == 'x' || c == 'X')
-               goto hex;
-       while(c = *s++) {
-               if(c >= '0' || c <= '7')
-                       nn = n*8 + c-'0';
-               else
-                       goto bad;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-       goto out;
-hex:
-       s++;
-       while(c = *s++) {
-               if(c >= '0' && c <= '9')
-                       c += 0-'0';
-               else
-               if(c >= 'a' && c <= 'f')
-                       c += 10-'a';
-               else
-               if(c >= 'A' && c <= 'F')
-                       c += 10-'A';
-               else
-                       goto bad;
-               nn = n*16 + c;
-               if(n < 0 && nn >= 0)
-                       goto bad;
-               n = nn;
-       }
-out:
-       *v = n;
-       return 0;
-
-bad:
-       *v = ~0;
-       return 1;
-}