Go prebuilts for linux-x86, version 1.4.1
See README.ANDROID for instructions on rebuilding the prebuilts.
Change-Id: I86db7f4fb3269585078da4d38947ca9126ac813b
diff --git a/src/cmd/gc/mparith3.c b/src/cmd/gc/mparith3.c
new file mode 100644
index 0000000..6afd75c
--- /dev/null
+++ b/src/cmd/gc/mparith3.c
@@ -0,0 +1,346 @@
+// 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>
+#include "go.h"
+
+/*
+ * returns the leading non-zero
+ * word of the number
+ */
+int
+sigfig(Mpflt *a)
+{
+ int i;
+
+ for(i=Mpprec-1; i>=0; i--)
+ if(a->val.a[i] != 0)
+ break;
+//print("sigfig %d %d\n", i-z+1, z);
+ return i+1;
+}
+
+/*
+ * sets the exponent.
+ * a too large exponent is an error.
+ * a too small exponent rounds the number to zero.
+ */
+void
+mpsetexp(Mpflt *a, int exp) {
+ if((short)exp != exp) {
+ if(exp > 0) {
+ yyerror("float constant is too large");
+ a->exp = 0x7fff;
+ }
+ else {
+ mpmovecflt(a, 0);
+ }
+ }
+ else {
+ a->exp = exp;
+ }
+}
+
+/*
+ * shifts the leading non-zero
+ * word of the number to Mpnorm
+ */
+void
+mpnorm(Mpflt *a)
+{
+ int s, os;
+ long x;
+
+ os = sigfig(a);
+ if(os == 0) {
+ // zero
+ a->exp = 0;
+ a->val.neg = 0;
+ return;
+ }
+
+ // this will normalize to the nearest word
+ x = a->val.a[os-1];
+ s = (Mpnorm-os) * Mpscale;
+
+ // further normalize to the nearest bit
+ for(;;) {
+ x <<= 1;
+ if(x & Mpbase)
+ break;
+ s++;
+ if(x == 0) {
+ // this error comes from trying to
+ // convert an Inf or something
+ // where the initial x=0x80000000
+ s = (Mpnorm-os) * Mpscale;
+ break;
+ }
+ }
+
+ mpshiftfix(&a->val, s);
+ mpsetexp(a, a->exp-s);
+}
+
+/// implements float arihmetic
+
+void
+mpaddfltflt(Mpflt *a, Mpflt *b)
+{
+ int sa, sb, s;
+ Mpflt c;
+
+ if(Mpdebug)
+ print("\n%F + %F", a, b);
+
+ sa = sigfig(a);
+ if(sa == 0) {
+ mpmovefltflt(a, b);
+ goto out;
+ }
+
+ sb = sigfig(b);
+ if(sb == 0)
+ goto out;
+
+ s = a->exp - b->exp;
+ if(s > 0) {
+ // a is larger, shift b right
+ mpmovefltflt(&c, b);
+ mpshiftfix(&c.val, -s);
+ mpaddfixfix(&a->val, &c.val, 0);
+ goto out;
+ }
+ if(s < 0) {
+ // b is larger, shift a right
+ mpshiftfix(&a->val, s);
+ mpsetexp(a, a->exp-s);
+ mpaddfixfix(&a->val, &b->val, 0);
+ goto out;
+ }
+ mpaddfixfix(&a->val, &b->val, 0);
+
+out:
+ mpnorm(a);
+ if(Mpdebug)
+ print(" = %F\n\n", a);
+}
+
+void
+mpmulfltflt(Mpflt *a, Mpflt *b)
+{
+ int sa, sb;
+
+ if(Mpdebug)
+ print("%F\n * %F\n", a, b);
+
+ sa = sigfig(a);
+ if(sa == 0) {
+ // zero
+ a->exp = 0;
+ a->val.neg = 0;
+ return;
+ }
+
+ sb = sigfig(b);
+ if(sb == 0) {
+ // zero
+ mpmovefltflt(a, b);
+ return;
+ }
+
+ mpmulfract(&a->val, &b->val);
+ mpsetexp(a, (a->exp + b->exp) + Mpscale*Mpprec - Mpscale - 1);
+
+ mpnorm(a);
+ if(Mpdebug)
+ print(" = %F\n\n", a);
+}
+
+void
+mpdivfltflt(Mpflt *a, Mpflt *b)
+{
+ int sa, sb;
+ Mpflt c;
+
+ if(Mpdebug)
+ print("%F\n / %F\n", a, b);
+
+ sb = sigfig(b);
+ if(sb == 0) {
+ // zero and ovfl
+ a->exp = 0;
+ a->val.neg = 0;
+ a->val.ovf = 1;
+ yyerror("constant division by zero");
+ return;
+ }
+
+ sa = sigfig(a);
+ if(sa == 0) {
+ // zero
+ a->exp = 0;
+ a->val.neg = 0;
+ return;
+ }
+
+ // adjust b to top
+ mpmovefltflt(&c, b);
+ mpshiftfix(&c.val, Mpscale);
+
+ // divide
+ mpdivfract(&a->val, &c.val);
+ mpsetexp(a, (a->exp-c.exp) - Mpscale*(Mpprec-1) + 1);
+
+ mpnorm(a);
+ if(Mpdebug)
+ print(" = %F\n\n", a);
+}
+
+static double
+mpgetfltN(Mpflt *a, int prec, int bias)
+{
+ int s, i, e, minexp;
+ uvlong v;
+ double f;
+
+ if(a->val.ovf && nsavederrors+nerrors == 0)
+ yyerror("mpgetflt ovf");
+
+ s = sigfig(a);
+ if(s == 0)
+ return 0;
+
+ if(s != Mpnorm) {
+ yyerror("mpgetflt norm");
+ mpnorm(a);
+ }
+
+ while((a->val.a[Mpnorm-1] & Mpsign) == 0) {
+ mpshiftfix(&a->val, 1);
+ mpsetexp(a, a->exp-1); // can set 'a' to zero
+ s = sigfig(a);
+ if(s == 0)
+ return 0;
+ }
+
+ // pick up the mantissa, a rounding bit, and a tie-breaking bit in a uvlong
+ s = prec+2;
+ v = 0;
+ for(i=Mpnorm-1; s>=Mpscale; i--) {
+ v = (v<<Mpscale) | a->val.a[i];
+ s -= Mpscale;
+ }
+ if(s > 0) {
+ v = (v<<s) | (a->val.a[i]>>(Mpscale-s));
+ if((a->val.a[i]&((1<<(Mpscale-s))-1)) != 0)
+ v |= 1;
+ i--;
+ }
+ for(; i >= 0; i--) {
+ if(a->val.a[i] != 0)
+ v |= 1;
+ }
+
+ // gradual underflow
+ e = Mpnorm*Mpscale + a->exp - prec;
+ minexp = bias+1-prec+1;
+ if(e < minexp) {
+ s = minexp - e;
+ if(s > prec+1)
+ s = prec+1;
+ if((v & ((1ULL<<s)-1)) != 0)
+ v |= 1ULL<<s;
+ v >>= s;
+ e = minexp;
+ }
+
+ // round to even
+ v |= (v&4)>>2;
+ v += v&1;
+ v >>= 2;
+
+ f = (double)(v);
+ f = ldexp(f, e);
+
+ if(a->val.neg)
+ f = -f;
+
+ return f;
+}
+
+double
+mpgetflt(Mpflt *a)
+{
+ return mpgetfltN(a, 53, -1023);
+}
+
+double
+mpgetflt32(Mpflt *a)
+{
+ return mpgetfltN(a, 24, -127);
+}
+
+void
+mpmovecflt(Mpflt *a, double c)
+{
+ int i;
+ double f;
+ long l;
+
+ if(Mpdebug)
+ print("\nconst %g", c);
+ mpmovecfix(&a->val, 0);
+ a->exp = 0;
+ if(c == 0)
+ goto out;
+ if(c < 0) {
+ a->val.neg = 1;
+ c = -c;
+ }
+
+ f = frexp(c, &i);
+ a->exp = i;
+
+ for(i=0; i<10; i++) {
+ f = f*Mpbase;
+ l = floor(f);
+ f = f - l;
+ a->exp -= Mpscale;
+ a->val.a[0] = l;
+ if(f == 0)
+ break;
+ mpshiftfix(&a->val, Mpscale);
+ }
+
+out:
+ mpnorm(a);
+ if(Mpdebug)
+ print(" = %F\n", a);
+}
+
+void
+mpnegflt(Mpflt *a)
+{
+ a->val.neg ^= 1;
+}
+
+int
+mptestflt(Mpflt *a)
+{
+ int s;
+
+ if(Mpdebug)
+ print("\n%F?", a);
+ s = sigfig(a);
+ if(s != 0) {
+ s = +1;
+ if(a->val.neg)
+ s = -1;
+ }
+ if(Mpdebug)
+ print(" = %d\n", s);
+ return s;
+}