diff options
Diffstat (limited to 'src/cmd/gc/mparith2.c')
-rw-r--r-- | src/cmd/gc/mparith2.c | 683 |
1 files changed, 0 insertions, 683 deletions
diff --git a/src/cmd/gc/mparith2.c b/src/cmd/gc/mparith2.c deleted file mode 100644 index 403255005..000000000 --- a/src/cmd/gc/mparith2.c +++ /dev/null @@ -1,683 +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 "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, lo; - int i, c; - - c = 0; - lo = a->a[0] & 1; - a1 = &a->a[Mpprec]; - for(i=0; i<Mpprec; i++) { - x = *--a1; - *a1 = (x + c) >> 1; - c = 0; - if(x & 1) - c = Mpbase; - } - if(a->neg && lo != 0) - mpaddcfix(a, -1); -} - -// -// right shift mpint by Mpscale -// ignores sign and overflow -// -static void -mprshw(Mpint *a) -{ - long *a1, lo; - int i; - - lo = a->a[0]; - a1 = &a->a[0]; - for(i=1; i<Mpprec; i++) { - a1[0] = a1[1]; - a1++; - } - a1[0] = 0; - if(a->neg && lo != 0) - mpaddcfix(a, -1); -} - -// -// 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) { - yyerror("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 = -*a1 -c; - c = 0; - if(x < 0) { - x += Mpbase; - c = 1; - } - *a1++ = x; - } -} - -// shift left by s (or right by -s) -void -mpshiftfix(Mpint *a, int s) -{ - if(s >= 0) { - while(s >= Mpscale) { - mplshw(a); - s -= Mpscale; - } - while(s > 0) { - mplsh(a); - s--; - } - } else { - s = -s; - while(s >= Mpscale) { - mprshw(a); - s -= Mpscale; - } - while(s > 0) { - mprsh(a); - s--; - } - } -} - -/// implements fix arihmetic - -void -mpaddfixfix(Mpint *a, Mpint *b) -{ - int i, c; - long x, *a1, *b1; - - if(a->ovf || b->ovf) { - yyerror("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) - yyerror("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) { - yyerror("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) - yyerror("set ovf in mpmulfixfix"); -} - -void -mpmulfract(Mpint *a, Mpint *b) -{ - - int i, j; - long *a1, x; - Mpint s, q; - - if(a->ovf || b->ovf) { - yyerror("ovf in mpmulflt"); - a->ovf = 1; - return; - } - - mpmovefixfix(&s, b); - a1 = &a->a[Mpprec]; - s.neg = 0; - mpmovecfix(&q, 0); - - x = *--a1; - if(x != 0) - yyerror("mpmulfract not normal"); - - for(i=0; i<Mpprec-1; i++) { - x = *--a1; - if(x == 0) { - mprshw(&s); - continue; - } - for(j=0; j<Mpscale; j++) { - x <<= 1; - if(x & Mpbase) - mpaddfixfix(&q, &s); - mprsh(&s); - } - } - - q.neg = a->neg ^ b->neg; - mpmovefixfix(a, &q); - if(a->ovf) - yyerror("set ovf in mpmulflt"); -} - -void -mporfixfix(Mpint *a, Mpint *b) -{ - int i; - long x, *a1, *b1; - - if(a->ovf || b->ovf) { - yyerror("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 | *b1++; - *a1++ = x; - } - - 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) { - yyerror("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 & *b1++; - *a1++ = x; - } - - if(b->neg) - mpneg(b); - if(x & Mpsign) { - a->neg = 1; - mpneg(a); - } -} - -void -mpandnotfixfix(Mpint *a, Mpint *b) -{ - int i; - long x, *a1, *b1; - - if(a->ovf || b->ovf) { - yyerror("ovf in mpandnotfixfix"); - 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 & ~*b1++; - *a1++ = x; - } - - 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) { - yyerror("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 ^ *b1++; - *a1++ = x; - } - - 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) { - yyerror("ovf in mporfixfix"); - mpmovecfix(a, 0); - a->ovf = 1; - return; - } - s = mpgetfix(b); - if(s < 0 || s >= Mpprec*Mpscale) { - yyerror("stupid shift: %lld", s); - mpmovecfix(a, 0); - return; - } - - mpshiftfix(a, s); -} - -void -mprshfixfix(Mpint *a, Mpint *b) -{ - vlong s; - - if(a->ovf || b->ovf) { - yyerror("ovf in mprshfixfix"); - mpmovecfix(a, 0); - a->ovf = 1; - return; - } - s = mpgetfix(b); - if(s < 0 || s >= Mpprec*Mpscale) { - yyerror("stupid shift: %lld", s); - if(a->neg) - mpmovecfix(a, -1); - else - mpmovecfix(a, 0); - return; - } - - mpshiftfix(a, -s); -} - -void -mpnegfix(Mpint *a) -{ - a->neg ^= 1; -} - -vlong -mpgetfix(Mpint *a) -{ - vlong v; - - if(a->ovf) { - yyerror("constant overflow"); - 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, ns, ds; - - ns = n->neg; - ds = d->neg; - n->neg = 0; - d->neg = 0; - - 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; - n->neg = ns; - d->neg = ds; - yyerror("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); - } - } - - n->neg = ns; - d->neg = ds; - r->neg = ns; - q->neg = ns^ds; -} - -static int -iszero(Mpint *a) -{ - long *a1; - int i; - a1 = &a->a[0] + Mpprec; - for(i=0; i<Mpprec; i++) { - if(*--a1 != 0) - return 0; - } - return 1; -} - -void -mpdivfract(Mpint *a, Mpint *b) -{ - Mpint n, d; - int i, j, neg; - long *a1, x; - - mpmovefixfix(&n, a); // numerator - mpmovefixfix(&d, b); // denominator - a1 = &a->a[Mpprec]; // quotient - - neg = n.neg ^ d.neg; - n.neg = 0; - d.neg = 0; - for(i=0; i<Mpprec; i++) { - x = 0; - for(j=0; j<Mpscale; j++) { - x <<= 1; - if(mpcmp(&d, &n) <= 0) { - if(!iszero(&d)) - x |= 1; - mpsubfixfix(&n, &d); - } - mprsh(&d); - } - *--a1 = x; - } - a->neg = neg; -} - -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; -} |