// DO NOT INCLUDE THIS FILE DIRECTLY. IT IS PARAMETERIZED // // LargeReal.h --- // a class for handling large or small signed numbers, similar to // (and based on) Prob class, which handles only non-negative numbers. // // Contributions from dfong, leslie, and rph. // // class OTHERREAL; class LRC : public AbstractLargeReal { LRCPROBTYPE mag; // the abs val of the quantity char nonneg; // flag: the quantity is not <0 public: LRC(LargeRealSign s, const LRCPROBTYPE& amag) : nonneg(s), mag(amag) { } LRC(const int asign, const LRCPROBTYPE& amag) : mag(amag) { if (asign > 0) nonneg = Pos; else nonneg = Neg; } LRC(const LRCPROBTYPE& amag) : nonneg(Pos), mag(amag) { } LRC(const double d) { if ((nonneg = (d>=0))) mag = (from_double) d; else mag = (from_double) - d; } LRC() : nonneg(Pos), mag() {; } LRC(LargeRealSign s) : nonneg(s), mag() {; } LRC(ConstProb c) : nonneg(Pos), mag (c) {;} inline LRC (const OTHERREAL r); int valid() const {return mag.valid();} int is_zero() const {return mag.is_zero();} LRCPROBTYPE ret_mag() const {return mag;} int is_nonneg() const {return nonneg;} int sgn() const {return is_zero()?0 : nonneg?1 :-1;} // treats zero as positive number. int is_positive() const {return nonneg;} double ret_double() const {return nonneg?mag.ret_double():-mag.ret_double();} friend int bigger(const LRC& a, const LRC& b) {return a.mag >= b.mag;} #define ASGOPDECL(T, op) friend INLINE T& operator op ## =(T&, const T&) ASGOPDECL(LRC, +); ASGOPDECL(LRC, -); ASGOPDECL(LRC, *); ASGOPDECL(LRC, /); #define BINOPDECL(T, op) friend INLINE T operator op(const T&, const T&) BINOPDECL(LRC, +); BINOPDECL(LRC, -); BINOPDECL(LRC, *); BINOPDECL(LRC, /); LRC operator-() const; #define RELOPDECL(T, op) friend INLINE int operator op(const T&, const T&) RELOPDECL(LRC, !=); RELOPDECL(LRC, ==); RELOPDECL(LRC, <); RELOPDECL(LRC, <=); RELOPDECL(LRC, >); RELOPDECL(LRC, >=); inline void print(ostream&) const; inline void rawprint(ostream&) const; }; // end of class inline int approxEqual(LRC const & a, LRC const & b) { if (a.sgn() == b.sgn()) return approxEqual (a.ret_mag(), b.ret_mag()); else return (approxEqual (a.ret_mag(), LRCPROBTYPE(LRCPROBTYPE::Zero)) && approxEqual (b.ret_mag(), LRCPROBTYPE(LRCPROBTYPE::Zero))); } // These are needed to avoid type confusion over // the various from_double casts. inline int approxEqual (LRC const &a, double const &b) {return approxEqual (a, (LRC) b); } inline int approxEqual (double const &b, LRC const &a) {return approxEqual (a, (LRC) b); } inline LRC log(LRC const &a) {assert (a.is_nonneg()); return LRC (log (a.ret_mag()));} inline LRC pow(const LRC &a, double r) { if (r < 0.0) { return(LRC((int)(a.is_nonneg()), pow(a.ret_mag(), -r))); } return(LRC((int)(a.is_nonneg()), pow(a.ret_mag(), r))); } inline int operator ==(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ? (a.mag == b.mag) : ( (a.mag.is_zero() ) & (b.mag.is_zero() ) ) ) :(b.nonneg ? ( (b.mag.is_zero() ) & (a.mag.is_zero() ) ) : (b.mag == a.mag) ); } inline int operator !=(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ? (a.mag != b.mag) : !( (a.mag.is_zero() ) & (b.mag.is_zero() ) ) ) :(b.nonneg ? !( (b.mag.is_zero() ) & (a.mag.is_zero() ) ) : (b.mag != a.mag) ); } inline int operator <(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ?(a.mag < b.mag) : (0) ) :(b.nonneg ?(1) : (b.mag < a.mag) ); } inline int operator >(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ?(a.mag > b.mag) : (1) ) :(b.nonneg ?(0) : (b.mag > a.mag) ); } inline int operator <=(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ? (a.mag <= b.mag) : ( (a.mag.is_zero() ) & (b.mag.is_zero() ) ) ) :(b.nonneg ? ( (b.mag.is_zero() ) & (a.mag.is_zero() ) ) : (b.mag <= a.mag) ); } inline int operator >=(const LRC& a, const LRC& b) { return a.nonneg ?(b.nonneg ? (a.mag >= b.mag) : ( (a.mag.is_zero() ) & (b.mag.is_zero() ) ) ) :(b.nonneg ? ( (b.mag.is_zero() ) & (a.mag.is_zero() ) ) : (b.mag >= a.mag) ); } inline LRC LRC::operator-() const /* unary- */ {return LRC(!nonneg, mag);} inline LRC operator+(const LRC& a, const LRC& b) { LRC r; if (a.nonneg == b.nonneg) {r.nonneg = a.nonneg; r.mag = a.mag+b.mag;} else if (bigger(a,b)) {r.nonneg = a.nonneg; r.mag = a.mag-b.mag;} else {r.nonneg = b.nonneg; r.mag = b.mag-a.mag;} return r; } inline LRC operator-(const LRC& a, const LRC& b) { LRC r; if (a.nonneg == b.nonneg) if (bigger(a,b)) {r.nonneg = a.nonneg; r.mag = a.mag-b.mag;} else {r.nonneg = ! b.nonneg; r.mag = b.mag-a.mag;} else {r.nonneg = a.nonneg; r.mag = a.mag+b.mag;} return r; } inline LRC operator*(const LRC& a, const LRC& b) { LRC r; r.nonneg = (a.nonneg == b.nonneg); r.mag = a.mag*b.mag; return r; } inline LRC operator/(const LRC& a, const LRC& b) { LRC r; r.nonneg = (a.nonneg == b.nonneg); r.mag = a.mag/b.mag; return r; } #define ASGOPDEF(T, op) inline \ T& operator op ## =(T& a, const T& b) {a = a op b; return a;} ASGOPDEF(LRC, +) ASGOPDEF(LRC, -) ASGOPDEF(LRC, *) ASGOPDEF(LRC, /) #undef ASGOPDEF inline ostream& operator<<(ostream& S, const LRC& r) {r.print(S); return S;} inline void LRC::print(ostream& S) const {S << (nonneg?'+' :'-') << mag;} inline void LRC::rawprint(ostream& S) const { S << '[' << (is_nonneg()?'+':'-') << ',' << setw(12)<