// Implementation of a rational number class
#include <iostream.h>
#include <assert.h>
#include "rational3.h"

// Define the + operation
Rational operator+ (Rational r1, Rational r2)
{ Rational r;
  r.numerator = (r1.numerator * r2.denominator) +
                (r1.denominator * r2.numerator);
  r.denominator = r1.denominator * r2.denominator;

  /* reduce the fraction stored by eliminating common factors */
  int common_fac = r.gcd (r.numerator, r.denominator);
  r.numerator = r.numerator / common_fac;
  r.denominator = r.denominator / common_fac;
  return r;
}

/* Overload familiar I/O operations */
istream& operator>> (istream& istr, Rational& r)
{ /* only numbers of the form num/denom, with denom!=0 are legal */
  char divSign;      /* use divSign to read the / symbol within the input */
  istr >> r.numerator >> divSign >> r.denominator;
  assert (divSign == '/');
  assert (r.denominator != 0);

  /* reduce the fraction stored by eliminating common factors */
  int common_fac = r.gcd (r.numerator, r.denominator);
  r.numerator = r.numerator / common_fac;
  r.denominator = r.denominator / common_fac;

  return istr;            /* the revised input stream is returned */
}

ostream& operator<< (ostream& ostr, Rational r)
{ /* first use the << operation for integers and strings */
  ostr << r.numerator << " / " << r.denominator;
  return ostr;           /* return the revised output stream */
}

// Constructor
Rational::Rational (int num, int denom)
{ /* an error results if denom == 0 */
  assert (denom != 0);

  /* reduce the fraction stored by eliminating common factors */
  int common_fac = gcd (num, denom);
  numerator = num / common_fac;
  denominator = denom / common_fac;
}

// Define decimal division
double Rational::eval (void)
{ return ((double) numerator / (double) denominator);
}

// Define the greatest common divisor function
int Rational::gcd (int a, int b)
/*  Pre-condition:  b != 0;
    Since ince b always == denom when called in this package, 
    this pre-condition is always met within this class */
{  if (a == 0)  
      return 1;
   /* if the numbers are nonzero, the classical Euclidean algorithm is used 
   to compute the gcd  -- see a mathematics text for more information */
   int x = a;
   int y = b;
   int r = y % x;
   while (r != 0)
     { y = x;
       x = r;
       r = y % x;
     }
   return x;
}
