001: // Copyright (c) 1997 Per M.A. Bothner.
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.math;
005:
006: import java.io.*;
007:
008: /** Implementation of exact rational numbers a ratio of two IntNums.
009: * @author Per Bothner
010: */
011:
012: public class IntFraction extends RatNum implements Externalizable {
013: IntNum num;
014: IntNum den;
015:
016: IntFraction() {
017: }
018:
019: public IntFraction(IntNum num, IntNum den) {
020: this .num = num;
021: this .den = den;
022: }
023:
024: public final IntNum numerator() {
025: return num;
026: }
027:
028: public final IntNum denominator() {
029: return den;
030: }
031:
032: public final boolean isNegative() {
033: return num.isNegative();
034: }
035:
036: public final int sign() {
037: return num.sign();
038: }
039:
040: public final int compare(Object obj) {
041: if (obj instanceof RatNum)
042: return RatNum.compare(this , (RatNum) obj);
043: return ((RealNum) obj).compareReversed(this );
044: }
045:
046: public int compareReversed(Numeric x) {
047: return RatNum.compare((RatNum) x, this );
048: }
049:
050: public Numeric add(Object y, int k) {
051: if (y instanceof RatNum)
052: return RatNum.add(this , (RatNum) y, k);
053: if (!(y instanceof Numeric))
054: throw new IllegalArgumentException();
055: return ((Numeric) y).addReversed(this , k);
056: }
057:
058: public Numeric addReversed(Numeric x, int k) {
059: if (!(x instanceof RatNum))
060: throw new IllegalArgumentException();
061: return RatNum.add((RatNum) x, this , k);
062: }
063:
064: public Numeric mul(Object y) {
065: if (y instanceof RatNum)
066: return RatNum.times(this , (RatNum) y);
067: if (!(y instanceof Numeric))
068: throw new IllegalArgumentException();
069: return ((Numeric) y).mulReversed(this );
070: }
071:
072: public Numeric mulReversed(Numeric x) {
073: if (!(x instanceof RatNum))
074: throw new IllegalArgumentException();
075: return RatNum.times((RatNum) x, this );
076: }
077:
078: public Numeric div(Object y) {
079: if (y instanceof RatNum)
080: return RatNum.divide(this , (RatNum) y);
081: if (!(y instanceof Numeric))
082: throw new IllegalArgumentException();
083: return ((Numeric) y).divReversed(this );
084: }
085:
086: public Numeric divReversed(Numeric x) {
087: if (!(x instanceof RatNum))
088: throw new IllegalArgumentException();
089: return RatNum.divide((RatNum) x, this );
090: }
091:
092: public static IntFraction neg(IntFraction x) {
093: // If x is normalized, we do not need to call RatNum.make to normalize.
094: return new IntFraction(IntNum.neg(x.numerator()), x
095: .denominator());
096: }
097:
098: public Numeric neg() {
099: return IntFraction.neg(this );
100: }
101:
102: public long longValue() {
103: return toExactInt(ROUND).longValue();
104: }
105:
106: public double doubleValue() {
107: boolean neg = num.isNegative();
108: if (den.isZero())
109: return (neg ? Double.NEGATIVE_INFINITY
110: : num.isZero() ? Double.NaN
111: : Double.POSITIVE_INFINITY);
112: IntNum n = num;
113: if (neg)
114: n = IntNum.neg(n);
115: int num_len = n.intLength();
116: int den_len = den.intLength();
117: int exp = 0;
118: if (num_len < den_len + 54) {
119: exp = den_len + 54 - num_len;
120: n = IntNum.shift(n, exp);
121: exp = -exp;
122: }
123:
124: // Divide n (which is shifted num) by den, using truncating division,
125: // and return quot and remainder.
126: IntNum quot = new IntNum();
127: IntNum remainder = new IntNum();
128: IntNum.divide(n, den, quot, remainder, TRUNCATE);
129: quot = quot.canonicalize();
130: remainder = remainder.canonicalize();
131:
132: return quot.roundToDouble(exp, neg, !remainder.isZero());
133: }
134:
135: public String toString(int radix) {
136: return num.toString(radix) + '/' + den.toString(radix);
137: }
138:
139: /**
140: * @serialData Write the (canonicalized) numerator and denominator IntNums.
141: */
142: public void writeExternal(ObjectOutput out) throws IOException {
143: out.writeObject(num);
144: out.writeObject(den);
145: }
146:
147: /**
148: * @serialData Read the numerator and denominator as IntNums.
149: * Assumes they have no common factors.
150: */
151: public void readExternal(ObjectInput in) throws IOException,
152: ClassNotFoundException {
153: num = (IntNum) in.readObject();
154: den = (IntNum) in.readObject();
155: }
156: }
|