//
// See rationals_v1.h for documentation
//
#include <iostream.h>
#include "rationals_v1.h"		// class definition

// -------- implementation of RationalNum class --------

// ---- prototypes for "helper functions" ----

// function to compute greatest common divisor

// precondition:  m, n are positive numbers
// postcondition:  return value is the greatest common divisor of m, n
int gcd(int m, int n);


// ---- function definitions ----

// ---- constructors ----

RationalNum::RationalNum(const int n, const int d)
{
	numerator = n; denominator = d;
}

// ---- member functions ----

bool RationalNum::stream_in(istream& iStr)
{
	int n, d;
	char c;
	iStr >> n >> c >> d;
	if (iStr && (c == '/'))
	{
		numerator = n;
		denominator = d;
		return true;
	}
	else
		return false;
}

void RationalNum::stream_out(ostream& oStr)
{
	oStr << numerator << "/" << denominator;
	return;
}

void RationalNum::reduce(void)
{
	int divisor;
	if (denominator == 0)
		numerator = 1;
	else if (numerator == 0)
		denominator = 1;
	else
	{
		if (denominator < 0)
		{
			denominator *= -1;
			numerator *= -1;
		}
		divisor = gcd(abs(numerator), denominator);
		numerator /= divisor;
		denominator /= divisor;
	}
	return;
}

// ---- friend functions ----

bool equals(const RationalNum p, const RationalNum q)
{
	return (p.numerator*q.denominator) == (q.numerator*p.denominator);
}
bool lessThan(const RationalNum p, const RationalNum q)
{
	return (p.numerator*q.denominator) < (q.numerator*p.denominator);
}
bool greaterThan(const RationalNum p, const RationalNum q)
{
	return (p.numerator*q.denominator) > (q.numerator*p.denominator);
}
RationalNum add(const RationalNum p, const RationalNum q)
{
	RationalNum r = RationalNum(
		p.numerator*q.denominator + q.numerator*p.denominator,
		p.denominator*q.denominator);
	r.reduce();
	return r;
}
RationalNum subtract(const RationalNum p, const RationalNum q)
{
	RationalNum r = RationalNum(
		p.numerator*q.denominator - q.numerator*p.denominator,
		p.denominator*q.denominator);
	r.reduce();
	return r;
}
RationalNum multiply(const RationalNum p, const RationalNum q)
{
	RationalNum r = RationalNum(p.numerator*q.numerator, 
		p.denominator*q.denominator);
	r.reduce();
	return r;
}
RationalNum divide(const RationalNum p, const RationalNum q)
{
	RationalNum r = RationalNum(p.numerator*q.denominator, 
		p.denominator*q.numerator);
	r.reduce();
	return r;
}

// ---- "helper functions" ----

int gcd(int m, int n)
// use Euclid's algorithm for finding greatest common divisor
// depends on two observations:
//	if m is a multiple of n, gcd(m, n) == n
//	otherwise, can write m = nt + r, and gcd(m, n) == gcd(n, r)
{
	int r;
	// ensure that m >= n
	if (m < n)
	{
		int temp = m;
		m = n;
		n = temp;
	}
	do {
		r = m % n;
		m = n;
		n = r;
	} while (r != 0);
	return m;
}