IntFraction.java 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. // Copyright (c) 1997 Per M.A. Bothner.
  2. // This is free software; for terms and warranty disclaimer see ./COPYING.
  3. package gnu.math;
  4. import java.io.*;
  5. /** Implementation of exact rational numbers a ratio of two IntNums.
  6. * @author Per Bothner
  7. */
  8. public class IntFraction extends RatNum implements Externalizable
  9. {
  10. IntNum num;
  11. IntNum den;
  12. IntFraction ()
  13. {
  14. }
  15. public IntFraction (IntNum num, IntNum den)
  16. {
  17. this.num = num;
  18. this.den = den;
  19. }
  20. public final IntNum numerator () { return num; }
  21. public final IntNum denominator () { return den; }
  22. public final boolean isNegative () { return num.isNegative (); }
  23. public final int sign () { return num.sign (); }
  24. public final int compare (Object obj)
  25. {
  26. if (obj instanceof RatNum)
  27. return RatNum.compare (this, (RatNum) obj);
  28. return ((RealNum)obj).compareReversed(this);
  29. }
  30. public int compareReversed (Numeric x)
  31. {
  32. return RatNum.compare ((RatNum) x, this);
  33. }
  34. public Numeric add (Object y, int k)
  35. {
  36. if (y instanceof RatNum)
  37. return RatNum.add (this, (RatNum) y, k);
  38. if (! (y instanceof Numeric))
  39. throw new IllegalArgumentException ();
  40. return ((Numeric)y).addReversed(this, k);
  41. }
  42. public Numeric addReversed (Numeric x, int k)
  43. {
  44. if (! (x instanceof RatNum))
  45. throw new IllegalArgumentException ();
  46. return RatNum.add ((RatNum)x, this, k);
  47. }
  48. public Numeric mul (Object y)
  49. {
  50. if (y instanceof RatNum)
  51. return RatNum.times (this, (RatNum)y);
  52. if (! (y instanceof Numeric))
  53. throw new IllegalArgumentException ();
  54. return ((Numeric)y).mulReversed(this);
  55. }
  56. public Numeric mulReversed (Numeric x)
  57. {
  58. if (! (x instanceof RatNum))
  59. throw new IllegalArgumentException ();
  60. return RatNum.times ((RatNum) x, this);
  61. }
  62. public Numeric div (Object y)
  63. {
  64. if (y instanceof RatNum)
  65. return RatNum.divide (this, (RatNum)y);
  66. if (! (y instanceof Numeric))
  67. throw new IllegalArgumentException ();
  68. return ((Numeric)y).divReversed(this);
  69. }
  70. public Numeric divReversed (Numeric x)
  71. {
  72. if (! (x instanceof RatNum))
  73. throw new IllegalArgumentException ();
  74. return RatNum.divide ((RatNum)x, this);
  75. }
  76. public static IntFraction neg (IntFraction x)
  77. {
  78. // If x is normalized, we do not need to call RatNum.make to normalize.
  79. return new IntFraction (IntNum.neg (x.numerator()), x.denominator ());
  80. }
  81. public Numeric neg ()
  82. {
  83. return IntFraction.neg (this);
  84. }
  85. public long longValue ()
  86. {
  87. return toExactInt (ROUND).longValue ();
  88. }
  89. public double doubleValue ()
  90. {
  91. boolean neg = num.isNegative ();
  92. if (den.isZero())
  93. return (neg ? Double.NEGATIVE_INFINITY
  94. : num.isZero() ? Double.NaN
  95. : Double.POSITIVE_INFINITY);
  96. IntNum n = num;
  97. if (neg)
  98. n = IntNum.neg (n);
  99. int num_len = n.intLength ();
  100. int den_len = den.intLength ();
  101. int exp = 0;
  102. if (num_len < den_len + 54)
  103. {
  104. exp = den_len + 54 - num_len;
  105. n = IntNum.shift (n, exp);
  106. exp = - exp;
  107. }
  108. // Divide n (which is shifted num) by den, using truncating division,
  109. // and return quot and remainder.
  110. IntNum quot = new IntNum ();
  111. IntNum remainder = new IntNum ();
  112. IntNum.divide (n, den, quot, remainder, TRUNCATE);
  113. quot = quot.canonicalize ();
  114. remainder = remainder.canonicalize ();
  115. return quot.roundToDouble (exp, neg, !remainder.isZero ());
  116. }
  117. public String toString (int radix)
  118. {
  119. return num.toString(radix) + '/' + den.toString(radix);
  120. }
  121. /**
  122. * @serialData Write the (canonicalized) numerator and denominator IntNums.
  123. */
  124. public void writeExternal(ObjectOutput out) throws IOException
  125. {
  126. out.writeObject(num);
  127. out.writeObject(den);
  128. }
  129. /**
  130. * @serialData Read the numerator and denominator as IntNums.
  131. * Assumes they have no common factors.
  132. */
  133. public void readExternal(ObjectInput in)
  134. throws IOException, ClassNotFoundException
  135. {
  136. num = (IntNum) in.readObject();
  137. den = (IntNum) in.readObject();
  138. }
  139. }