-// 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
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;
}
//
ex = 0; /* exponent */
zer = 1; /* zero */
- mpmovecflt(a, 0);
+ mpmovecflt(a, 0.0);
for(;;) {
switch(c = *s++) {
default:
void
mpatofix(Mpint *a, char *as)
{
-
int c, f;
char *s;
--- /dev/null
+// 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;
+}
--- /dev/null
+// 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;
+}
+++ /dev/null
-// 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;
-}