/**************************************************************************\ MODULE: xdouble SUMMARY: The class xdouble is used to represent floating point numbers with the same precision as a 'double', but with extended exponent range (offering a few more bits than that of a 'long' for the exponent). The programming interface for xdoubles is almost identical to that of ordinary doubles. \**************************************************************************/ #include <NTL/ZZ.h> class xdouble { public: xdouble(); // = 0 xdouble(const xdouble& a); // copy constructor explicit xdouble(double a); // promotion constructor xdouble& operator=(const xdouble& a); // assignment operator xdouble& operator=(double a); ~xdouble(); double mantissa() const; // read-only access to mantissa long exponent() const; // read-only access to exponenent static void SetOutputPrecision(long p); // This sets the number of decimal digits to be output. Default is // 10. static long OutputPrecision(); // returns current output precision. }; /**************************************************************************\ Arithmetic Operations The following are the standard arithmetic operators, whose meaning should be clear. \**************************************************************************/ xdouble operator+(const xdouble& a, const xdouble& b); xdouble operator-(const xdouble& a, const xdouble& b); xdouble operator*(const xdouble& a, const xdouble& b); xdouble operator/(const xdouble& a, const xdouble& b); // PROMOTIONS: +, -, *, / promote double to xdouble on (a, b). xdouble operator-(const xdouble& a); xdouble& operator+=(xdouble& a, const xdouble& b); xdouble& operator+=(xdouble& a, double b); xdouble& operator-=(xdouble& a, const xdouble& b); xdouble& operator-=(xdouble& a, double b); xdouble& operator*=(xdouble& a, const xdouble& b); xdouble& operator*=(xdouble& a, double b); xdouble& operator/=(xdouble& a, const xdouble& b); xdouble& operator/=(xdouble& a, xdouble b); xdouble& operator++(xdouble& a); // prefix void operator++(xdouble& a, int); // postfix xdouble& operator--(xdouble& a); // prefix void operator--(xdouble& a, int); // postfix /**************************************************************************\ Comparison \**************************************************************************/ long sign(const xdouble& a); // returns sign (+1, -1, 0) of a long compare(const xdouble& a, const xdouble& b); // returns sign of a - b long operator==(const xdouble& a, const xdouble& b); long operator!=(const xdouble& a, const xdouble& b); long operator<=(const xdouble& a, const xdouble& b); long operator>=(const xdouble& a, const xdouble& b); long operator <(const xdouble& a, const xdouble& b); long operator >(const xdouble& a, const xdouble& b); // PROMOTIONS: compare and operators ==, ..., > promote double to xdouble // on (a, b). /**************************************************************************\ Input/Output Input Syntax: <number>: [ "-" ] <unsigned-number> <unsigned-number>: <dotted-number> [ <e-part> ] | <e-part> <dotted-number>: <digits> | <digits> "." <digits> | "." <digits> | <digits> "." <digits>: <digit> <digits> | <digit> <digit>: "0" | ... | "9" <e-part>: ( "E" | "e" ) [ "+" | "-" ] <digits> Examples of valid input: 17 1.5 0.5 .5 5. -.5 e10 e-10 e+10 1.5e10 .5e10 .5E10 Note that the number of decimal digits of precision that are used for output can be set to any number p >= 1 by calling the routine xdouble::SetOutputPrecision(p). The default value of p is 10. The current value of p is returned by a call to xdouble::OutputPrecision(). \**************************************************************************/ ostream& operator<<(ostream& s, const xdouble& a); istream& operator>>(istream& s, xdouble& x); /**************************************************************************\ Miscellaneous \**************************************************************************/ xdouble trunc(const xdouble& a); // returns integer obtained by truncating xdouble floor(const xdouble& a); // returns greatest integer <= a xdouble ceil(const xdouble& a); // returns smallest integer >= a xdouble fabs(const xdouble& a); // returns |a| xdouble sqrt(const xdouble& a); // returns a^{1/2}; error is raised if a < 0 double log(const xdouble& a); // returns log(a) (note return val is double!) xdouble xexp(double a); // returns exp(a) (note argument is double!) xdouble exp(const double& a); // equivalent to xexp(to_double(a)) void power(xdouble& z, const xdouble& a, const ZZ& e); xdouble power(const xdouble& a, const ZZ& e); void power(xdouble& z, const xdouble& a, long e); xdouble power(const xdouble& a, long e); // z = a^e, e may be negative void power2(xdouble& z, long e); xdouble power2_xdouble(long e); // z = 2^e, e may be negative void MulAdd(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c); xdouble MulAdd(const xdouble& a, const xdouble& b, const xdouble& c); // z = a + b*c, but faster void MulSub(xdouble& z, const xdouble& a, const xdouble& b, const xdouble& c); xdouble MulSub(const xdouble& a, const xdouble& b, const xdouble& c); // z = a - b*c, but faster /**************************************************************************\ Implementation details: An xdouble is represented as a mantissa/exponent pair (x, e), where x is a double and e is a long. The real number represented by (x, e) is x * NTL_XD_BOUND^e, where NTL_XD_BOUND = NTL_XD_HBOUND^2, and NTL_XD_HBOUND = 2^{(max(NTL_DOUBLE_PRECISION,NTL_BITS_PER_LONG)+4)}. Also, the mantissa x satisfies 1/NTL_XD_HBOUND <= |x| <= NTL_XD_HBOUND, except that the number 0 is always represented as (0, 0). Both NTL_XD_BOUND and NTL_XD_HBOUND are macros defined in <NTL/xdouble.h>. SIZE INVARIANT: |e| < 2^(NTL_BITS_PER_LONG-4). \**************************************************************************/