OldDivMod.agda 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. ------------------------------------------------------------------------
  2. -- The Agda standard library
  3. --
  4. -- Integer division
  5. ------------------------------------------------------------------------
  6. module Issue846.OldDivMod where
  7. open import Data.Nat as Nat
  8. open import Data.Nat.Properties
  9. open import Data.Nat.Solver
  10. open +-*-Solver
  11. open import Data.Fin as Fin using (Fin; zero; suc; toℕ; fromℕ)
  12. import Data.Fin.Properties as Fin
  13. open import Data.Nat.Induction
  14. open import Relation.Nullary.Decidable
  15. open import Relation.Binary.PropositionalEquality
  16. open ≡-Reasoning
  17. open import Function
  18. ------------------------------------------------------------------------
  19. -- Some boring lemmas
  20. private
  21. lem₁ : (m k : ℕ) →
  22. Nat.suc m ≡ suc (toℕ (Fin.inject+ k (fromℕ m)) + 0)
  23. lem₁ m k = cong suc $ begin
  24. m
  25. ≡⟨ sym $ Fin.toℕ-fromℕ m ⟩
  26. toℕ (fromℕ m)
  27. ≡⟨ Fin.toℕ-inject+ k (fromℕ m) ⟩
  28. toℕ (Fin.inject+ k (fromℕ m))
  29. ≡⟨ solve 1 (λ x → x := x :+ con 0) refl _ ⟩
  30. toℕ (Fin.inject+ k (fromℕ m)) + 0
  31. lem₂ : ∀ n → _
  32. lem₂ = solve 1 (λ n → con 1 :+ n := con 1 :+ (n :+ con 0)) refl
  33. lem₃ : ∀ n k q (r : Fin n) eq → suc n + k ≡ toℕ r + suc q * n
  34. lem₃ n k q r eq = begin
  35. suc n + k
  36. ≡⟨ solve 2 (λ n k → con 1 :+ n :+ k := n :+ (con 1 :+ k))
  37. refl n k ⟩
  38. n + suc k
  39. ≡⟨ cong (_+_ n) eq ⟩
  40. n + (toℕ r + q * n)
  41. ≡⟨ solve 3 (λ n r q → n :+ (r :+ q :* n) :=
  42. r :+ (con 1 :+ q) :* n)
  43. refl n (toℕ r) q ⟩
  44. toℕ r + suc q * n
  45. ------------------------------------------------------------------------
  46. -- Division
  47. infixl 7 _divMod_ _div_ _mod_
  48. -- A specification of integer division.
  49. record DivMod (dividend divisor : ℕ) : Set where
  50. constructor result
  51. field
  52. quotient : ℕ
  53. remainder : Fin divisor
  54. property : dividend ≡ toℕ remainder + quotient * divisor
  55. -- Integer division with remainder.
  56. -- Note that Induction.Nat.<-rec is used to establish termination of
  57. -- division. The run-time complexity of this implementation of integer
  58. -- division should be linear in the size of the dividend, assuming
  59. -- that well-founded recursion and the equality type are optimised
  60. -- properly (see "Inductive Families Need Not Store Their Indices"
  61. -- (Brady, McBride, McKinna, TYPES 2003)).
  62. _divMod_ : (dividend divisor : ℕ) {≢0 : False (divisor ≟ 0)} →
  63. DivMod dividend divisor
  64. _divMod_ m n {≢0} = <′-rec Pred dm m n {≢0}
  65. where
  66. Pred : ℕ → Set
  67. Pred dividend = (divisor : ℕ) {≢0 : False (divisor ≟ 0)} →
  68. DivMod dividend divisor
  69. 1+_ : ∀ {k n} → DivMod (suc k) n → DivMod (suc n + k) n
  70. 1+_ {k} {n} (result q r eq) = result (1 + q) r (lem₃ n k q r eq)
  71. dm : (dividend : ℕ) → <′-Rec Pred dividend → Pred dividend
  72. dm m rec zero {≢0 = ()}
  73. dm zero rec (suc n) = result 0 zero refl
  74. dm (suc m) rec (suc n) with compare m n
  75. dm (suc m) rec (suc .(suc m + k)) | less .m k = result 0 r (lem₁ m k)
  76. where r = suc (Fin.inject+ k (fromℕ m))
  77. dm (suc m) rec (suc .m) | equal .m = result 1 zero (lem₂ m)
  78. dm (suc .(suc n + k)) rec (suc n) | greater .n k =
  79. 1+ rec (suc k) le (suc n)
  80. where le = s≤′s (s≤′s (n≤′m+n n k))
  81. -- Integer division.
  82. _div_ : (dividend divisor : ℕ) {≢0 : False (divisor ≟ 0)} → ℕ
  83. _div_ m n {≢0} = DivMod.quotient $ _divMod_ m n {≢0}
  84. -- The remainder after integer division.
  85. _mod_ : (dividend divisor : ℕ) {≢0 : False (divisor ≟ 0)} → Fin divisor
  86. _mod_ m n {≢0} = DivMod.remainder $ _divMod_ m n {≢0}