Skip to content

Commit 5087388

Browse files
committed
DivMod!
1 parent b51548b commit 5087388

File tree

1 file changed

+108
-0
lines changed

1 file changed

+108
-0
lines changed
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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

Comments
 (0)