#include <iostream.h>
#include <math.h>
#include <stdlib.h>
#include <conio.h>

#ifndef TRUE
#define TRUE 1
#endif

#ifndef FALSE
#define FALSE 0
#endif

class gcd_cls {   // base class
         unsigned long u,v,r;
public:
         unsigned long gcd (unsigned long a,unsigned long b);

};

class fraction : private gcd_cls { //derived class with private access
                                   //to gcd_cls function gcd()
         long n,np;
public:
         fraction operator+(fraction d);  //overload +
         fraction operator-(fraction d);  //overload -
         fraction operator*(fraction d);  //overload *
         fraction operator/(fraction d);  //overload /
         fraction operator=(fraction d);  //overload =
         char operator<(fraction &d);  //overload less than
         char operator>(fraction &d); //overload greater than
         char operator==(fraction &d); //overload ==
         char operator!=(fraction &d); //overload !=
         void swap (fraction &a,fraction &b);
         friend ostream &operator<<(ostream &stream, fraction &x);
         friend istream &operator>>(istream &stream, fraction &x);
};

unsigned long gcd_cls :: gcd (unsigned long a,unsigned long b)
{
         ldiv_t r;   //use special div functions for longs
                     //requires correct type structure

         u=labs(a);  //make sure argument is a positive number
         v=labs(b);  //ditto second argument
         if (v==0)
                 return u;
         while (v!=0) {
                 r=ldiv(u,v);
                 u=v;
                 v=r.rem;
         }
         return u;
}

ostream &operator<<(ostream &stream, fraction &x)
{
        if (x.n==0 && x.np==1) // Trap 0/1 as zero
                stream << "Zero" ;
        else {
                stream << x.n;
                stream << '/';
                stream << x.np;
        }
        return stream;
}

istream &operator>>(istream &stream, fraction &x)
{
        int col,col2,row;

        col=wherex();  //get col current location
        row=wherey();  //get current row

        gotoxy (col+5,row); //go foward 5 spaces, print slash
        cout << '/';
        col2=wherex();
        gotoxy (col,row);  //go back
        stream >> x.n;     // get numerator
        gotoxy (col2,row-1); // go right of slash
        stream >>x.np;          //get denominator
        return stream;
}

fraction fraction :: operator=(fraction x) //overload =
{
         n=x.n;
         np=x.np;
         return (*this);
}

char fraction :: operator<(fraction &x) // overload less than
{
        fraction temp;

        temp=*this-x;
        if (temp.n<0)
                return TRUE;
        else
                return FALSE;

}

char fraction :: operator>(fraction &x) //overload greater than
{
        if ( !(*this<x || *this==x) )
                return TRUE;
        else
                return FALSE;
}



char fraction :: operator!=(fraction &x) //overload !=
{
        if ( (n!=x.n) || (np!=x.np))
                return TRUE;
        else
                return FALSE;
}

char fraction :: operator==(fraction &x) //overload ==
{
        if( (n==x.n) && (np==x.np))
                return TRUE;
        else
                return FALSE;
}

fraction fraction :: operator+(fraction x) // overload +
{
         fraction w;
         long d1,t,d2;

         d1=gcd(np,x.np);
         if (d1==1){
                 w.n=(n*x.np)+(np*x.n);
                 w.np=(np*x.np);
                 return w;
         }
         if (d1>1) {
                 t=n*(x.np/d1)+x.n*(np/d1);
                 d2=gcd(t,d1);
                 w.n=t/d2;
                 w.np=(np/d1)*(x.np/d2);
                 return w;
         }
}

fraction fraction :: operator-(fraction x) // over load -
{
         fraction w,tmpa,tmpb;
         long d1,t,d2;


         tmpa=*this;
         tmpb=x;

         d1=gcd(tmpa.np,tmpb.np);
         if (d1==1){
                 w.n=(tmpa.n*tmpb.np)-(tmpa.np*tmpb.n);
                 w.np=(tmpa.np*tmpb.np);
                 return w;
         }
         if (d1>1) {
                 t=n*(tmpb.np/d1)-tmpb.n*(tmpa.np/d1);
                 d2=gcd(t,d1);
                 w.n=t/d2;
                 w.np=(tmpa.np/d1)*(tmpb.np/d2);
                 return w;
         }
}


fraction fraction :: operator*(fraction x) //overload *
{
         fraction temp;
         long d;
         d=gcd(n*x.n,np*x.np);
         temp.n=n*x.n / d;
         temp.np=np*x.np/d;
         return temp;
}

fraction fraction :: operator/(fraction x) //overload /
{
         fraction temp,tmp2;
         // first we will invert
         temp.n=x.np;
         temp.np=x.n;
         //now we will multiply
         tmp2=temp* *this;
         return tmp2;
}



void fraction :: swap (fraction &a, fraction &b)
{
         fraction temp;
                 temp=a;
                 a=b;
                 b=temp;
}

void main(void)
{
         fraction a,b,c;
         char ch;

         cout << "\nEnter fraction a: ";
         cin >> a;
         cout << "\nEnter fraction b: ";
         cin >> b;
         c=a+b;
         cout << "\nAdd " << c;
         c=a-b;
         cout << "\nsub " << c;
         c=a*b;
         cout << "\nMult " << c;
         c=a/b;
         cout << "\nDiv " << c;
         if (a<b) cout << "\n" << a << " is less than " << b;
         if (b<a) cout << "\n" << b << " is less than " << a;
         if (a>b) cout << "\n" << a << " is greater than " << b;
         if (b>a) cout << "\n" << b << " is greater than " << a;
         if (b==a) cout << "\nFractions are equal";
         if (a!=b) cout << "\nFractions are not equal";

}
