/*******************************************************************************
+
+  LEDA 3.5
+
+  rational.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.
+ 
*******************************************************************************/
#ifndef LEDA_RATIONAL_H
#define LEDA_RATIONAL_H

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


/*{\Manpage {rational} {} {Rational Numbers}}*/

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

class rational
{

/*{\Mdefinition An instance $q$ of type |\Mname| is a rational number
where the numerator and the denominator are both of type
$integer$.}*/

protected:
  integer num; // numerator
  integer den; // denominator, always nonzero and positive


public:

/*{\Mcreation q}*/

  rational() : num(0), den(1) {}
/*{\Mcreate creates an instance |\Mvar| of type |\Mname|.}*/

  rational(integer n) : num(n), den(1) {}
/*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes it
            with the integer $n$.}*/


/*{\Moptions nextwarning=no }*/
  rational(int, int);

  rational(integer n, integer d);
/*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes its
            the rational number $n/d$.}*/

  rational(double x);
/*{\Mcreate creates an instance |\Mvar| of type |\Mname| and initializes it
            with the value of $x$.}*/


  rational(const rational& r) : num(r.num), den(r.den) {}

  rational& operator=(const rational&);


 ~rational() {}


/*{\Moperations 2 5}*/

/*{\Mtext

The arithmetic operations $+,\ -,\ *,\ /,\ +=,\
-=,\ *=,\ /=,\ -$(unary), $++,\ --$,  
the comparison operations $<,\ <=,\ >,\ 
>=,\ ==,\ !=$ and the stream operations are all available.}*/

  rational& operator+= (const rational& r);
  rational& operator-= (const rational&);
  rational& operator*= (const rational&);
  rational& operator/= (const rational&);
  rational& operator++ ();
  rational& operator-- ();

// arithmetic operators

  friend rational operator+ (const rational& q, const rational& r);
  friend rational operator- (const rational& q, const rational& r);
  friend rational operator* (const rational& q, const rational& r);
  friend rational operator/ (const rational& q, const rational& r);
  friend rational operator- (const rational&);

// comparison operators

  static int cmp(const rational&, const rational&);

  friend bool operator==(const rational& q, const rational& r);
  friend bool operator==(const rational& q, const integer& a);
  friend bool operator==(const integer& n, const rational& q);
  friend bool operator==(const rational& q, int n);
  friend bool operator==(int n, const rational& q);

  friend bool operator!=(const rational& q, const rational& r);
  friend bool operator!=(const rational& q, int n);
  friend bool operator!=(int n, const rational& q);
  friend bool operator!=(const rational& q, const integer& a);
  friend bool operator!=(const integer& n, const rational& q);

  friend bool operator< (const rational& q, const rational& r);
  friend bool operator<=(const rational& q, const rational& r);
  friend bool operator> (const rational& q, const rational& r);
  friend bool operator>=(const rational& q, const rational& r);


  integer numerator() const;
/*{\Mop returns the numerator of $q$.}*/

  integer denominator() const;
/*{\Mop returns the denominator of $q$.}*/

  rational& simplify(const integer& a);
/*{\Mop simplifies $q$ by $a$.\\
        \precond $a$ divides the numerator and the denominator of $q$.}*/

  rational& normalize();
/*{\Mop normalizes |\Mvar|.}*/

  void negate(); 
/*{\Mop negates |\Mvar|.}*/

  void invert(); 
/*{\Mop inverts |\Mvar|.}*/

  rational inverse();  
/*{\Mop returns the inverse of |\Mvar|.}*/

  double to_double () const;
/*{\Mfunc returns a double floating point approximation of |\Mvar|. }*/

  double todouble() const { return to_double(); }
/*{\Xop returns a double floating point approximation of |\Mvar|. }*/



/*{\Mtext
\smallskip
{\bf Non-member functions}
\smallskip }*/

  friend int sign(const rational& q);
/*{\Mfunc returns the sign of $q$.}*/

  friend rational abs(const rational& q);
/*{\Mfunc returns the absolute value of $q$.}*/

  friend rational sqr(const rational& q);
/*{\Mfunc returns the square of $q$.}*/

  friend integer trunc(const rational& q);
/*{\Mfunc returns the $integer$ with the next smaller absolute value.}*/

  friend rational pow(const rational& q, int n); 
/*{\Mfunc returns the $n$-th power of $q$.}*/

  friend rational pow(const rational& q, integer a); 
/*{\Mfunc returns the $a$-th power of $q$.}*/

  friend integer floor(const rational& q);
/*{\Mfunc returns the next smaller $integer$.}*/

  friend integer ceil(const rational& q);
/*{\Mfunc returns the next bigger $integer$.}*/

  friend integer round(const rational& q);
/*{\Mfunc rounds $q$ to the nearest $integer$.}*/


  friend double Double(const rational& q) { return q.to_double(); }
/*{\Mfunc returns a double floating point approximation of $q$.}*/



  friend istream& operator>> (istream& in, rational& q);
  friend ostream& operator<< (ostream& out, const rational& q);

};


rational small_rational_between(const rational& p, const rational& q);
/*{\Mfunc returns a }*/

rational small_rational_near(const rational& p, rational eps);
/*{\Mfunc returns a }*/


inline char* leda_tname(const rational*) { return "rational"; }

inline int compare(const rational& x, const rational& y) 
{ return rational::cmp(x,y); } 



/*{\Mimplementation A $rational$ is implemented by two $integer$
numbers which represent the numerator and the denominator. The sign
is represented by the sign of the numerator.}*/


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


#endif

