|
| 1 | +------------------------------------------------------------------------ |
| 2 | +-- The Agda standard library |
| 3 | +-- |
| 4 | +-- Division with remainder for integers constructed as a pair of naturals |
| 5 | +------------------------------------------------------------------------ |
| 6 | + |
| 7 | +{-# OPTIONS --safe --cubical-compatible #-} |
| 8 | + |
| 9 | +module Data.Integer.IntConstruction.DivMod where |
| 10 | + |
| 11 | +open import Data.Fin.Base as Fin using (Fin) |
| 12 | +import Data.Fin.Properties as Fin |
| 13 | +open import Data.Integer.IntConstruction |
| 14 | +open import Data.Integer.IntConstruction.Properties |
| 15 | +open import Data.Nat.Base as ℕ using (ℕ) |
| 16 | +import Data.Nat.Properties as ℕ |
| 17 | +import Data.Nat.DivMod as ℕ |
| 18 | +open import Function.Base |
| 19 | +open import Relation.Binary |
| 20 | +open import Relation.Binary.PropositionalEquality |
| 21 | +open import Relation.Nullary.Decidable |
| 22 | + |
| 23 | +-- should the divisor also be an integer? |
| 24 | +record DivMod (dividend : ℤ) (divisor : ℕ) : Set where |
| 25 | + field |
| 26 | + quotient : ℤ |
| 27 | + remainder : ℕ |
| 28 | + remainder<divisor : remainder ℕ.< divisor |
| 29 | + property : dividend ≃ ⁺ remainder + quotient * ⁺ divisor |
| 30 | + |
| 31 | +divMod : ∀ i n .{{_ : ℕ.NonZero n}} → DivMod i n |
| 32 | +divMod (a ⊖ b) n = record |
| 33 | + { quotient = quotient |
| 34 | + ; remainder<divisor = remainder<n |
| 35 | + ; property = property |
| 36 | + } |
| 37 | + where |
| 38 | + open ≡-Reasoning |
| 39 | + |
| 40 | + -- either the actual quotient or one above it |
| 41 | + quotient′ : ℤ |
| 42 | + quotient′ = (a ℕ./ n) ⊖ (b ℕ./ n) |
| 43 | + |
| 44 | + remainder′ : ℤ |
| 45 | + remainder′ = (a ℕ.% n) ⊖ (b ℕ.% n) |
| 46 | + |
| 47 | + property′ : a ⊖ b ≃ remainder′ + quotient′ * ⁺ n |
| 48 | + property′ = mk≃ $ cong₂ ℕ._+_ left right |
| 49 | + where |
| 50 | + left : a ≡ a ℕ.% n ℕ.+ (a ℕ./ n ℕ.* n ℕ.+ b ℕ./ n ℕ.* 0) |
| 51 | + left = begin |
| 52 | + a ≡⟨ ℕ.m≡m%n+[m/n]*n a n ⟩ |
| 53 | + a ℕ.% n ℕ.+ a ℕ./ n ℕ.* n ≡⟨ cong (a ℕ.% n ℕ.+_) (ℕ.+-identityʳ (a ℕ./ n ℕ.* n)) ⟨ |
| 54 | + a ℕ.% n ℕ.+ (a ℕ./ n ℕ.* n ℕ.+ 0) ≡⟨ cong (λ z → a ℕ.% n ℕ.+ (a ℕ./ n ℕ.* n ℕ.+ z)) (ℕ.*-zeroʳ (b ℕ./ n)) ⟨ |
| 55 | + a ℕ.% n ℕ.+ (a ℕ./ n ℕ.* n ℕ.+ b ℕ./ n ℕ.* 0) ∎ |
| 56 | + |
| 57 | + right : b ℕ.% n ℕ.+ (a ℕ./ n ℕ.* 0 ℕ.+ b ℕ./ n ℕ.* n) ≡ b |
| 58 | + right = begin |
| 59 | + b ℕ.% n ℕ.+ (a ℕ./ n ℕ.* 0 ℕ.+ b ℕ./ n ℕ.* n) ≡⟨ cong (λ z → b ℕ.% n ℕ.+ (z ℕ.+ b ℕ./ n ℕ.* n)) (ℕ.*-zeroʳ (a ℕ./ n)) ⟩ |
| 60 | + b ℕ.% n ℕ.+ (0 ℕ.+ b ℕ./ n ℕ.* n) ≡⟨ cong (b ℕ.% n ℕ.+_) (ℕ.+-identityˡ (b ℕ./ n ℕ.* n)) ⟩ |
| 61 | + b ℕ.% n ℕ.+ b ℕ./ n ℕ.* n ≡⟨ ℕ.m≡m%n+[m/n]*n b n ⟨ |
| 62 | + b ∎ |
| 63 | + |
| 64 | + quotient : ℤ |
| 65 | + quotient with b ℕ.% n ℕ.≤? a ℕ.% n |
| 66 | + ... | yes _ = quotient′ |
| 67 | + ... | no _ = pred quotient′ |
| 68 | + |
| 69 | + remainder : ℕ |
| 70 | + remainder with b ℕ.% n ℕ.≤? a ℕ.% n |
| 71 | + ... | yes _ = a ℕ.% n ℕ.∸ b ℕ.% n |
| 72 | + ... | no _ = n ℕ.∸ (b ℕ.% n ℕ.∸ a ℕ.% n) |
| 73 | + |
| 74 | + remainder<n : remainder ℕ.< n |
| 75 | + remainder<n with b ℕ.% n ℕ.≤? a ℕ.% n |
| 76 | + ... | yes _ = ℕ.≤-<-trans (ℕ.m∸n≤m (a ℕ.% n) (b ℕ.% n)) (ℕ.m%n<n a n) |
| 77 | + ... | no b%n≰a%n = ℕ.∸-monoʳ-< {o = 0} (ℕ.m<n⇒0<n∸m (ℕ.≰⇒> b%n≰a%n)) (ℕ.≤-trans (ℕ.m∸n≤m (b ℕ.% n) (a ℕ.% n)) (ℕ.<⇒≤ (ℕ.m%n<n b n))) |
| 78 | + |
| 79 | + property : a ⊖ b ≃ ⁺ remainder + quotient * ⁺ n |
| 80 | + property with b ℕ.% n ℕ.≤? a ℕ.% n |
| 81 | + ... | yes p = ≃-trans property′ (+-cong rem-prop ≃-refl) |
| 82 | + where |
| 83 | + rem-prop : remainder′ ≃ ⁺ (a ℕ.% n ℕ.∸ b ℕ.% n) |
| 84 | + rem-prop = mk≃ $ begin |
| 85 | + a ℕ.% n ℕ.+ 0 ≡⟨ ℕ.+-identityʳ (a ℕ.% n) ⟩ |
| 86 | + a ℕ.% n ≡⟨ ℕ.m∸n+n≡m p ⟨ |
| 87 | + a ℕ.% n ℕ.∸ b ℕ.% n ℕ.+ b ℕ.% n ∎ |
| 88 | + ... | no b%n≰a%n = ≃-trans property′ $ mk≃ $ begin |
| 89 | + (w ℕ.+ x) ℕ.+ (y ℕ.+ (n ℕ.+ z)) ≡⟨ cong ((w ℕ.+ x) ℕ.+_) (ℕ.+-assoc y n z) ⟨ |
| 90 | + (w ℕ.+ x) ℕ.+ ((y ℕ.+ n) ℕ.+ z) ≡⟨ cong (λ k → (w ℕ.+ x) ℕ.+ (k ℕ.+ z)) (ℕ.+-comm y n) ⟩ |
| 91 | + (w ℕ.+ x) ℕ.+ ((n ℕ.+ y) ℕ.+ z) ≡⟨ cong ((w ℕ.+ x) ℕ.+_) (ℕ.+-assoc n y z) ⟩ |
| 92 | + (w ℕ.+ x) ℕ.+ (n ℕ.+ (y ℕ.+ z)) ≡⟨ ℕ.+-assoc (w ℕ.+ x) n (y ℕ.+ z) ⟨ |
| 93 | + ((w ℕ.+ x) ℕ.+ n) ℕ.+ (y ℕ.+ z) ≡⟨ cong (ℕ._+ (y ℕ.+ z)) (ℕ.+-comm (w ℕ.+ x) n) ⟩ |
| 94 | + (n ℕ.+ (w ℕ.+ x)) ℕ.+ (y ℕ.+ z) ≡⟨ cong (ℕ._+ (y ℕ.+ z)) (ℕ.+-assoc n w x) ⟨ |
| 95 | + ((n ℕ.+ w) ℕ.+ x) ℕ.+ (y ℕ.+ z) ≡⟨ cong (λ k → ((n ℕ.+ k) ℕ.+ x) ℕ.+ (y ℕ.+ z)) (ℕ.m∸[m∸n]≡n (ℕ.≰⇒≥ b%n≰a%n)) ⟨ |
| 96 | + ((n ℕ.+ (v ℕ.∸ (v ℕ.∸ w))) ℕ.+ x) ℕ.+ (y ℕ.+ z) ≡⟨ cong (λ k → (k ℕ.+ x) ℕ.+ (y ℕ.+ z)) (ℕ.+-∸-assoc n (ℕ.m∸n≤m v w)) ⟨ |
| 97 | + (((n ℕ.+ v) ℕ.∸ (v ℕ.∸ w)) ℕ.+ x) ℕ.+ (y ℕ.+ z) ≡⟨ cong (λ k → (k ℕ.+ x) ℕ.+ (y ℕ.+ z)) (ℕ.+-∸-comm v (ℕ.≤-trans (ℕ.m∸n≤m v w) (ℕ.<⇒≤ (ℕ.m%n<n b n)))) ⟩ |
| 98 | + (((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ v) ℕ.+ x) ℕ.+ (y ℕ.+ z) ≡⟨ cong (ℕ._+ (y ℕ.+ z)) (ℕ.+-assoc (n ℕ.∸ (v ℕ.∸ w)) v x) ⟩ |
| 99 | + ((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ (v ℕ.+ x)) ℕ.+ (y ℕ.+ z) ≡⟨ cong (λ k → ((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ k) ℕ.+ (y ℕ.+ z)) (ℕ.+-comm v x) ⟩ |
| 100 | + ((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ (x ℕ.+ v)) ℕ.+ (y ℕ.+ z) ≡⟨ cong (ℕ._+ (y ℕ.+ z)) (ℕ.+-assoc (n ℕ.∸ (v ℕ.∸ w)) x v) ⟨ |
| 101 | + (((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ x) ℕ.+ v) ℕ.+ (y ℕ.+ z) ≡⟨ ℕ.+-assoc (n ℕ.∸ (v ℕ.∸ w) ℕ.+ x) v (y ℕ.+ z) ⟩ |
| 102 | + ((n ℕ.∸ (v ℕ.∸ w)) ℕ.+ x) ℕ.+ (v ℕ.+ (y ℕ.+ z)) ∎ |
| 103 | + where |
| 104 | + w = a ℕ.% n |
| 105 | + x = a ℕ./ n ℕ.* n ℕ.+ b ℕ./ n ℕ.* 0 |
| 106 | + y = a ℕ./ n ℕ.* 0 |
| 107 | + z = b ℕ./ n ℕ.* n |
| 108 | + v = b ℕ.% n |
0 commit comments