/*******************************************************************************
+
+  LEDA 3.5
+
+  bigfloat.h
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/

/* This file has been automatically generated from "bigfloat.w"
   by CTANGLE (Version 3.1 [km2c]) */


#ifndef LEDA_BIGFLOAT_H
#define LEDA_BIGFLOAT_H

#if !defined(LEDA_ROOT_INCL_ID)
#define LEDA_ROOT_INCL_ID 350019
#include <LEDA/REDEFINE_NAMES.h>
#endif

#include <LEDA/integer.h>
#include <math.h>

enum rounding_modes{
TO_NEAREST= 0,TO_ZERO= 1,TO_P_INF= 2,TO_N_INF= 3,TO_INF= 4,EXACT= 5};


/*{\Manpage {bigfloat} {} {The data type bigfloat}
}*/



class bigfloat
{

/*{\Mdefinition
In general a |bigfloat| is given by two integers $s$ and $e$ where $s$ is the
significant and $e$ is the exponent.
The tuple $(s,e)$ represents the real number $$s \cdot 2^e.$$
In addition, there are the special |bigfloat| values |NaN| (not a number),
|pZero|, |nZero| ($= +0, -0$), and |pInf|, |nInf| ($= +\infty, -\infty$).
These special values behave as defined by the IEEE floating
point standard.
In particular,
$\frac{5}{+0}=\infty$, $\frac{-5}{+0}=-\infty$, $\infty+1=\infty$,
$\frac{5}{\infty}=+0$, $+\infty+(-\infty)=NaN$ and $0 \cdot \infty = NaN$.

Arithmetic on |bigfloat|s uses two parameters:
The precision |prec| of the result (in number of binary digits) and the
rounding mode |mode|.
Possible rounding modes are:
\begin{itemize}
\item |TO_NEAREST|: round to the closest representable value
\item |TO_ZERO|: round towards zero
\item |TO_INF|: round away from zero
\item |TO_P_INF|: round towards $+\infty$
\item |TO_N_INF|: round towards $-\infty$
\item |EXACT|: compute exactly for |+,-,*| and round to nearest otherwise
\end{itemize}
Operations $+$, $-$, $*$ work as follows.
First, the exact result |z| is computed.
If the rounding mode is EXACT then |z| is the result of the operation.
Otherwise, let |s| be the significant of the result; |s| is rounded to |prec|
binary places as dictated by |mode|.
Operations $/$ and $\sqrt{\hspace{1ex}}$ work accordingly except that
EXACT is treated as TO\_NEAREST.

The parameters |prec| and |mode| are either set directly for a single
operation or else they are set globally for every operation to follow.
The default values are 53 for |prec| and TO\_NEAREST for |mode|.
}*/

public:

enum output_modes{BIN_OUT= 0,DEC_OUT= 1};

static const bigfloat pZero;
static const bigfloat nZero;
static const bigfloat nInf;
static const bigfloat pInf;
static const bigfloat NaN;

static const bigfloat zero;
static const bigfloat one;

enum special_values
{NOT_VAL,PZERO_VAL,NZERO_VAL,PINF_VAL,NINF_VAL,NAN_VAL};

static long global_prec;
static rounding_modes round_mode;
static bool dbool;
static output_modes output_mode;

private:


integer significant,exponent;
special_values special;
long precision;



friend long sign_of_special_value(const bigfloat&x);



bigfloat(special_values sp);

public:

/*{\Mcreation x }*/

/*{\Mtext
A |bigfloat| may be constructed from data types |double|, |long|, |int| and
|integer|, without loss of accuracy.
In addition, an instance of type |bigfloat| can be created as follows.
}*/

~bigfloat(){}
bigfloat();
bigfloat(double);
bigfloat(long);
bigfloat(int);
bigfloat(const integer&);

bigfloat(const integer&s,const integer&e);
/*{\Mcreate introduces a variable |\Mvar| of type \Mtype
     and initializes it to $s \cdot 2^e$
    }*/


/*{\Moperations 1.7 3.5
  }*/

/*{\Mtext
The arithmetical operators |+|, |-|, |*|, |/|, |+=|, |-=|, |*=|, |/=|,
$\mathit{sqrt}$, the comparison operators $<$, $\leq$, $>$, $\geq$ , $=$,
$\neq$ and the stream operators |<<| and |>>| are available.
Addition, subtraction, multiplication, division and square root are implemented
by the functions |add|, |sub|, |mul|, |div| and |sqrt|, respectively.
For example, the call
\begin{center} |add(x, y, prec, mode, is_exact)| \end{center}
computes the sum of \Mtype{s} |x| and |y| with |prec| binary digits, in
rounding mode |mode|, and returns it.
The optional last parameter |is_exact| is a boolean variable that is set to
|true| if and only if the returned bigfloat exactly equals the sum of
|x| and |y|.
The parameters |prec| and |mode| are also optional and have the global default
values |global_prec| and |round_mode| respectively,
that is, the three calls |add(x, y, global_prec, round_mode)|,
|add(x, y, global_prec)|, and |add(x, y)| are all equivalent.
The syntax for functions |sub|, |mul|, |div|, and |sqrt| is analogous.

The operators $+$, $-$, $*$, and $/$ are implemented
by their counterparts among the functions
|add|, |sub|, |mul| and |div|.
For example, the call $x+y$ is equivalent to |add(x,y)|.
}*/

friend bigfloat add(const bigfloat&,const bigfloat&,
long prec= bigfloat::global_prec,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool);

friend bigfloat sub(const bigfloat&,const bigfloat&,
long prec= bigfloat::global_prec,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool);

friend bigfloat mul(const bigfloat&,const bigfloat&,
long prec= bigfloat::global_prec,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool);

friend bigfloat div(const bigfloat&,const bigfloat&,
long prec= bigfloat::global_prec,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool);

friend bigfloat sqrt(const bigfloat&,
long prec= bigfloat::global_prec,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool,
const bigfloat&start= bigfloat::pZero);

friend bigfloat operator+(const bigfloat&a,const bigfloat&b);
friend bigfloat operator-(const bigfloat&a,const bigfloat&b);
friend bigfloat operator*(const bigfloat&a,const bigfloat&b);
friend bigfloat operator/(const bigfloat&a,const bigfloat&b);
friend bigfloat operator-(const bigfloat&);

friend bigfloat operator+= (bigfloat&a,const bigfloat&b);
friend bigfloat operator-= (bigfloat&a,const bigfloat&b);
friend bigfloat operator*= (bigfloat&a,const bigfloat&b);
friend bigfloat operator/= (bigfloat&a,const bigfloat&b);

friend bool operator==(const bigfloat&,const bigfloat&);
friend bool operator>(const bigfloat&,const bigfloat&);
friend bool operator!=(const bigfloat&a,const bigfloat&b);
friend bool operator>=(const bigfloat&a,const bigfloat&b);
friend bool operator<(const bigfloat&a,const bigfloat&b);
friend bool operator<=(const bigfloat&a,const bigfloat&b);

/*{\Mtext
  A |bigfloat| |\Mvar| can be rounded by the call
  |round(\Mvar,prec,mode,is_exact)|. %,bias)
  %Here bias is an optional integer variable taking values in $\{-1,0,+1\}$,
  %with default value $0$.
  %If \Mvar is nonzero, the function |round| rounds
  %\Mvar $+$ bias $\cdot \epsilon$,
  %where $\epsilon$ is a positive infinitesimal, with prec binary digits
  %in rounding mode mode.
  The optional boolean variable |is_exact| is set to true if and only if the
  rounding operation did not change the value of |\Mvar|.
  % and bias=0.
  }*/

friend bigfloat round(const bigfloat&y,long digits= 0,
rounding_modes mode= bigfloat::round_mode,
bool&is_exact= bigfloat::dbool,long bias= 0);

/*{\Mtext |bigfloat|s offer a small set of mathematical functions
  (e.g. |abs|, |log2|,
  |ceil|, |floor|, |sign|), functions to test for special values, conversions
  to |double|s and |integer|s, functions to access |significant| and
  |exponent|, and functions to set the global precision, the rounding mode
  and the output mode.
  }*/

friend bool isNaN(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |\Mvar| is in special state |NaN|
  }*/
friend bool isnInf(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |\Mvar| is in special state |nInf|
  }*/
friend bool ispInf(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |\Mvar| is in special state |pInf|
  }*/
friend bool isnZero(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |\Mvar| is in special state |nZero|
  }*/
friend bool ispZero(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |\Mvar| is in special state |pZero|
  }*/
friend bool isZero(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |ispZero(\Mvar)| or |isnZero(\Mvar)|
  }*/
friend bool isInf(const bigfloat&x);
/*{\Mfunc returns |true| if and only if |ispInf(\Mvar)| or |isnInf(\Mvar)|
  }*/

inline friend bool isSpecial(const bigfloat&x)
{return(x.special!=bigfloat::NOT_VAL);}
/*{\Mfunc returns |true| if and only if |\Mvar| is in a special state
  }*/

friend long sign(const bigfloat&x);
/*{\Mfunc returns the sign of |\Mvar|.
  }*/

friend bigfloat abs(const bigfloat&x);
/*{\Mfunc returns the absolute value of |\Mvar|
  }*/
friend bigfloat pow2(const integer&p);
/*{\Mfunc returns $2^p$
  }*/
friend bigfloat sqrt_d(const bigfloat&x,long p,int d= 2);
/*{\Mfunc returns $\sqrt[d]{x}$, with relative error $\leq 2^{-p}$
            but not necessarily exactly rounded to $p$ binary digits
  }*/
friend integer ilog2(const bigfloat&x);
/*{\Mfunc returns the binary logarithm of abs(|\Mvar|), rounded up to the
    next integer. \precond |\Mvar| $\neq 0$
  }*/
friend integer ceil(const bigfloat&x);
/*{\Mfunc returns |\Mvar|, rounded up to the next integer
  }*/
friend integer floor(const bigfloat&x);
/*{\Mfunc returns |\Mvar|, rounded down to the next integer
  }*/
friend integer to_integer(bigfloat x,
rounding_modes rmode= TO_NEAREST);
/*{\Mfuncl returns the integer value next to |\Mvar|
     (in the given rounding mode)
  }*/


friend double to_double(const bigfloat&x);
/*{\Mfunc returns the double value next to |\Mvar| (in rounding mode
     |TO_NEAREST|
  }*/

friend ostream& operator<<(ostream&os,const bigfloat&x);
/*{\Mbinopfuncl writes |\Mvar| to output stream |os|
  }*/
friend istream& operator>>(istream&is,bigfloat&x);
/*{\Mbinopfuncl reads |\Mvar| from input stream |is| in decimal format
  }*/

long get_significant_length(void)const;
/*{\Mop returns the length of the significant of |\Mvar|
  }*/
integer get_exponent(void)const;
/*{\Mop returns the exponent of |\Mvar|
  }*/
integer get_significant(void)const;
/*{\Mop returns the significant of |\Mvar|
  }*/

static long set_precision(long p);
/*{\Mstaticl sets the global precision to p and returns the old precision
  }*/
static rounding_modes set_rounding_mode(rounding_modes m);
/*{\Mstaticl sets the global rounding mode to m and returns the old
     rounding mode
  }*/
static output_modes set_output_mode(output_modes o_mode);
/*{\Mstaticl sets the output mode to |o_mode| and returns the old
      output mode
  }*/

void normalize();

};

inline int compare(const bigfloat&x,const bigfloat&y)
{return sign(x-y);}
inline char*leda_tname(const bigfloat*){return"bigfloat";}


#if LEDA_ROOT_INCL_ID == 350019
#undef LEDA_ROOT_INCL_ID
#include <LEDA/UNDEFINE_NAMES.h>
#endif


#endif


