//
// LiDIA - a library for computational number theory
//   Copyright (c) 1994, 1995 by the LiDIA Group
//
// File        : bigfloat_int.h 
// Author      : Nigel Smart (NiSm), Patrick Theobald (PT)
// Last change : PT, Jan 23 1997, initial version
//		

#ifndef LIDIA_BIGFLOAT_INT_H
#define LIDIA_BIGFLOAT_INT_H

#include <LiDIA/bigint.h>
#include <LiDIA/bigrational.h>
#include <LiDIA/bigfloat.h>

class bigfloat_int
{
 private:

  /**
   **  An interval is represented by two bigfloats
   **     (Upp,Low)
   **/

  bigfloat Upp,Low;

  /**
   ** Private functions used for normalisation
   **/

  void normalize(bigfloat&,bigfloat&,bigfloat& ,bigfloat&);

 public:

  /**
   ** constructors and destructor; we coould leave out some of these
   **/

  bigfloat_int();
  bigfloat_int(int);
  bigfloat_int(long );
  bigfloat_int(unsigned long);
  bigfloat_int(double);
  bigfloat_int(const bigint & );
  bigfloat_int(const bigint & , const bigint & );
  bigfloat_int(const bigrational & );
  bigfloat_int(const bigfloat_int &);
  bigfloat_int(const bigfloat & );
  bigfloat_int(const bigfloat & ,const bigfloat & );
  ~bigfloat_int() {} ;

  /**
   ** member functions
   **/

  bool contains_zero() const;
  bool is_gt_zero() const;
  bool is_lt_zero() const;

  void assign_zero();
  void assign_one();
  void assign(int );
  void assign(long );
  void assign(unsigned long );
  void assign(double );
  void assign(const bigint & );
  void assign(const bigint & , const bigint & );
  void assign(const bigrational & );
  void assign(const bigfloat_int &);
  void assign(const bigfloat & );
  void assign(const bigfloat & ,const bigfloat & );

  // Routines For Approximation and conversion
  void dble(double &);
  void Approx();
  void approx(bigfloat& );
  void int_length(bigfloat& );

  /**
   ** assignment
   **/

  bigfloat_int & operator = (const bigfloat_int &);
  bigfloat_int & operator = (const bigfloat & );

  /**
   ** comparisons
   **/

  // I don't think it makes much sense to have a == operator
  //  != means definitely not equal (as do others)
  friend bool operator != (const bigfloat_int & , const bigfloat_int & );
  friend bool operator >  (const bigfloat_int & , const bigfloat_int & );
  friend bool operator <  (const bigfloat_int & , const bigfloat_int & );

  /**
   ** operator overloading
   **/

  friend bigfloat_int operator -  (const bigfloat_int & );
  friend bigfloat_int operator +  (const bigfloat_int & , const bigfloat_int & );
  friend bigfloat_int operator -  (const bigfloat_int & , const bigfloat_int & );
  friend bigfloat_int operator *  (const bigfloat_int & , const bigfloat_int & );
  friend bigfloat_int operator /  (const bigfloat_int & , const bigfloat_int & );
  
  bigfloat_int & operator +=  (const bigfloat_int & );
  bigfloat_int & operator -=  (const bigfloat_int & );
  bigfloat_int & operator *=  (const bigfloat_int & );
  bigfloat_int & operator /=  (const bigfloat_int & );

  bigfloat_int & operator ++ ();
  bigfloat_int & operator -- ();

  /**
   ** Procedural versions
   **/

  friend void add(bigfloat_int & , const bigfloat_int & , const bigfloat_int & );
  friend void add(bigfloat_int & , const bigfloat_int & , long );
  friend void add(bigfloat_int & , long , const bigfloat_int & );

  friend void subtract(bigfloat_int & , const bigfloat_int & , const bigfloat_int & );
  friend void subtract(bigfloat_int & , const bigfloat_int & , long );
  friend void subtract(bigfloat_int & , long , const bigfloat_int & );

  friend void multiply(bigfloat_int & , const bigfloat_int & , const bigfloat_int & );
  friend void multiply(bigfloat_int & , const bigfloat_int & , long );
  friend void multiply(bigfloat_int & , long , const bigfloat_int & );

  friend void divide(bigfloat_int & , const bigfloat_int & , const bigfloat_int & );
  friend void divide(bigfloat_int & , const bigfloat_int & , long);
  friend void divide(bigfloat_int & , long , const bigfloat_int & );

  void negate();
  friend void negate(bigfloat_int & , const bigfloat_int & );

  void invert();
  friend void invert(bigfloat_int & , const bigfloat_int & );

  friend void inc(bigfloat_int & );
  friend void dec(bigfloat_int & );

  int sign() const;
  void absolute_value();
  friend void truncate(bigint &, const bigfloat_int & );
  friend void round(bigint &, const bigfloat_int & );
  friend void floor(bigint &, const bigfloat_int & );
  friend void ceil(bigint &, const bigfloat_int & );



  /**
   ** Transcedental functions(procedural)
   **/

  friend void square(bigfloat_int & , const bigfloat_int & );
  friend void sqrt(bigfloat_int & , const bigfloat_int &);
  friend void sqr(bigfloat_int & , const bigfloat_int & );
  friend void exp(bigfloat_int & , const bigfloat_int & );
  friend void log(bigfloat_int & , const bigfloat_int & );
  friend void power(bigfloat_int & , const bigfloat_int & , const bigfloat_int & );
  friend void power(bigfloat_int & , const bigfloat_int & , long );
  friend void besselj(bigfloat_int & , int , const bigfloat_int & );

  /**
   ** (Inverse) trigonometrical functions(procedural)
   **/

  friend void sin(bigfloat_int & , const bigfloat_int & );
  friend void cos(bigfloat_int & , const bigfloat_int & );
  friend void tan(bigfloat_int & , const bigfloat_int & );
  friend void cot(bigfloat_int & , const bigfloat_int & );
  friend void asin(bigfloat_int & , const bigfloat_int & );
  friend void acos(bigfloat_int & , const bigfloat_int & );
  friend void atan(bigfloat_int & , const bigfloat_int & );
  friend void atan2(bigfloat_int &, const bigfloat_int & , const bigfloat_int & );
  friend void acot(bigfloat_int & , const bigfloat_int & );

  /**
   ** (Inverse) Hyperbolic trigonometrical functions(procedural)
   **/

  friend void sinh(bigfloat_int & , const bigfloat_int & );
  friend void cosh(bigfloat_int & , const bigfloat_int & );
  friend void tanh(bigfloat_int & , const bigfloat_int & );
  friend void coth(bigfloat_int & , const bigfloat_int & );
  friend void asinh(bigfloat_int & , const bigfloat_int & );
  friend void acosh(bigfloat_int & , const bigfloat_int & );
  friend void atanh(bigfloat_int & , const bigfloat_int & );
  friend void acoth(bigfloat_int & , const bigfloat_int & );

  /**
   ** Transcedental functions
   **/

  friend bigfloat_int square(const bigfloat_int & );
  friend bigfloat_int sqrt(const bigfloat_int & );
  friend bigfloat_int sqr(const bigfloat_int &);
  friend bigfloat_int exp(const bigfloat_int & );
  friend bigfloat_int log(const bigfloat_int & );

  friend bigfloat_int power(const bigfloat_int & , const bigfloat_int & );
  friend bigfloat_int power(const bigfloat_int & , long);
  friend bigfloat_int besselj(int , const bigfloat_int & );

  /**
   ** (Inverse) trigonometrical functions
   **/

  friend bigfloat_int sin(const bigfloat_int & );
  friend bigfloat_int cos(const bigfloat_int & );
  friend bigfloat_int tan(const bigfloat_int & );
  friend bigfloat_int cot(const bigfloat_int & );
  friend bigfloat_int asin(const bigfloat_int & );
  friend bigfloat_int acos(const bigfloat_int & );
  friend bigfloat_int atan(const bigfloat_int & );
  friend bigfloat_int atan2(const bigfloat_int & , const bigfloat_int & );
  friend bigfloat_int acot(const bigfloat_int & );

  /**
   ** (Inverse) Hyperbolic trigonometrical functions
   **/

  friend bigfloat_int sinh(const bigfloat_int & );
  friend bigfloat_int cosh(const bigfloat_int & );
  friend bigfloat_int tanh(const bigfloat_int & );
  friend bigfloat_int coth(const bigfloat_int & );
  friend bigfloat_int asinh(const bigfloat_int & );
  friend bigfloat_int acosh(const bigfloat_int & );
  friend bigfloat_int atanh(const bigfloat_int & );
  friend bigfloat_int acoth(const bigfloat_int & );

  /**
   ** Constants (procedural/functional)
   **/

  friend void constant_E(bigfloat_int &x);
  friend void constant_Pi(bigfloat_int &x);
  friend void constant_Euler(bigfloat_int &x);
  friend void constant_Catalan(bigfloat_int &x);

  /**
   ** Functions
   **/

  friend int sign(const bigfloat_int & );
  friend bigfloat_int abs(const bigfloat_int & );
  friend bigfloat_int inverse(const bigfloat_int & );
  friend bigint truncate(const bigfloat_int & );
  friend bigint round(const bigfloat_int & );
  friend bigint floor(const bigfloat_int & );
  friend bigint ceil(const bigfloat_int & );


  /**
   ** input/output
   **/

  friend istream & operator >> (istream & in, bigfloat_int & a);
  friend ostream & operator << (ostream & out, const bigfloat_int & a);

  friend void swap(bigfloat_int&, bigfloat_int&);

};

#endif

