using System using System.Collections.Generic set namespace Fx7 public class Rational : IComparable [Rational] num_int : int num_big : BigInteger dem_int : int dem_big : BigInteger static zero : BigInteger = BigInteger () static one : BigInteger = BigInteger (1) static minus_one : BigInteger = BigInteger (-1) public static One : Rational = Rational (1, 1) public static Two : Rational = Rational (2, 1) public static Zero : Rational = Rational (0, 1) public static MinusOne : Rational = Rational (-1, 1) public static NegativeInfinity : Rational = Rational (-1, 0, true) public static PositiveInfinity : Rational = Rational (1, 0, true) static gcd (a : int, b : int) : int if (a == 0) b else gcd (b % a, a) this (n : int, d : int, _override : bool) num_int = n dem_int = d public this (n : int, d : int) assert (d != 0) if (n == 0) num_int = 0 dem_int = 1 else if (d < 0) dem_int = -d num_int = -n else dem_int = d num_int = n def g = gcd (Math.Abs (num_int), dem_int) num_int /= g dem_int /= g public this (n : BigInteger, d : BigInteger) assert (n : object != null && d : object != null) assert (d != zero) if (n == zero) num_big = zero dem_big = one else if (d < zero) dem_big = -d num_big = -n else dem_big = d num_big = n def g = num_big.abs ().gcd (dem_big) num_big /= g dem_big /= g public this (n : long, d : long) if (d < 0) this (-n, -d) else if (n < int.MinValue || n > int.MaxValue || d > int.MaxValue) this (BigInteger (n), BigInteger (d)) else this (n :> int, d :> int) public IsZero : bool get if (num_big : object == null) num_int == 0 else num_big == zero public IsOne : bool get if (num_big : object == null) num_int == 1 && dem_int == 1 else num_big == one && dem_int == one public IsMinusOne : bool get if (num_big : object == null) num_int == -1 && dem_int == 1 else num_big == minus_one && dem_int == one public IsInt : bool get if (num_big : object == null) dem_int == 1 else dem_big == one public StripFraction () : Rational if (num_big : object == null) Rational (num_int / dem_int, 1) else Rational (num_big / dem_big, one) public Floor () : Rational if (IsInt) this else if (IsNegative) StripFraction () - One else StripFraction () public Ceil () : Rational if (IsInt) this else if (IsNegative) StripFraction () else StripFraction () + One public Invert () : Rational assert (!IsInf) if (num_big : object == null) Rational (dem_int, num_int) else Rational (dem_big, num_big) public IsInf : bool get num_big : object == null && dem_int == 0 ToBig () : Rational assert (num_big : object == null) assert (!IsInf) Rational (BigInteger (num_int), BigInteger (dem_int)) static IsBig (a : ref Rational, b : ref Rational) : bool if (a.num_big : object != null) if (b.num_big : object != null) true else b = b.ToBig () true else if (b.num_big : object != null) a = a.ToBig () true else false public static @* (mutable a : Rational, mutable b : Rational) : Rational assert (!a.IsInf && !b.IsInf) if (a.IsOne) b else if (b.IsOne) a else if (a.IsMinusOne) -b else if (b.IsMinusOne) -a else if (IsBig (ref a, ref b)) Rational (a.num_big * b.num_big, a.dem_big * b.dem_big) else Rational ((a.num_int : long) * b.num_int, (a.dem_int : long) * b.dem_int) public static @+ (mutable a : Rational, mutable b : Rational) : Rational assert (!a.IsInf && !b.IsInf) if (a.IsZero) b else if (b.IsZero) a else if (IsBig (ref a, ref b)) Rational (a.num_big * b.dem_big + b.num_big * a.dem_big, a.dem_big * b.dem_big) else Rational ((a.num_int : long) * b.dem_int + (b.num_int : long) * a.dem_int, (a.dem_int : long) * b.dem_int) public static @/ (mutable a : Rational, mutable b : Rational) : Rational a * b.Invert () public static @- (a : Rational, b : Rational) : Rational a + -b public static @- (a : Rational) : Rational assert (!a.IsInf) if (a.IsZero) a else if (a.num_big : object == null) Rational (-a.num_int, a.dem_int) else Rational (-a.num_big, a.dem_big) public static @== (a : Rational, b : int) : bool if (b == 0) a.IsZero else if (b == 1) a.IsOne else if (b == -1) a.IsMinusOne else a == Rational (b, 1) public static @!= (a : Rational, b : int) : bool ! (a == b) public static @== (mutable a : Rational, mutable b : Rational) : bool if (a.IsInf) if (b.IsInf) a.IsNegative == b.IsNegative else false else if (b.IsInf) false else if (IsBig (ref a, ref b)) a.num_big == b.num_big && a.dem_big == b.dem_big else a.num_int == b.num_int && a.dem_int == b.dem_int public static @!= (a : Rational, b : Rational) : bool ! (a == b) public IsPositive : bool get if (num_big : object == null) num_int > 0 else num_big > zero public IsNegative : bool get if (num_big : object == null) num_int < 0 else num_big < zero public CompareTo (mutable b : Rational) : int match ((IsNegative, b.IsNegative)) | (true, false) => -1 | (false, true) => 1 | _ => mutable a = this if (IsInf) if (b.IsInf) 0 else if (IsNegative) -1 else 1 else if (b.IsInf) if (IsNegative) 1 else -1 else if (IsBig (ref a, ref b)) if (a == b) 0 else if (a.num_big * b.dem_big < b.num_big * a.dem_big) -1 else 1 else if (a == b) 0 else if ((a.num_int : long) * b.dem_int < (b.num_int : long) * a.dem_int) -1 else 1 public static @< (a : Rational, b : Rational) : bool a.CompareTo (b) < 0 public static @> (a : Rational, b : Rational) : bool a.CompareTo (b) > 0 public static @< (a : Rational, b : int) : bool if (b == 0) a.IsNegative else a.CompareTo (Rational (b, 1)) < 0 public static @> (a : Rational, b : int) : bool if (b == 0) a.IsPositive else a.CompareTo (Rational (b, 1)) > 0 public static @<= (a : Rational, b : Rational) : bool a.CompareTo (b) <= 0 public static @>= (a : Rational, b : Rational) : bool a.CompareTo (b) >= 0 public static Parse (s : string) : Rational Rational (int.Parse (s), 1) /* public CompareTo (b : object) : int | b is Rational => CompareTo (b) | _ => throw Exception ("wrong type") */ public override ToString () : string if (IsInf) if (IsNegative) "-inf" else "inf" else if (num_big : object == null) if (dem_int == 1) num_int.ToString () else $ "$num_int/$dem_int" else if (dem_big == one) num_big.ToString () else $ "$num_big/$(dem_big)B" [Nemerle.OverrideObjectEquals] \ public Equals (b : Rational) : bool this == b public override GetHashCode () : int if (num_big : object == null) num_int ^ dem_int else num_big.IntValue () ^ dem_big.IntValue ()