//
// LiDIA - a library for computational number theory
//   Copyright (c) 1995 by the LiDIA Group
//
// File        : bigrational.h 
// Author      : Thomas Papanikolaou (TP)
// Last change : TP, Jan 29 1995, initial version 
//		 MM, Sep 11 1996, added 
//		     assign(const bigint&, const bigint&)
//

#ifndef LIDIA_BIGRATIONAL_H
#define LIDIA_BIGRATIONAL_H

#include <LiDIA/bigint.h>

class bigrational
{
  /**
   ** the C++ type we use to represent a bigrational
   **/

  bigint num, den;
  void normalize();

 public:

  /**
   ** constructors and destructor we could leave out some of these
   **/

  bigrational();
  bigrational(int i);
  bigrational(long l);
  bigrational(unsigned long ul);
  bigrational(double d);
  bigrational(const bigint & n);
  bigrational(const bigint & n, const bigint & d);
  bigrational(const bigrational & a);
  ~bigrational();

#ifndef HEADBANGER

  /**
   ** inline member functions
   **/

  int sign() const;
  bool is_positive() const;
  bool is_negative() const;
  bool is_zero() const;
  bool is_gt_zero() const;
  bool is_ge_zero() const;
  bool is_lt_zero() const;
  bool is_le_zero() const;
  bool is_one() const;
  bool intify(int &i) const;
  bool longify(long &i) const;
  int abs_compare(const bigrational & a) const;
  int compare(const bigrational & a) const;

  void absolute_value();
  void negate();
  void invert();

  bigint numerator() const;
  bigint denominator() const;

  void assign_zero();
  void assign_one();
  void assign(const bigint & n, const bigint & d);
  void assign(const bigrational & a);
  void multiply_by_2();
  void divide_by_2();

#endif

  /**
   ** type checking
   **/

friend bool is_bigint(const bigrational & a);

  /**
   ** assignments
   **/

  int operator = (int i);
  long operator = (long l);
  unsigned long operator = (unsigned long ul);
  double operator = (double d);
  bigint operator = (const bigint & a);
  bigrational & operator = (const bigrational & a);

  /**
   ** comparisons
   **/

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

  /**
   ** operator overloading
   **/

friend bigrational operator - (const bigrational & a);
friend bigrational operator + (const bigrational & a, const bigrational & b);
friend bigrational operator - (const bigrational & a, const bigrational & b);
friend bigrational operator *(const bigrational & a, const bigrational & b);
friend bigrational operator / (const bigrational & a, const bigrational & b);
friend bigrational operator << (const bigrational & a, unsigned long ui);
friend bigrational operator >> (const bigrational & a, unsigned long ui);

  bigrational & operator += (const bigrational & a);
  bigrational & operator -= (const bigrational & a);
  bigrational & operator *= (const bigrational & a);
  bigrational & operator /= (const bigrational & a);
  bigrational & operator <<= (unsigned long ui);
  bigrational & operator >>= (unsigned long ui);

  bigrational & operator++ ();
  bigrational & operator-- ();
  int operator ! ();

#ifndef HEADBANGER

  /**
   ** Procedural versions
   **/

friend void invert(bigrational & c, const bigrational & a);
friend void negate(bigrational & a, const bigrational & b);
friend void add(bigrational & c, const bigrational & a, const bigrational & b);
friend void subtract(bigrational & c, const bigrational & a, const bigrational & b);
friend void multiply(bigrational & c, const bigrational & a, const bigrational & b);
friend void divide(bigrational & c, const bigrational & a, const bigrational & b);
friend void shift_left(bigrational & c, const bigrational & a, long ui);
friend void shift_right(bigrational & c, const bigrational & a,long ui);
friend void power(bigrational & c, const bigrational & a, const bigint & b);
friend void power(bigrational & c, const bigrational & a, long i);
friend void inc(bigrational & c);
friend void dec(bigrational & c);

friend void add(bigrational & c, const bigrational & a, long i);
friend void subtract(bigrational & c, const bigrational & a, long i);
friend void multiply(bigrational & c, const bigrational & a, long i);
friend void divide(bigrational & c, const bigrational & a, long i);

friend void add(bigrational & c, long i, const bigrational & a);
friend void subtract(bigrational & c, long i, const bigrational & a);
friend void multiply(bigrational & c, long i, const bigrational & a);
friend void divide(bigrational & c, long i, const bigrational & a);

#endif

  /**
   ** functions
   **/

friend bigrational abs(const bigrational & a);
friend bigrational inverse(const bigrational & a);

friend bigint numerator(const bigrational & a);
friend bigint denominator(const bigrational & a);
friend bigint round(const bigrational & a);
friend bigint floor(const bigrational & a);
friend bigint ceiling(const bigrational & a);
friend bigint truncate(const bigrational & a);

friend double dbl(const bigrational & a);

friend void square(bigrational & a, const bigrational & b);
friend void swap(bigrational & a, bigrational & b);

  /**
   ** input / output
   **/

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

friend int string_to_bigrational(char *s, char *t, bigrational & a);
friend int bigrational_to_string(const bigrational & a, char *s, char *t);

  /**
   ** using fread/fwrite
   **/

  void read_from_file(FILE * fp);
  void write_to_file(FILE * fp);

  /**
   ** using fscanf/fprintf
   **/

  void scan_from_file(FILE * fp);
  void print_to_file(FILE * fp);

};

#endif






