anchor.diff:  open System.Globalization
   
   
  -[<AutoOpen>]
  -module private BigRationalLargeImpl =
  -    let ZeroI = BigInteger (0)
  -    let OneI = BigInteger (1)
  -    let bigint (x : int) = BigInteger (x)
  -    let ToDoubleI (x : BigInteger) = float x
  -    let ToInt32I (x : BigInteger) = int32 x
  -
  -
  -[<CustomEquality; CustomComparison>]
  -type BigRationalLarge =
  -    // invariants: (p,q) in lowest form, q >= 0
  -    | Q of BigInteger * BigInteger
  -
  -    member x.IsNegative =
  -        let (Q (ap, _)) = x
  -        sign ap < 0
  -
  -    member x.IsPositive =
  -        let (Q (ap, _)) = x
  -        sign ap > 0
  -
  -    member x.Numerator =
  -        let (Q (p, _)) = x in p
  -
  -    member x.Denominator =
  -        let (Q (_, q)) = x in q
  -
  -    member x.Sign =
  -        let (Q (p,_) ) = x
  +// invariants: (p,q) in lowest form, q >= 0
  +[<Sealed>]
  +type BigRationalLarge (p : BigInteger, q : BigInteger) =
  +    //
  +    member __.IsNegative =
  +        sign p < 0
  +
  +    //
  +    member __.IsPositive =
  +        sign p > 0
  +
  +    //
  +    member __.Numerator = p
  +
  +    //
  +    member __.Denominator = q
  +
  +    //
  +    member __.Sign =
           sign p
   
  -    override this.GetHashCode () =
  -        BigRationalLarge.Hash this
  -
  -    override this.ToString () =
  -        let (Q (p, q)) = this
  +    override __.GetHashCode () =
  +        // This hash code must be identical to the hash for BigInteger when the numbers coincide.
  +        if q.IsOne then p.GetHashCode ()
  +        else (p.GetHashCode () <<< 3) + q.GetHashCode ()
  +
  +    override __.ToString () =
           if q.IsOne then
  -            p.ToString()
  +            p.ToString ()
           else
  -            p.ToString() + "/" + q.ToString()
  -
  -    static member Hash (Q (ap, aq)) =
  -        // This hash code must be identical to the hash for BigInteger when the numbers coincide.
  -        if aq.IsOne then ap.GetHashCode ()
  -        else (ap.GetHashCode () <<< 3) + aq.GetHashCode ()
  -
  -    static member Equals(Q (ap, aq), Q (bp, bq)) =
  +            p.ToString () + "/" + q.ToString ()
  +
  +    //
  +    static member Equals (x : BigRationalLarge, y : BigRationalLarge) =
           // normal form, so structural equality
  -        BigInteger.(=) (ap, bp) && BigInteger.(=) (aq, bq)
  -
  -    static member LessThan (Q (ap, aq), Q (bp, bq)) =
  -        BigInteger.(<) (ap * bq, bp * aq)
  -
  -    // TODO: performance improvement possible here
  -    static member Compare (p, q) =
  -        if BigRationalLarge.LessThan (p, q) then -1
  -        elif BigRationalLarge.LessThan (q, p)then 1
  -        else 0
  -
  -    static member ToDouble (Q (p, q)) =
  -        ToDoubleI p / ToDoubleI q
  -
  +        x.Numerator = y.Numerator && x.Denominator = y.Denominator
  +
  +    //
  +    static member Compare (x : BigRationalLarge, y : BigRationalLarge) =
  +        compare (x.Numerator * y.Denominator) (y.Numerator * x.Denominator)
  +
  +    //
  +    static member ToDouble (num : BigRationalLarge) =
  +        float num.Numerator / float num.Denominator
  +
  +    //
       static member Normalize (p : BigInteger, q : BigInteger) =
           if q.IsZero then
               (* throw for any x/0 *)
               raise <| System.DivideByZeroException ()
           elif q.IsOne then
  -            Q (p, q)
  +            BigRationalLarge (p, q)
           else
               let k = BigInteger.GreatestCommonDivisor (p, q)
               let p = p / k
               let q = q / k
               if sign q < 0 then
  -                Q (-p, -q)
  -            else Q (p, q)
  -
  -    static member Rational (p : int, q : int) =
  +                BigRationalLarge (-p, -q)
  +            else
  +                BigRationalLarge (p, q)
  +
  +    //
  +    static member Create (p : int, q : int) =
           BigRationalLarge.Normalize (bigint p, bigint q)
   
  -    // TODO : Rename to Rational? It doesn't seem like we need to force the overload resolution here with a separate name...
  -    static member RationalZ (p, q) =
  +    //
  +    static member Create (p, q) =
           BigRationalLarge.Normalize (p, q)
   
  +    /// Return the given rational number
  +    static member (~+) (n1 : BigRationalLarge) = n1
  +
       /// Return the negation of a rational number
  -    static member (~-) (Q (bp, bq)) =
  +    static member (~-) (num : BigRationalLarge) =
           // still coprime, bq >= 0
  -        Q(-bp, bq)
  +        BigRationalLarge (-num.Numerator, num.Denominator)
       
       /// Return the sum of two rational numbers
  -    static member (+) (Q (ap, aq), Q (bp, bq)) =
  -        BigRationalLarge.Normalize ((ap * bq) + (bp * aq), aq * bq)
  +    static member (+) (x : BigRationalLarge, y : BigRationalLarge) =
  +        BigRationalLarge.Normalize ((x.Numerator * y.Denominator) + (y.Numerator * x.Denominator), x.Denominator * y.Denominator)
       
       /// Return the difference of two rational numbers
  -    static member (-) (Q (ap, aq), Q (bp, bq)) =
  -        BigRationalLarge.Normalize ((ap * bq) - (bp * aq), aq * bq)
  +    static member (-) (x : BigRationalLarge, y : BigRationalLarge) =
  +        BigRationalLarge.Normalize ((x.Numerator * y.Denominator) - (y.Numerator * x.Denominator), x.Denominator * y.Denominator)
       
       /// Return the product of two rational numbers
  -    static member (*) (Q (ap, aq), Q (bp, bq)) =
  -        BigRationalLarge.Normalize (ap * bp, aq * bq)
  +    static member (*) (x : BigRationalLarge, y : BigRationalLarge) =
  +        BigRationalLarge.Normalize (x.Numerator * y.Numerator, x.Denominator * y.Denominator)
       
       /// Return the ratio of two rational numbers
  -    static member (/) (Q (ap, aq), Q (bp, bq)) =
  -        BigRationalLarge.Normalize (ap * bq, aq * bp)
  -
  -    /// Return the given rational number
  -    static member ( ~+ ) (n1 : BigRationalLarge) = n1
  +    static member (/) (x : BigRationalLarge, y : BigRationalLarge) =
  +        BigRationalLarge.Normalize (x.Numerator * y.Denominator, x.Denominator * y.Numerator)
  +
  +    //
  +    static member Reciprocal (num : BigRationalLarge) =
  +        BigRationalLarge.Normalize (num.Denominator, num.Numerator)
  +
  +    //
  +    static member PowN (num : BigRationalLarge, n : int) =
  +        // p,q powers still coprime
  +        BigRationalLarge (BigInteger.Pow (num.Numerator, n), BigInteger.Pow (num.Denominator, n))
  +
  +    //
  +    static member FromBigInteger z =
  +        BigRationalLarge.Create (z, BigInteger.One)
  +
  +    //
  +    static member FromInt32 n =
  +        BigRationalLarge.Create (n, 1)
  +
  +    /// Returns the integer part of a rational number.
  +    static member ToBigInteger (num : BigRationalLarge) =
  +        // have p = d.q + r, |r| < |q|
  +        let d, r = BigInteger.DivRem (num.Numerator, num.Denominator)
  +
  +        if r < BigInteger.Zero then
  +            // p = (d-1).q + (r+q)
  +            d - BigInteger.One
  +        else
  +            // p = d.q + r
  +            d
   
       //
       static member Parse (str : string) =
           let len = str.Length
  -        if len=0 then invalidArg "str" "empty string";
  +        if len = 0 then
  +            invalidArg "str" "empty string"
  +
           let j = str.IndexOf '/'
           if j >= 0 then
  -            let p = BigInteger.Parse (str.Substring(0,j))
  -            let q = BigInteger.Parse (str.Substring(j+1,len-j-1))
  -            BigRationalLarge.RationalZ (p,q)
  +            let p = BigInteger.Parse (str.Substring (0, j))
  +            let q = BigInteger.Parse (str.Substring (j + 1, len - j - 1))
  +            BigRationalLarge.Create (p, q)
           else
               let p = BigInteger.Parse str
  -            BigRationalLarge.RationalZ (p,OneI)
  -
  -    override this.Equals(that : obj) =
  +            BigRationalLarge.Create (p, BigInteger.One)
  +
  +    override this.Equals (that : obj) =
           match that with
           | :? BigRationalLarge as that ->
  -            BigRationalLarge.Equals(this,that)
  +            BigRationalLarge.Equals (this, that)
           | _ -> false
   
       interface System.IComparable with
  
positive.code:         | Q q, Q qq ->
              Q (q - qq)
          | Z z, Q qq ->
              Q (BigRationalLarge.of_bigint z - qq)
          | Q q, Z zz ->
              Q (q  - BigRationalLarge.of_bigint zz)
  
      /// Return the product of two rational numbers
      static member ( * ) (n1, n2) =
          match n1,n2 with
          | Z z, Z zz ->
              Z (z * zz)
          | Q q, Q qq ->
              Q (q * qq)
          | Z z, Q qq ->
              Q (BigRationalLarge.of_bigint z * qq)
          | Q q, Z zz ->
              Q (q  * BigRationalLarge.of_bigint zz)
  
      /// Return the ratio of two rational numbers
      static member ( / ) (n1, n2) =
          match n1, n2 with
          | Z z, Z zz ->
              Q (BigRationalLarge.RationalZ(z,zz))
          | Q q, Q qq ->
              Q (q / qq)
          | Z z, Q qq ->
              Q (BigRationalLarge.of_bigint z / qq)
          | Q q, Z zz ->
              Q (q  / BigRationalLarge.of_bigint zz)
  
      /// Return the negation of a rational number
      static member ( ~- ) n =
  
negative.code:     /// Return the denominator of the normalized rational number
      member this.Denominator =
          match this with
          | Z _ -> BigInteger.One
          | Q q -> q.Denominator
  
      /// Return a boolean indicating if this rational number is strictly negative
  