BOOL Float::sub(const Float &b) { if (b.iszero()) return FALSE; if (iszero()) {*this=-b; return TRUE;} Big y=b.m; m.shift(precision-length(m)); // make them precision length y.shift(precision-length(y)); if (e>=b.e) { if (e-b.e>precision) return FALSE; y.shift(b.e-e); m-=y; if (m.iszero()) e=0; else e+=length(m)-precision; } else { if (b.e-e>precision) {*this=-b; return TRUE;} m.shift(e-b.e); m-=y; if (m.iszero()) e=0; else e=b.e+length(m)-precision; } m.shift(precision-length(m)); return TRUE; }
BOOL Float::add(const Float &b) { // return TRUE if this is affected, FALSE if b has no effect if (b.iszero()) return FALSE; if (iszero()) {*this=b; return TRUE;} Big y=b.m; m.shift(precision-length(m)); // make them precision length y.shift(precision-length(y)); if (e>=b.e) { if (e-b.e>precision) return FALSE; y.shift(b.e-e); m+=y; if (m.iszero()) e=0; else e+=length(m)-precision; } else { if (b.e-e>precision) {*this=b; return TRUE;} m.shift(e-b.e); m+=y; if (m.iszero()) e=0; else e=b.e+length(m)-precision; } m.shift(precision-length(m)); return TRUE; }
double todouble(const Float &f) { int i,s; Big x=f.m; double word,d=0.0; mr_small dig; if (f.iszero()) return d; if (f.m>=0) s=PLUS; else {s=MINUS; x.negate();} word=pow(2.0,(double)MIRACL); for (i=0;i<length(x);i++) { dig=x[i]; d+=(double)dig; d/=word; } if (f.e>0) for (i=0;i<f.e;i++) d*=word; if (f.e<0) for (i=0;i<-f.e;i++) d/=word; if (s==MINUS) d=-d; return d; }
Float exp(const Float &a) { // from Brent int i; Float t,x,y,r,one=(Float)1; int q; Big lambda; if (a.iszero()) return one; x=a; q=isqrt(MIRACL*precision,2); lambda=pow((Big)2,q); x/=(Float)lambda; r=0; y=one; for (i=1;i<=q+2;i++) { t=x; t/=i; y*=t; // y*=(x/i); if (!r.add(y)) break; } for (i=0;i<q;i++) { r+=one; r*=r; if (i<q-1) r-=one; } return r; }
Big trunc(const Float& f) { Big b=0; if (f.iszero()) return b; b=shift(f.m,f.e-length(f.m)); return b; }
Float pow(const Float &f,int n) { Float x,r=1; if (n==0) return r; if (f.iszero()) return f; x=f; if (n<0) { n=(-n); x=reciprocal(x); } if (n==1) return x; forever { if (n%2!=0) r*=x; n/=2; if (n==0) break; x*=x; } return r; }