Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 60 additions & 0 deletions Cubical/Data/Int/GCD.agda
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
module Cubical.Data.Int.GCD where

open import Cubical.Data.Empty as ⊥
import Cubical.Data.Nat.GCD as ℕ
open import Cubical.Data.Nat.Divisibility renaming (_∣_ to _∣ℕ_)
open import Cubical.Foundations.Prelude
open import Cubical.Data.Int.Divisibility
open import Cubical.Data.Int

------------------------------------------------------------------------
-- Definition
------------------------------------------------------------------------

gcd : ℤ → ℤ → ℤ
gcd i j = pos (ℕ.gcd (abs i) (abs j))

gcd-def : ∀ i j → gcd i j ≡ pos (ℕ.gcd (abs i) (abs j))
gcd-def i j = refl

gcdSym : ∀ i j → gcd i j ≡ gcd j i
gcdSym i j = cong pos (ℕ.gcdSym (abs i) (abs j))

------------------------------------------------------------------------
-- ℕ and ℤ conversions
------------------------------------------------------------------------

gcd∣ℕ→∣ℤ-lemma : ∀ {i j k : ℤ} → ℕ.gcd (abs i) (abs j) ∣ℕ (abs k) → gcd i j ∣ k
gcd∣ℕ→∣ℤ-lemma {i}{j}{k} gcdij|k = ∣ℕ→∣ gcdij|k

ℕ∣gcd→ℤ∣-lemma : ∀ {i j k : ℤ} → (abs k) ∣ℕ ℕ.gcd (abs i) (abs j) → k ∣ gcd i j
ℕ∣gcd→ℤ∣-lemma {i}{j}{k} k|gcdij = ∣ℕ→∣ k|gcdij

gcd∣ℤ→∣ℕ-lemma : ∀ {i j k : ℤ} → gcd i j ∣ k → ℕ.gcd (abs i) (abs j) ∣ℕ (abs k)
gcd∣ℤ→∣ℕ-lemma {i}{j}{k} gcdij|k = ∣→∣ℕ gcdij|k

ℤ∣gcd→ℕ∣-lemma : ∀ {i j k : ℤ} → k ∣ gcd i j → (abs k) ∣ℕ ℕ.gcd (abs i) (abs j)
ℤ∣gcd→ℕ∣-lemma {i}{j}{k} k|gcdij = ∣→∣ℕ k|gcdij

------------------------------------------------------------------------
-- Properties
------------------------------------------------------------------------

gcd[i,j]∣i : ∀ i j → gcd i j ∣ i
gcd[i,j]∣i i j = gcd∣ℕ→∣ℤ-lemma {i}{j} (ℕ.gcd[m,n]∣m (abs i) (abs j))

gcd[i,j]∣j : ∀ i j → gcd i j ∣ j
gcd[i,j]∣j i j = gcd∣ℕ→∣ℤ-lemma {i}{j} (ℕ.gcd[m,n]∣n (abs i) (abs j))

gcd-greatest : ∀ {i j c} → c ∣ i → c ∣ j → c ∣ gcd i j
gcd-greatest {i}{j}{c} ci cj =
ℕ∣gcd→ℤ∣-lemma {i}{j}{c} (ℕ.gcd-greatest (∣→∣ℕ ci) (∣→∣ℕ cj))

gcd[0,0]≡0 : gcd 0 0 ≡ 0
gcd[0,0]≡0 = cong pos ℕ.gcd[0,0]≡0

gcd[i,j]≡0⇒i≡0 : ∀ {i j} → gcd i j ≡ 0 → i ≡ 0
gcd[i,j]≡0⇒i≡0 {i} {j} eqn = abs≡0 i (ℕ.gcd[m,n]≡0⇒m≡0 {abs i}{abs j} (injPos eqn))

gcd[i,j]≡0⇒j≡0 : ∀ {i j} → gcd i j ≡ 0 → j ≡ 0
gcd[i,j]≡0⇒j≡0 {i}{j} eqn = gcd[i,j]≡0⇒i≡0 {j}{i} (gcdSym j i ∙ eqn)
4 changes: 4 additions & 0 deletions Cubical/Data/Nat/Base.agda
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ isZero : ℕ → Bool
isZero zero = true
isZero (suc n) = false

NonZero : ℕ → Type
NonZero zero = ⊥
NonZero (ℕ.suc n) = Unit

-- exponential

_^_ : ℕ → ℕ → ℕ
Expand Down
6 changes: 6 additions & 0 deletions Cubical/Data/Nat/Coprime.agda
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ open import Cubical.Data.Nat.GCD
areCoprime : ℕ × ℕ → Type₀
areCoprime (m , n) = isGCD m n 1

zeroCoprime : {d-1 : ℕ} → (copr : areCoprime (0 , ℕ.suc d-1)) → d-1 ≡ 0
zeroCoprime {d-1} copr = injSuc (zeroGCD-unique (symGCD copr))

isPropAreCoprime : (x : ℕ) (y : ℕ) → isProp (areCoprime (x , y))
isPropAreCoprime x y = isPropIsGCD

-- Any pair (m , n) can be converted to a coprime pair (m' , n') s.t.
-- m' ∣ m, n' ∣ n if and only if one of m or n is nonzero

Expand Down
62 changes: 55 additions & 7 deletions Cubical/Data/Nat/GCD.agda
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ module Cubical.Data.Nat.GCD where
open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.HLevels
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Isomorphism

open import Cubical.Induction.WellFounded

open import Cubical.Data.Sigma as Σ
open import Cubical.Data.Fin as F hiding (_%_ ; _/_)
open import Cubical.Data.NatPlusOne
open import Cubical.Data.Sum
open import Cubical.Data.Fin as F hiding (_%_ ; _/_)

open import Cubical.HITs.PropositionalTruncation as PropTrunc

open import Cubical.Data.Empty as ⊥
open import Cubical.Data.Nat.Base
open import Cubical.Data.Nat.Properties
open import Cubical.Data.Nat.Order
Expand All @@ -27,7 +27,7 @@ open import Cubical.Relation.Nullary

private
variable
m n d : ℕ
m n c d : ℕ

-- common divisors

Expand Down Expand Up @@ -55,7 +55,6 @@ isPropGCD : isProp (GCD m n)
isPropGCD (d , dCD , gr) (d' , d'CD , gr') =
Σ≡Prop (λ _ → isPropIsGCD) (antisym∣ (gr' d dCD) (gr d' d'CD))


symGCD : isGCD m n d → isGCD n m d
symGCD (dCD , gr) = symCD dCD , λ { d' d'CD → gr d' (symCD d'CD) }

Expand All @@ -65,11 +64,21 @@ divsGCD p = (∣-refl refl , p) , λ { d (d∣m , _) → d∣m }
oneGCD : ∀ m → isGCD m 1 1
oneGCD m = symGCD (divsGCD (∣-oneˡ m))


-- The base case of the Euclidean algorithm
zeroGCD : ∀ m → isGCD m 0 m
zeroGCD m = divsGCD (∣-zeroʳ m)

-- zeroGCD-unique lemma: if d is gcd of m and 0, then d ≡ m
zeroGCD-unique : {m d : ℕ} → isGCD m 0 d → m ≡ d
zeroGCD-unique {m} {d} (iscd , greatest) =
let
d∣m = fst iscd
m∣m = ∣-refl (refl {x = m})
m∣0 = ∣-zeroʳ m
m∣d = greatest m (m∣m , m∣0)
in
antisym∣ m∣d d∣m

-- a pair of useful lemmas about ∣ and (efficient) %
private
∣→∣% : ∀ {m n d} → d ∣ m → d ∣ n → d ∣ (m % n)
Expand Down Expand Up @@ -159,7 +168,6 @@ euclid m n@(suc n-1) =
in
r .fst , stepGCD (r .snd)


isContrGCD : ∀ m n → isContr (GCD m n)
isContrGCD m n = euclid m n , isPropGCD _

Expand All @@ -177,6 +185,16 @@ isGCD→gcd≡ dGCD = cong fst (isContrGCD _ _ .snd (_ , dGCD))
gcd≡→isGCD : gcd m n ≡ d → isGCD m n d
gcd≡→isGCD p = subst (isGCD _ _) p (gcdIsGCD _ _)

gcd≡isGCD : ∀ m n d → (gcd m n ≡ d) ≡ (isGCD m n d)
gcd≡isGCD m n d = isoToPath (iso gcd≡→isGCD isGCD→gcd≡
(λ b → isPropIsGCD (gcd≡→isGCD (isGCD→gcd≡ b)) b)
(λ a → isSetℕ (gcd m n) d (isGCD→gcd≡ {m}{n}{d} (gcd≡→isGCD a)) a))

uniqueGCD : ∀ {d'} → isGCD m n d → isGCD m n d' → d ≡ d'
uniqueGCD isgd isgd' = sym (isGCD→gcd≡ isgd) ∙ isGCD→gcd≡ isgd'

gcdSym : (m n : ℕ) → (gcd m n) ≡ (gcd n m)
gcdSym m n = uniqueGCD (gcdIsGCD m n) (symGCD (gcdIsGCD n m))

-- multiplicative properties of the gcd

Expand Down Expand Up @@ -214,6 +232,36 @@ isGCD-multʳ {m} {n} {d} k dGCD = gcd≡→isGCD (gcd-factorʳ m n k ∙ cong (_
where r : gcd m n ≡ d
r = isGCD→gcd≡ dGCD

-- Core properties of gcd

gcd[m,n]∣m : (m n : ℕ) → (gcd m n) ∣ m
gcd[m,n]∣m m n = fst (fst (gcdIsGCD m n))

gcd[m,n]∣n : (m n : ℕ) → (gcd m n) ∣ n
gcd[m,n]∣n m n = transport (cong (λ a → a ∣ n) (gcdSym n m) ) (gcd[m,n]∣m n m)

gcd-greatest : c ∣ m → c ∣ n → c ∣ gcd m n
gcd-greatest = curry (snd (gcdIsGCD _ _) _)

-- Other properties

gcd[0,0]≡0 : gcd 0 0 ≡ 0
gcd[0,0]≡0 = antisym∣ (∣-zeroʳ (gcd 0 0) ) (gcd-greatest (∣-zeroʳ 0) (∣-zeroʳ 0))

gcd[m,n]≢0 : ∀ (m n : ℕ) → (¬ (m ≡ 0)) ⊎ (¬ (n ≡ 0)) → ¬ (gcd m n ≡ 0)
gcd[m,n]≢0 m n (inl m≢0) gcd0 =
m≢0 (sym (∣-zeroˡ (transport (cong (λ a → a ∣ m) gcd0) (gcd[m,n]∣m m n))))
gcd[m,n]≢0 m n (inr n≢0) gcd0 =
n≢0 (sym (∣-zeroˡ (transport ((cong (λ a → a ∣ n) gcd0)) (gcd[m,n]∣n m n))))

gcd[m,n]≡0⇒m≡0 : gcd m n ≡ 0 → m ≡ 0
gcd[m,n]≡0⇒m≡0 {zero} {n} gmn = refl
gcd[m,n]≡0⇒m≡0 {suc m} {n} gmn =
⊥.elim {A = λ bot → suc m ≡ 0} (gcd[m,n]≢0 (suc m) n (inl snotz) gmn)

gcd[m,n]≡0⇒n≡0 : ∀ {m n} → gcd m n ≡ 0 → n ≡ 0
gcd[m,n]≡0⇒n≡0 {m}{n} gmn = gcd[m,n]≡0⇒m≡0 {n} {m} (gcdSym n m ∙ gmn)

-- Inequality for strict divisibility

stDivIneqGCD : ¬ m ≡ 0 → ¬ m ∣ n → (g : GCD m n) → g .fst < m
Expand Down
Loading