// A2X - C++ Course 1998
// Copyright © 1998 by Thomas Papanikolaou - All rights reserved.

// the following two lines are used to protect the header file from
// being included multiple times. The check works as follows: if the
// symbol CXX_COURSE_RATIONAL_H is not defined, define it and include
// everything in the file. If CXX_COURSE_RATIONAL_H is already defined,
// just ignore it.

#ifndef CXX_COURSE_RATIONAL_H
#define CXX_COURSE_RATIONAL_H

// include the header necessary for input/output
#include <iostream.h>

// class declaration begins here
class rational
{
  public:
   
    // constructors and destructor 
    rational ( );
    rational ( int i );
    rational ( int i , int j );
    rational ( const rational & x );
    ~rational ( );

    // accessors
    int numerator ( ) const { return n; }
    int denominator ( ) const { return d; }
    

    // overloading of the assignment operator =
    rational & operator = ( const rational & x );

    // overloading of the unary minus operator -
    friend rational operator - ( const rational & x );

    // overloadings of the binary operators +, -, *, /
    friend rational operator + ( const rational & x , const rational & y );
    friend rational operator - ( const rational & x , const rational & y );
    friend rational operator * ( const rational & x , const rational & y );
    friend rational operator / ( const rational & x , const rational & y );
      
    // overloading of the input and output operator
    friend istream & operator >> ( istream & in  ,       rational & x);
    friend ostream & operator << ( ostream & out , const rational & x);

  private:
    // the representation of a rational n / d
    int n, d;

    // internal utility for computing gcds
    static int gcd ( int a , int b ) 
      { 
         return b ? rational::gcd(b, a % b) : a; 
      }

    // error handling routine
    static void error ( char *text )
      {
        cerr << "rational error: " << text << endl;
        exit(1);
      }

    // reduce n / d such that gcd(n, d) == 1 and d > 0. If d == 0
    // return an error.
    void simplify ( )
      {
         if (d == 0)
           rational::error("zero denominator");
         int g = rational::gcd(n, d);
         n = n / g;
         d = d / g;
         if (d < 0)
           {
              n = -n;
              d = -d;
           }
      }

};
// class declaration ends here

#endif


