class Szam // Hungarian for number { long numerator, denominator; static Szam ZERO = new Szam(0,1); static Szam ONE = new Szam(1,1); static Szam TWO = new Szam(2,1); static CompostHeap compostHeap = new CompostHeap(ZERO.getClass(),true,2); // static ObjectPointer wrapper = new ObjectPointer(); public Szam(long A, long B) { becomesRatio(A,B); // dbgalloc(2,"Made a Szam "+this); } public Szam(Szam szamToCopy) { copy(szamToCopy); } public void becomesRatio(long A, long B) { long gcd = GCD(A,B); if (gcd != 0) { A /= gcd; B /= gcd; } if (B < 0) {A *=-1; B*=-1;} numerator = A; denominator = B; } static public Szam newSzam(Szam szamToCopy) { boolean recycled = false; Szam ans = ZERO; // wrapper.it = ans; if (!compostHeap.exists()) ans = new Szam(szamToCopy); else ans = (Szam)compostHeap.likeNew(); ans.copy(szamToCopy); return ans; } static public Szam newSzam(long A, long B) { Szam ans = newSzam(ZERO); ans.becomesRatio(A,B); return ans; } public void copy(Szam szamToCopy) { numerator = szamToCopy.numerator; denominator = szamToCopy.denominator; } public void free() { compostHeap.recycle(this); } static public void debug(int i, String s) { if (i>=2) System.out.println(s); } public void dbgalloc(int i,String s) { if (i>=4) System.out.println(" "+s); } static public long GCD(long A, long B) { long C = Math.abs(A), D = Math.abs(B), tmp; if (C>D) { tmp=C; C=D; D=tmp;} while (C != 0) { tmp = D % C; D = C; C = tmp; } return D; } // In many of the following I pull out some GCD intermediately that // Szam() ought to be able to. This is to stave off overflowing the ints // a little bit longer. // This q() thing is for quotient, to divide by these GCDs everywhere. long q(long num, long den) { if (den == 0) return 0; else return num/den; } public Szam plus(Szam other) { long gcd = GCD(denominator,other.denominator); long newNum = numerator * q(other.denominator,gcd) + q(denominator,gcd) * other.numerator; long newDen = q(denominator,gcd) * other.denominator; return newSzam(newNum, newDen); } public Szam times(Szam other) { long gcd1 = GCD(numerator,other.denominator); long gcd2 = GCD(denominator,other.numerator); long newNum = q(numerator,gcd1) * q(other.numerator,gcd2); long newDen = q(denominator,gcd2) * q(other.denominator,gcd1); return newSzam(newNum, newDen); } public Szam minus(Szam other) { long gcd = GCD(denominator,other.denominator); long newNum = numerator * q(other.denominator,gcd) - q(denominator,gcd) * other.numerator; long newDen = q(denominator,gcd) * other.denominator; return newSzam(newNum, newDen); } public double value() { return (double)numerator/(double)denominator; } public boolean lessThan(Szam other) { long gcd1 = GCD(numerator,other.numerator); long gcd2 = GCD(denominator,other.denominator); return q(numerator,gcd1) * q(other.denominator,gcd2) < q(denominator,gcd2) * q(other.numerator,gcd1); } public boolean lessThanEq(Szam other) { long gcd1 = GCD(numerator,other.numerator); long gcd2 = GCD(denominator,other.denominator); return (q(numerator,gcd1) * q(other.denominator,gcd2) <= q(denominator,gcd2) * q(other.numerator,gcd1)); } public Szam over(Szam other) { long gcd1 = GCD(numerator,other.numerator); long gcd2 = GCD(denominator,other.denominator); long newNum = q(numerator,gcd1) * q(other.denominator,gcd2); long newDen = q(denominator,gcd2) * q(other.numerator,gcd1); if (newDen < 0) { newDen *= -1; newNum *= -1; } return newSzam(newNum, newDen); } public boolean equals(Szam other) { return ((numerator == other.numerator) && (denominator == other.denominator)); } public String toString() { if (denominator == 1) return Long.toString(numerator); else return numerator +"/"+ denominator; } }