/* * MIRACL C++ Float functions float.cpp * * AUTHOR : M. Scott * * PURPOSE : Implementation of Class Float functions */ #include #include "floating.h" using namespace std; #define TAN 1 #define SIN 2 #define COS 3 static Float *spi; static int precision=4; // must be power of 2 static BOOL pi_cooked=FALSE; Float makefloat(int a,int b) { return (Float)a/b; } Float fabs(const Float& f) { Float r=f; if (r.m<0) r.m.negate(); return r; } int norm(int type,Float& y) { // convert y to 1st quadrant angle, and return sign int s=PLUS; Float pi,w,t; if (y.sign()<0) { y.negate(); if (type!=COS) s=-s; } pi=fpi(); w=pi/2; if (fcomp(y,w)<=0) return s; w=2*pi; if (fcomp(y,w)>0) { // reduce mod 2.pi t=y/w; t=trunc(t); t*=w; y-=t; } if (fcomp(y,pi)>0) { y-=pi; if (type!=TAN) s=(-s); } w=pi/2; if (fcomp(y,w)>0) { y=pi-y; if (type!=SIN) s=(-s); } return s; } Float cos(const Float& f) { // see Brent - "The complexity of multiprecision arithmetic" int i,q,sgn; Float t,r,y,x=f; Float one=(Float)1; Big lambda; sgn=norm(COS,x); if (x.iszero()) return sgn*one; q=isqrt(MIRACL*precision,2); lambda=pow((Big)2,q); x/=(Float)lambda; r=0; y=one; x*=x; for (i=2;i<=q+2;i+=2) { t=x; t.negate(); t/=(i*(i-1)); y*=t; // y*=(-x/(i*(i-1))); if (!r.add(y)) break; } for (i=0;isb) return 1; if (sab.e) return sa; if (a.ey) return 1; if (x0) return PLUS; if (m<0) return MINUS; return 0; } Float operator-(const Float& f) { Float r=f; r.m.negate(); return r; } Float& Float::operator=(const Float &f) { e=f.e; m=f.m; return *this; } Float::Float(double d) { Big t; double ip,word; int c,s=PLUS; if (d<0) {s=MINUS; d=-d;} m=0; e=0; if (d==0.0) return; c=1; word=pow(2.0,(double)MIRACL); while (d>=word) { d/=word; c++; } while (d<1.0) { d*=word; c--; } d=modf(d,&ip); m=(mr_small)ip; forever { d*=word; d=modf(d,&ip); t=(mr_small)ip; m=shift(m,1)+t; if (d==0.0 || length(m)>precision) break; } e=c; if (s==MINUS) m.negate(); } Float& Float::operator=(double d) { Float t=d; *this=t; return *this; } 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;i0) for (i=0;i=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; } Float& Float::operator+=(const Float &b) { add(b); return *this; } 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; } Float& Float::operator-=(const Float &b) { sub(b); return *this; } Float operator+(const Float& a,const Float &b) { Float r=a; r+=b; return r; } Float operator-(const Float& a,const Float &b) { Float r=a; r-=b; return r; } Float& Float::operator*=(const Float& b) { BOOL extra; if (iszero() || b.isone()) return *this; if (b.iszero() || isone()) {*this=b; return *this;} if (&b==this) { if (m<0) m.negate(); // result will be positive m.shift(precision-length(m)); // make them precision length extra=fmth(precision,m,m,m); e+=e; if (extra) e--; } else { Big y=b.m; int s=PLUS; if (m<0) { s*=MINUS; m.negate(); } if (y<0) { s*=MINUS; y.negate(); } m.shift(precision-length(m)); // make them precision length y.shift(precision-length(y)); extra=fmth(precision,m,y,m); if (s<0) m.negate(); e+=b.e; if (extra) e--; } return *this; } Float operator*(const Float& a,const Float& b) { Float r=a; r*=b; return r; } Float operator*(const Float& a,int b) { Float r=a; r*=b; return r; } Float operator*(int a,const Float& b) { Float r=b; r*=a; return r; } Float& Float::operator*=(int x) { int olm=length(m); m*=x; e+=length(m)-olm; m.shift(precision-length(m)); return *this; } Float& Float::operator/=(int x) { int olm; if (x==1) return *this; m.shift(precision-length(m)); olm=length(m); m/=x; e+=length(m)-olm; m.shift(precision-length(m)); return *this; } Float operator/(const Float& f,int x) { Float r=f; r/=x; return r; } Float& Float::operator/=(const Float &f) { Float g=reciprocal(f); *this*=g; return *this; } Float operator/(const Float& a,const Float &b) { Float r=reciprocal(b); r*=a; return r; } void setprecision(int p) {precision=(1<