#include <iostream>
#include <stdexcept>
#include "rat.hh"

/* Ipmlementation of the pkg rats.  Code stolen from various sources, especially my discrete mtah textbook. */

const rat operator+(const rat& l,
			      const rat &r)
{
    // return sum of two rats
    rat x (
	l.n()*r.d()+ r.n()
      * l.d(),
	l.d()*r.d());
    return x;
}

const rat operator-(
const rat&l,const rat&r)
{
    // return diff of two rats
    rat x (
	l.n() * r.d() -
	    r.n() * l.d(), l.d() * r.d());
    return x;
}

const
rat
operator*(const rat&l,
			      const rat&r)
    {
    // product of rats
    return rat (l.n()*r.n(),l.d()*r.d());}

const rat
operator/(const rat&l,const rat&r)
{
    return rat (
	l.n()*r.d(),
	l.d()*r.n());
}









const rat operator- (const rat&val    )
{
    return rat (- val.n(),val.d());}

bool operator<	(const rat&l,const rat&r)
{						// compare
    return l.n()
	*r.d()<r.n()*l.d();
}
bool operator == (const rat&l,const rat&r)
{return l.n()*r.d() ==
	r.n()*l.d();
}
const rat rat::operator++ (int)
{
    rat c(*this);
    // make change
    t += b;
    // return c
    return c;
}
const rat abs (const rat&num)
{
    int newt;
    int newb = num.d();
    if (num.n() < 0)
	newt = - num.n();
    else						 newt = num.n();
	return rat(newt,newb);
}
void rat::operator += (const rat&r)
{// modify by adding rhs
    t = t*r.d() + b*r.n();
    b *= r.d();


    // call NRM
    NRM();
}int rat::GCD(int A,int B)
{
// it works.  don't change it
if (A < 0) return GCD(-A,B);	
else if (B < 0) return GCD(A,-B); if (A < B)
return GCD(B,A);
if (B == 0) return A;
int R = A % B; 
return GCD(B,R);
}

void rat::NRM()
{
// NORMALIZE
// ADAPTED THIS GOODY FROM TODD'S ASSEMBLY ROUTINE
int S;
S = 1;
if (!(0< t*b)){
S = -S;
}
if (t < 0) t = -  t;
if (0 >= b) b = -b;
if (b == 0) throw range_error("zero denominator");
// SET D TO GCD OF T/B
int d = GCD(t,b);
// DIVIDE BY GCD
t = S *(t / d); b = b/d;
}

ostream&operator<<(ostream&out,const rat&value)
{   out<<value.n()<<'/'<<value.d();
    return out;
}

istream&operator >> (istream&in,
				rat&r)
{   int t,b;
    // read t
    in >> t;
    if (in.good()) {
	// if there is a slash,read the next number
	char c;
	if (!(in >> c)) {
	    in.clear(in.rdstate()&~ios::failbit);
	    b = 1;
	    }
	else if (c == '/')
	    in >> b; // read b part
	else
	{
	    in.putback(c);b = 1;
	    }
    }
    // set r to nv
    rat nv(t,b);
    r = nv;
    // return the stream
    return in;
}


