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

MODULE: RR

SUMMARY:

The class RR is used to represent arbitrary-precision floating point numbers.

Here is a simple program that reads two numbers and prints their product:

#include "ZZ.h"

main()
{
   RR a, b, prod;


   cin >> a;
   cin >> b;
   mul(prod, a, b);
   cout << prod << "\n";
}


The arithmetic operations always round their results to p bits,
where p is the current precision.
The current precision can be changed using RR::SetPrecision(),
and can be read using RR:: precision().
All arithmetic operations are implemented so that the effect is
as if the result was computed exactly, and then rounded to p bits.
If a number lies exactly half-way between two p-bit numbers,
the "round to even" rule is used.

Note that because precision is variable, a number may be computed with 
a precision p', and then be used as input to an arithmetic
operation when the current precision is p < p'.
The above rounding rule still applies; in particular,
no rounding is done until *after the operation is performed.
In the case of the assignment and copy constructors, the result
is always rounded to the current precision. 

The above rounding rules apply to all arithmetic operations in this module,
but not to the input/output routines.
For the input routine, if scientific notation is not used,
the rule still applies, but if scientific notation is used,
only a very close approximation of the input is computed
(to within a relative error of less than 2^{-p}).
For the output routine, only a very good decimal approximation is computed.

Unlike IEEE standard floating point, there are no "special values",
like "infinity" or "not a number", nor are there any "denormalized numbers".
Overflow, underflow, or taking a square root of a negative
number all result in an error being raised.

An RR is represented as a mantissa/exponent pair (x, e),
where x is a ZZ and e is a long.
The real number represented by (x, e) is x * 2^e.
Zero is always represented as (0, 0).
For all other numbers, x is always odd.

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



#include "ZZ.h"
#include "xdouble.h"

class RR {

public:

RR(); // = 0

void operator=(const RR& a); 
RR(const RR& a);
~RR();

const ZZ& mantissa() const;  // read the mantissa
long exponent();  // read the exponent

static void SetPrecision(long p);  // set current precision to p bits
                                   // default is 90, minimum is 53

static long precision();  // read current value of precision

static void SetOutputPrecision(long p);  
// set the number of output decimal digits to p

static long OutputPrecision();
// read the current number of output decimal digits


};


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

                                 Basic Routines 

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



long IsZero(const RR& a); // test if 0

long IsOne(const RR& a); // test if 1

long sign(const RR& a);  // returns sign of a (+1, -1, 0)

void clear(RR& z);  // z = 0

void set(RR& z);  // z = 1

void swap(RR& a, RR& b);  // swaps a and b (by swapping pointers)

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

                                  Addition

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


void add(RR& z, const RR& a, const RR& b);
void add(RR& z, const RR& a, long b);
void add(RR& z, const RR& a, int b);
void add(RR& z, const RR& a, double b);
void add(RR& z, const RR& a, float b);
void add(RR& z, long a, const RR& b);
void add(RR& z, int a, const RR& b);
void add(RR& z, double a, const RR& b);
void add(RR& z, float a, const RR& b);

// z = a + b


void sub(RR& z, const RR& a, const RR& b);
void sub(RR& z, const RR& a, long b);
void sub(RR& z, const RR& a, int b);
void sub(RR& z, const RR& a, double b);
void sub(RR& z, const RR& a, float b);
void sub(RR& z, long a, const RR& b);
void sub(RR& z, int a, const RR& b);
void sub(RR& z, double a, const RR& b);
void sub(RR& z, float a, const RR& b);

// z = a - b


void negate(RR& z, const RR& a);

// z = -a

void abs(RR& z, const RR& a);

// z = |a|


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

                                  Multiplication

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



void mul(RR& z, const RR& a, const RR& b);
void mul(RR& z, const RR& a, long b);
void mul(RR& z, const RR& a, int b);
void mul(RR& z, const RR& a, double b);
void mul(RR& z, const RR& a, float b);
void mul(RR& z, long a, const RR& b);
void mul(RR& z, int a, const RR& b);
void mul(RR& z, double a, const RR& b);
void mul(RR& z, float a, const RR& b);

// z = a * b

void sqr(RR& z, const RR& a);

// z = a * a


void div(RR& z, const RR& a, const RR& b);
void div(RR& z, const RR& a, long b);
void div(RR& z, const RR& a, int b);
void div(RR& z, const RR& a, double b);
void div(RR& z, const RR& a, float b);
void div(RR& z, long a, const RR& b);
void div(RR& z, int a, const RR& b);
void div(RR& z, double a, const RR& b);
void div(RR& z, float a, const RR& b);

// z = a / b

void inv(RR& z, const RR& a);

// z = 1 / a



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

                                  Comparison

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


long compare(const RR& a, const RR& b);
long compare(const RR& a, long b);
long compare(const RR& a, int b);
long compare(const RR& a, double b);
long compare(const RR& a, float b);

// returns sign(a-b)



// following are standard comparison operators

long operator==(const RR& a, const RR& b);
long operator!=(const RR& a, const RR& b);
long operator<=(const RR& a, const RR& b);
long operator>=(const RR& a, const RR& b);
long operator <(const RR& a, const RR& b);
long operator >(const RR& a, const RR& b);

long operator==(const RR& a, long b);
long operator!=(const RR& a, long b);
long operator<=(const RR& a, long b);
long operator>=(const RR& a, long b);
long operator <(const RR& a, long b);
long operator >(const RR& a, long b);

long operator==(const RR& a, int b);
long operator!=(const RR& a, int b);
long operator<=(const RR& a, int b);
long operator>=(const RR& a, int b);
long operator <(const RR& a, int b);
long operator >(const RR& a, int b);

long operator==(const RR& a, double b);
long operator!=(const RR& a, double b);
double operator<=(const RR& a, double b);
double operator>=(const RR& a, double b);
double operator <(const RR& a, double b);
double operator >(const RR& a, double b);

long operator==(const RR& a, float b);
long operator!=(const RR& a, float b);
long operator<=(const RR& a, float b);
long operator>=(const RR& a, float b);
long operator <(const RR& a, float b);
long operator >(const RR& a, float b);



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

                                  Miscellaneous

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


void trunc(RR& z, const RR& a);  // z = a, truncated to 0
void floor(RR& z, const RR& a);  // z = a, truncated to -infinity
void ceil(RR& z, const RR& a);   // z = a, truncated to +infinity

void power(RR& z, const RR& a, long e);
void power(RR& z, long a, long e);
void power(RR& z, int a, long e);
void power(RR& z, double a, long e);

// z = a^e, e may be negative



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

                                  Conversion

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


void operator<<(RR& z, const ZZ& a);
void operator<<(RR& z, long a);
void operator<<(RR& z, int a);
void operator<<(RR& z, double a);
void operator<<(RR& z, float a);
void operator<<(RR& z, xdouble a);

// z = a


void operator<<(ZZ& z, const RR& a);  // z = floor(a)
void operator<<(long& z, const RR& a);  // z = floor(a)
void operator<<(double& z, const RR& a);  // z = a
void operator<<(xdouble& z, const RR& a);  // z = a

// functional versions:

long Long(const RR& a);
double Double(const RR& a);
xdouble XDouble(const RR& a);





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

                               Input/Output
Input Syntax:

<number>: [ white-space ] [ "-" ] [ white-space ] <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
  -  .5
e10
e-10
e+10
1.5e10
.5e10
.5E10

Examples of invalid input:

.e10
1.5e - 10
1.5 e10


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



ostream& operator<<(ostream& s, const RR& a);

istream& operator>>(istream& s, RR& x);


