package rational;

// Programmer:  Rance Cleaveland
// Date:  12 Oct. 2006

public class Rational {
	
	private int num = 0;  	// num is numerator; may be any int
	private int denom = 1;  // denom is denomiator; must be positive int
		
	// General initializer
	
	private void assignFields (int n, int d) {
		num = n;
		denom = d;
	}
	
	// makeInt is used to turn an integer into a Rational
	
	private void makeInt (int n) {
		assignFields (n, 1);
	}

	// Constructors
	
	Rational () {
		makeInt (0);
	}
	
	Rational (int n){
		makeInt (n);
	}
	
	// Makes rational number equivalent to result of dividing n by d.
	// So num, denom are in lowest terms, and d is > 0.
	
	Rational (int n, int d){
		
		// Handle 0 values in n, d.  Also make d positive.
		if (n == 0 && d != 0){
			makeInt (0);
		}
		else {
			if (d == 0) {
				System.exit(1);
			}
			else if (d < 0) { // make d positive
				d = -d;
				n = -n;
			}
		
			// Factor out gcd of |n|, d (recall n may be negative).
		
			int gcd = GCD.gcd (Math.abs(n), d);
			assignFields (n / gcd, d / gcd);
		}
	}
	
	// Copy constructor
	
	Rational (Rational r){
		assignFields (r.getNum(), r.getDenom());
	}
	
	// Getters
	
	public int getNum () {
		return num;
	}
	
	public int getDenom () {
		return denom;
	}
	
	// toString
	public String toString () {
		return (getNum() + " / " + getDenom());
	}
	
	// Arithmetic operations
	
	public static Rational negate (Rational r){
		Rational returnVal = new Rational (r);
		returnVal.num = -returnVal.getNum();
		return returnVal;
	}
	
	public static Rational invert (Rational r){
		return (new Rational (r.getDenom(), r.getNum()));
	}
	
	public static Rational add (Rational r1, Rational r2){
		int n = (r1.getNum() * r2.getDenom()) + (r2.getNum() * r1.getDenom());
		int d = r1.getDenom() * r2.getDenom();
		return (new Rational (n, d));
	}
	
	public static Rational subtract (Rational r1, Rational r2){
		return (add (r1, negate(r2)));
	}
	
	public static Rational multiply (Rational r1, Rational r2){
		int n = r1.getNum() * r2.getNum();
		int d = r1.getDenom() * r2.getDenom();
		return (new Rational (n, d));
	}
	
	public static Rational divide (Rational r1, Rational r2){
		return (multiply (r1, invert(r2)));
	}
	
	// Comparisons
	
	public boolean equals (Rational r){
		return (this.getNum() == r.getNum() && this.getDenom() == r.getDenom());
	}
	
	public int compareTo (Rational r){
		int me = this.getNum() * r.getDenom();
		int you = r.getNum() * this.getDenom();
		if (me < you)
			return -1;
		else if (me == you)
			return 0;
		else
			return 1;
			
	}
}
