/- Copyright (c) 2021 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Leonardo de Moura -/ namespace Lean /-! Rational numbers for implementing decision procedures. We should not confuse them with the Mathlib rational numbers. -/ structure Rat where private mk :: num : Int den : Nat := 1 deriving Inhabited, BEq, DecidableEq instance : ToString Rat where toString a := if a.den == 1 then toString a.num else s!"{a.num}/{a.den}" instance : Repr Rat where reprPrec a _ := if a.den == 1 then repr a.num else s!"({a.num} : Rat)/{a.den}" @[inline] def Rat.normalize (a : Rat) : Rat := let n := Nat.gcd a.num.natAbs a.den if n == 1 then a else { num := a.num / n, den := a.den / n } def mkRat (num : Int) (den : Nat) : Rat := if den == 0 then { num := 0 } else Rat.normalize { num, den } namespace Rat protected def isInt (a : Rat) : Bool := a.den == 1 protected def lt (a b : Rat) : Bool := if a.num < 0 && b.num >= 0 then true else if a.num == 0 then b.num > 0 else if a.num > 0 && b.num <= 0 then false else -- `a` and `b` must have the same sign a.num * b.den < b.num * a.den protected def mul (a b : Rat) : Rat := let g1 := Nat.gcd a.den b.num.natAbs let g2 := Nat.gcd a.num.natAbs b.den { num := (a.num / g2)*(b.num / g1) den := (b.den / g2)*(a.den / g1) } protected def inv (a : Rat) : Rat := if a.num < 0 then { num := - a.den, den := a.num.natAbs } else if a.num == 0 then a else { num := a.den, den := a.num.natAbs } protected def div (a b : Rat) : Rat := Rat.mul a b.inv protected def add (a b : Rat) : Rat := let g := Nat.gcd a.den b.den if g == 1 then { num := a.num * b.den + b.num * a.den, den := a.den * b.den } else let den := (a.den / g) * b.den let num := (b.den / g) * a.num + (a.den / g) * b.num let g1 := Nat.gcd num.natAbs g if g1 == 1 then { num, den } else { num := num / g1, den := den / g1 } protected def sub (a b : Rat) : Rat := let g := Nat.gcd a.den b.den if g == 1 then { num := a.num * b.den - b.num * a.den, den := a.den * b.den } else let den := (a.den / g) * b.den let num := (b.den / g) * a.num - (a.den / g) * b.num let g1 := Nat.gcd num.natAbs g if g1 == 1 then { num, den } else { num := num / g1, den := den / g1 } protected def neg (a : Rat) : Rat := { a with num := - a.num } protected def floor (a : Rat) : Int := if a.den == 1 then a.num else let r := a.num / a.den if a.num < 0 then r - 1 else r protected def ceil (a : Rat) : Int := if a.den == 1 then a.num else let r := a.num / a.den if a.num > 0 then r + 1 else r instance : LT Rat where lt a b := (Rat.lt a b) = true instance (a b : Rat) : Decidable (a < b) := inferInstanceAs (Decidable (_ = true)) instance : LE Rat where le a b := ¬(b < a) instance (a b : Rat) : Decidable (a ≤ b) := inferInstanceAs (Decidable (¬ _)) instance : Add Rat where add := Rat.add instance : Sub Rat where sub := Rat.sub instance : Neg Rat where neg := Rat.neg instance : Mul Rat where mul := Rat.mul instance : Div Rat where div a b := a * b.inv instance : OfNat Rat n where ofNat := { num := n } instance : Coe Int Rat where coe num := { num } end Rat end Lean