    /**************************************************************************\

    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).

    \**************************************************************************/