view automaton-in-agda/src/gcd.agda @ 206:f1370437c68e

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 19 Jun 2021 10:54:51 +0900
parents e97cf4fb67fa
children 764bc577b1e9
line wrap: on
line source

{-# OPTIONS --allow-unsolved-metas #-}
module gcd where

open import Data.Nat 
open import Data.Nat.Properties
open import Data.Empty
open import Data.Unit using (⊤ ; tt)
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality
open import Relation.Binary.Definitions
open import nat
open import logic

record Factor (n m : ℕ ) : Set where
   field 
      factor : ℕ
      remain : ℕ
      is-factor : factor * n + remain ≡ m

record Dividable (n m : ℕ ) : Set where
   field 
      factor : ℕ
      is-factor : factor * n + 0 ≡ m 

open Factor

DtoF : {n m : ℕ} → Dividable n m → Factor n m
DtoF {n} {m} record { factor = f ; is-factor = fa } = record { factor = f ; remain = 0 ; is-factor = fa }

FtoD : {n m : ℕ} → (fc : Factor n m) → remain fc ≡ 0 → Dividable n m 
FtoD {n} {m} record { factor = f ; remain = r ; is-factor = fa } refl = record { factor = f ; is-factor = fa }

--decD : {n m : ℕ} → Dec (Dividable n m)
--decD = {!!}

--divdable^2 : ( n k : ℕ ) → Dividable k ( n * n ) → Dividable k n
--divdable^2 n k dn2 = {!!}

decf : { n k : ℕ } → ( x : Factor k (suc n) ) → Factor k n
decf {n} {k} record { factor = f ; remain = r ; is-factor = fa } = 
 decf1 {n} {k} f r fa where
  decf1 : { n k : ℕ } → (f r : ℕ) → (f * k + r ≡ suc n)  → Factor k n 
  decf1 {n} {k} f (suc r) fa  =  -- this case must be the first
     record { factor = f ; remain = r ; is-factor = ( begin -- fa : f * k + suc r ≡ suc n
        f * k + r ≡⟨ cong pred ( begin
          suc ( f * k + r ) ≡⟨ +-comm _ r ⟩
          r + suc (f * k)  ≡⟨ sym (+-assoc r 1 _) ⟩
          (r + 1) + f * k ≡⟨ cong (λ t → t + f * k ) (+-comm r 1) ⟩
          (suc r ) + f * k ≡⟨ +-comm (suc r) _ ⟩
          f * k + suc r  ≡⟨ fa ⟩
          suc n ∎ ) ⟩ 
        n ∎ ) }  where open ≡-Reasoning
  decf1 {n} {zero} (suc f) zero fa  = ⊥-elim ( nat-≡< fa (
        begin suc (suc f * zero + zero) ≡⟨ cong suc (+-comm _ zero)  ⟩
        suc (f * 0) ≡⟨ cong suc (*-comm f zero)  ⟩
        suc zero ≤⟨ s≤s z≤n ⟩
        suc n ∎ )) where open ≤-Reasoning
  decf1 {n} {suc k} (suc f) zero fa  = 
     record { factor = f ; remain = k ; is-factor = ( begin -- fa : suc (k + f * suc k + zero) ≡ suc n
        f * suc k + k ≡⟨ +-comm _ k ⟩
        k + f * suc k ≡⟨ +-comm zero _ ⟩
        (k + f * suc k) + zero  ≡⟨ cong pred fa ⟩
        n ∎ ) }  where open ≡-Reasoning

div0 :  {k : ℕ} → Dividable k 0
div0 {k} = record { factor = 0; is-factor = refl }

gcd1 : ( i i0 j j0 : ℕ ) → ℕ
gcd1 zero i0 zero j0 with <-cmp i0 j0
... | tri< a ¬b ¬c = i0
... | tri≈ ¬a refl ¬c = i0
... | tri> ¬a ¬b c = j0
gcd1 zero i0 (suc zero) j0 = 1
gcd1 zero zero (suc (suc j)) j0 = j0
gcd1 zero (suc i0) (suc (suc j)) j0 = gcd1 i0 (suc i0) (suc j) (suc (suc j))
gcd1 (suc zero) i0 zero j0 = 1
gcd1 (suc (suc i)) i0 zero zero = i0
gcd1 (suc (suc i)) i0 zero (suc j0) = gcd1 (suc i) (suc (suc i))  j0 (suc j0)
gcd1 (suc i) i0 (suc j) j0 = gcd1 i i0 j j0  

gcd : ( i j : ℕ ) → ℕ
gcd i j = gcd1 i i j j 

div1 : { k : ℕ } → k > 1 →  ¬  Dividable k 1
div1 {k} k>1 record { factor = (suc f) ; is-factor = fa } = ⊥-elim ( nat-≡< (sym fa) ( begin
    2 ≤⟨ k>1 ⟩
    k ≡⟨ +-comm 0 _ ⟩
    k + 0 ≡⟨ refl  ⟩
    1 * k ≤⟨ *-mono-≤ {1} {suc f} (s≤s z≤n ) ≤-refl ⟩
    suc f * k ≡⟨ +-comm 0 _ ⟩
    suc f * k + 0 ∎  )) where open ≤-Reasoning  

div-div : { i j k : ℕ } → k > 1 →  Dividable k i →  Dividable k j → Dividable k (i - j) ∧ Dividable k (j - i)
div-div {i} {j} {suc k} k>1 di dj = div-div0 di dj where
   div-div1 : {i j : ℕ}   →  Dividable (suc k) i →  Dividable (suc k) j → i < j  → Dividable (suc k) (j - i)
   div-div1 {i} {j} record { factor = fi ; is-factor = fai } record { factor = fj ; is-factor = faj } i<j =
            subst (λ g →  Dividable (suc k) g ) div-div3 ( div-div2 fj fi fi<fj ) where
      fi<fj : fi < fj
      fi<fj with <-cmp fi fj
      ... | tri< a ¬b ¬c = a
      ... | tri≈ ¬a b ¬c = ⊥-elim ( nat-≡< (cong (λ g → g * suc k + 0) b) (begin
             suc (fi * suc k + 0)  ≡⟨ cong suc fai ⟩
             suc i  ≤⟨ i<j ⟩
             j  ≡⟨ sym faj ⟩
             fj * suc k + 0 ∎  )) where open ≤-Reasoning  
      ... | tri> ¬a ¬b c = ⊥-elim ( nat-<> (*-monoˡ-< k c ) (begin
             suc (fi * suc k) ≡⟨ +-comm 0 _ ⟩
             suc (fi * suc k + 0) ≡⟨ cong suc fai ⟩
             suc i ≤⟨ i<j ⟩
             j ≡⟨ sym faj ⟩
             fj * suc k + 0 ≡⟨ +-comm _ 0 ⟩
             fj * suc k ∎  )) where open ≤-Reasoning  
      div-div3 : (fj * suc k) - (fi * suc k) ≡ j - i
      div-div3 = begin (fj * suc k) - (fi * suc k) ≡⟨  cong₂ (λ g h → g - h) (+-comm 0 (fj * suc k)) (+-comm 0 (fi * suc k)) ⟩
          (fj * suc k + 0) - (fi * suc k + 0) ≡⟨  cong₂ (λ g h → g - h) faj  fai ⟩
          j - i ∎  where open ≡-Reasoning  
      div-div2 : (fj fi : ℕ) → fi < fj → Dividable (suc k) ((fj * suc k) - (fi * suc k))
      div-div2 zero fi i<j = subst (λ g → Dividable (suc k) g) (begin
          0 ≡⟨ sym (minus<=0 {0} {fi * suc k} z≤n ) ⟩
          0 -  (fi * suc k) ≡⟨ refl ⟩
          (zero * suc k) - (fi * suc k) ∎ ) div0
          where open ≡-Reasoning  
      div-div2 (suc fj) fi i<j with <-cmp fi fj
      ... | tri> ¬a ¬b c = ⊥-elim ( nat-≤> c i<j  )
      ... | tri≈ ¬a refl ¬c = record { factor = 1 ; is-factor = (begin
             1 * suc k + 0 ≡⟨ +-comm _ 0 ⟩
               1 * suc k ≡⟨ cong suc (+-comm _ 0) ⟩
             suc k ≡⟨ sym (minus+y-y {suc k} {fj * suc k}) ⟩
             (suc k + fj * suc k) - (fj * suc k) ≡⟨ refl ⟩
             (suc (k + fj * suc k)) - (fj * suc k) ∎  )} where open ≡-Reasoning  
      ... | tri< fi<fj ¬b ¬c = record { factor = suc (Dividable.factor (div-div2 fj fi fi<fj )) ; is-factor = ( begin 
          suc (Dividable.factor (div-div2 fj fi fi<fj )) * suc k + 0 ≡⟨ +-comm _ 0 ⟩
          suc (Dividable.factor (div-div2 fj fi fi<fj )) * suc k  ≡⟨ refl ⟩
          suc k + ((Dividable.factor (div-div2 fj fi fi<fj )) * suc k )  ≡⟨ cong (λ g → suc k + g ) (+-comm 0 _) ⟩
          suc k + ((Dividable.factor (div-div2 fj fi fi<fj )) * suc k + 0)  ≡⟨ cong (λ g → suc k + g) (Dividable.is-factor (div-div2 fj fi fi<fj) ) ⟩
          suc k + ((fj * suc k) - (fi * suc k)) ≡⟨ minus+yz {suc k} {fj * suc k} {fi * suc k} (<to≤ (*-monoˡ-< k fi<fj )) ⟩
           ( (suc k + (fj * suc k)) - (fi * suc k)) ≡⟨ refl ⟩
          ((suc fj * suc k) - (fi * suc k)) ∎ ) } where
             open ≡-Reasoning  
   div-div0 : { i j : ℕ } →  Dividable (suc k) i →  Dividable (suc k) j → Dividable (suc k) (i - j) ∧ Dividable (suc k) (j - i)
   div-div0 {i} {j} di dj with <-cmp i j
   ... | tri< a ¬b ¬c    = ⟪ subst (λ g → Dividable (suc k) g) (sym (minus<=0 {i} {j} (<to≤ a))) div0 , div-div1 di dj a ⟫ 
   ... | tri≈ ¬a refl ¬c = ⟪ subst (λ g → Dividable (suc k) g) (sym (minus<=0 {i} {i} refl-≤)) div0 ,
                             subst (λ g → Dividable (suc k) g) (sym (minus<=0 {i} {i} refl-≤)) div0 ⟫
   ... | tri> ¬a ¬b c    = ⟪ div-div1 dj di c , subst (λ g → Dividable (suc k) g) (sym (minus<=0 {j} {i} (<to≤ c))) div0  ⟫ 

open _∧_

gcd-gt : ( i i0 j j0 k : ℕ ) → k > 1 → (if : Factor k i) (i0f : Dividable k i0 ) (jf : Factor k j ) (j0f : Dividable k j0)
   → Dividable k (i - j) ∧ Dividable k (j - i)
   → Dividable k ( gcd1 i i0 j j0 ) 
gcd-gt zero i0 zero j0 k k>1 if i0f jf j0f i-j with <-cmp i0 j0
... | tri< a ¬b ¬c = i0f 
... | tri≈ ¬a refl ¬c = i0f
... | tri> ¬a ¬b c = j0f
gcd-gt zero i0 (suc zero) j0 k k>1 if i0f jf j0f i-j = ⊥-elim (div1 k>1 (proj2 i-j)) -- can't happen
gcd-gt zero zero (suc (suc j)) j0 k k>1 if i0f jf j0f i-j = j0f
gcd-gt zero (suc i0) (suc (suc j)) j0 k k>1 if i0f jf j0f i-j =   
    gcd-gt i0 (suc i0) (suc j) (suc (suc j))  k k>1 (decf (DtoF i0f)) i0f (decf jf) (proj2 i-j) (div-div k>1 i0f (proj2 i-j))
gcd-gt (suc zero) i0 zero j0 k k>1 if i0f jf j0f i-j  = ⊥-elim (div1 k>1 (proj1 i-j)) -- can't happen
gcd-gt (suc (suc i)) i0 zero zero k k>1 if i0f jf j0f i-j  = i0f
gcd-gt (suc (suc i)) i0 zero (suc j0) k k>1 if i0f jf j0f i-j  = --   
     gcd-gt (suc i) (suc (suc i)) j0 (suc j0) k k>1 (decf if) (proj1 i-j) (decf (DtoF j0f)) j0f (div-div k>1 (proj1 i-j) j0f )
gcd-gt (suc zero) i0 (suc j) j0 k k>1 if i0f jf j0f i-j  =  
     gcd-gt zero i0 j j0 k k>1 (decf if) i0f (decf jf) j0f i-j
gcd-gt (suc (suc i)) i0 (suc j) j0 k k>1 if i0f jf j0f i-j  = 
     gcd-gt (suc i) i0 j j0 k k>1 (decf if) i0f (decf jf) j0f i-j 

gcd-div : ( i j k : ℕ ) → k > 1 → (if : Dividable k i) (jf : Dividable k j ) 
   → Dividable k ( gcd i  j ) 
gcd-div i j k k>1 if jf = gcd-gt i i j j k k>1 (DtoF if) if (DtoF jf) jf (div-div k>1 if jf)

-- open import Data.Sum.Base
-- factor-0 : (i j : ℕ) → j ≤ i → Factor (i - j) 0 → i ≡ j
-- factor-0 i j lt eq with m*n≡0⇒m≡0∨n≡0 (factor eq) ( m+n≡0⇒m≡0 (factor eq * (i - j)) (is-factor eq ) )
-- ... | inj₁ x = {!!}
-- ... | inj₂ y =  i-j=0→i=j lt y
--     factor eq * (i - j) + remain eq ≡⟨ is-factor eq ⟩ 

gg1 : {i0 : ℕ } → 1 * i0 + 0 ≡ i0
gg1 {i0} = begin  1 * i0 + 0 ≡⟨ +-comm _ 0 ⟩
    i0 + 0 ≡⟨ +-comm _ 0 ⟩
    i0 ∎   where open ≡-Reasoning  

gg3 : {i0 : ℕ } → i0 * 1 + 0 ≡ i0
gg3 = trans (+-comm _ 0 ) m*1=m

open import Data.Sum.Base

gcd-divable : ( i i0 j j0 : ℕ )
      → (if : Factor i0 j0) (jf : Factor j0 i0)   -- factor eq * i0 + (j0 - i0) = j0
      → remain if ≡ j - i  → remain jf ≡ i - j
      → Dividable ( gcd1 i i0 j j0 ) i0 ∧ Dividable ( gcd1 i i0 j j0 ) j0
gcd-divable zero i0 zero j0 if jf if=0 jf=0 with <-cmp i0 j0
... | tri< a ¬b ¬c = ⟪ record { factor = 1 ; is-factor = gg1 } ,  record { factor = factor if ; is-factor = gg2 } ⟫ where
    gg2 : factor if *  i0 + 0 ≡ j0
    gg2 = begin
      factor if * i0 + 0 ≡⟨ cong (λ k → factor if * i0 + k) (sym if=0) ⟩
      factor if * i0 + remain if ≡⟨ is-factor if ⟩
      j0 ∎   where open ≡-Reasoning  
... | tri≈ ¬a refl ¬c = ⟪ record { factor = 1 ; is-factor = gg1 } ,  record { factor = 1 ; is-factor = gg1 } ⟫
... | tri> ¬a ¬b c = ⟪ record { factor = factor jf ; is-factor = gg2 } ,  record { factor = 1 ; is-factor = gg1 } ⟫ where
    gg2 : factor jf *  j0 + 0 ≡ i0
    gg2 = begin
      factor jf * j0 + 0 ≡⟨ cong (λ k → factor jf * j0 + k) (sym jf=0)  ⟩
      factor jf * j0 + remain jf ≡⟨ is-factor jf ⟩
      i0 ∎   where open ≡-Reasoning  
gcd-divable zero i0 (suc zero) j0 if jf if=0 jf=0 =  ⟪ record { factor = i0 ; is-factor = gg3 } ,  record { factor = j0 ; is-factor = gg3 } ⟫ 
gcd-divable zero zero (suc (suc j)) j0 if jf if=0 jf=0 = ⟪ record { factor = factor jf ; is-factor = gg4 } ,  record { factor = 1 ; is-factor = gg1 } ⟫
   where
    gg4 :  factor jf * j0  + 0 ≡ zero
    gg4 with  m*n≡0⇒m≡0∨n≡0 (factor jf) (  m+n≡0⇒m≡0 (factor jf * j0) (is-factor jf))
    ... | inj₁ x = begin
      factor jf * j0 + 0 ≡⟨ +-comm _ 0 ⟩
      factor jf * j0  ≡⟨ cong (λ k → k * j0) x  ⟩
      0 ∎   where open ≡-Reasoning
    ... | inj₂ y = begin
      factor jf * j0 + 0 ≡⟨ +-comm _ 0 ⟩
      factor jf * j0  ≡⟨ cong (λ k → factor jf * k) y  ⟩
      factor jf * 0  ≡⟨ *-comm (factor jf) 0  ⟩
      0 ∎   where open ≡-Reasoning
gcd-divable zero (suc i0) (suc (suc j)) j0 if jf if=0 jf=0
    with gcd-divable i0 (suc i0) (suc j) (suc (suc j))
        record { factor = {!!} ; is-factor = {!!} ; remain = suc j - i0 }
        record { factor = {!!} ; is-factor = {!!} ; remain = i0 - suc j } refl refl 
... | t = ⟪ record { factor = {!!} ; is-factor = {!!} } , {!!} ⟫ -- Dividable (gcd1 i0 (suc i0) (suc j) (suc (suc j))) (suc i0)
gcd-divable (suc zero) i0 zero j0 if jf if=0 jf=0 = ⟪ record { factor = i0 ; is-factor = gg3 } ,  record { factor = j0 ; is-factor = gg3 } ⟫
gcd-divable (suc (suc i)) i0 zero zero if jf if=0 jf=0 = ⟪ record { factor = 1 ; is-factor = gg1 } ,  record { factor = factor if ; is-factor = gg4 } ⟫
   where
    gg4 :  factor if * i0  + 0 ≡ zero
    gg4 with  m*n≡0⇒m≡0∨n≡0 (factor if) (  m+n≡0⇒m≡0 (factor if * i0) (is-factor if))
    ... | inj₁ x = begin
      factor if * i0 + 0 ≡⟨ +-comm _ 0 ⟩
      factor if * i0  ≡⟨ cong (λ k → k * i0) x  ⟩
      0 ∎   where open ≡-Reasoning
    ... | inj₂ y = begin
      factor if * i0 + 0 ≡⟨ +-comm _ 0 ⟩
      factor if * i0  ≡⟨ cong (λ k → factor if * k) y  ⟩
      factor if * 0  ≡⟨ *-comm (factor if) 0  ⟩
      0 ∎   where open ≡-Reasoning
gcd-divable (suc (suc i)) i0 zero (suc j0) if jf if=0 jf=0 with gcd-divable (suc i) (suc (suc i)) j0 (suc j0) {!!} {!!} refl refl
... | t = ⟪ {!!} , {!!} ⟫
gcd-divable (suc zero) i0 (suc j) j0 if jf if=0 jf=0 =  
     gcd-divable zero i0 j j0 record {  factor = factor if ; is-factor = gg4 ; remain = j - zero }
                              record {  factor = factor jf ; is-factor = gg5 ; remain = zero - j  } refl refl where
    gg4 : factor if * i0 + (j - zero) ≡ j0
    gg4 = begin
      factor if * i0 + (j - zero)  ≡⟨  cong ( λ k → factor if * i0 + k) (sym if=0) ⟩
      factor if * i0 + remain if ≡⟨ is-factor if   ⟩
      j0 ∎   where open ≡-Reasoning  
    gg5 : factor jf * j0 + (zero - j) ≡ i0
    gg5 = begin
      factor jf * j0 + (zero - j)  ≡⟨  cong ( λ k → factor jf * j0 + k) (sym jf=0) ⟩
      factor jf * j0 + remain jf ≡⟨ is-factor jf   ⟩
      i0 ∎   where open ≡-Reasoning  
gcd-divable (suc (suc i)) i0 (suc j) j0 if jf if=0 jf=0 = 
     gcd-divable (suc i) i0 j j0 record {  factor = factor if ; is-factor = gg4 ; remain = j - suc i }
                              record {  factor = factor jf ; is-factor = gg5 ; remain = suc i - j } refl refl where
    gg4 : factor if * i0 + (j - suc i ) ≡ j0
    gg4 = begin
      factor if * i0 + ( j - suc i ) ≡⟨ cong ( λ k → factor if * i0 + k ) (sym if=0) ⟩ 
      factor if * i0 + remain if  ≡⟨ is-factor if   ⟩
      j0 ∎   where open ≡-Reasoning  
    gg5 : factor jf * j0 + (suc i - j) ≡ i0
    gg5 = begin
      factor jf * j0 + ( suc i - j ) ≡⟨ cong ( λ k → factor jf * j0 + k ) (sym jf=0) ⟩  
      factor jf * j0 + remain jf  ≡⟨ is-factor jf   ⟩
      i0 ∎   where open ≡-Reasoning  

gcd22 : ( i i0 o o0 : ℕ ) → gcd1 (suc i) i0 (suc o) o0 ≡ gcd1 i i0 o o0
gcd22 zero i0 zero o0 = refl
gcd22 zero i0 (suc o) o0 = refl
gcd22 (suc i) i0 zero o0 = refl
gcd22 (suc i) i0 (suc o) o0 = refl 

gcd20 : (i : ℕ) → gcd i 0 ≡ i
gcd20 zero = refl
gcd20 (suc i) = gcd201 (suc i) where
    gcd201 : (i : ℕ ) → gcd1 i i zero zero ≡ i
    gcd201 zero = refl
    gcd201 (suc zero) = refl
    gcd201 (suc (suc i)) = refl

gcdmm : (n m : ℕ) → gcd1 n m n m ≡ m
gcdmm zero m with <-cmp m m
... | tri< a ¬b ¬c = refl
... | tri≈ ¬a refl ¬c = refl
... | tri> ¬a ¬b c = refl
gcdmm (suc n) m  = subst (λ k → k ≡ m) (sym (gcd22 n m n m )) (gcdmm n m )

gcdsym2 : (i j : ℕ) → gcd1 zero i zero j ≡ gcd1 zero j zero i
gcdsym2 i j with <-cmp i j | <-cmp j i
... | tri< a ¬b ¬c | tri< a₁ ¬b₁ ¬c₁ = ⊥-elim (nat-<> a a₁) 
... | tri< a ¬b ¬c | tri≈ ¬a b ¬c₁ = ⊥-elim (nat-≡< (sym b) a) 
... | tri< a ¬b ¬c | tri> ¬a ¬b₁ c = refl
... | tri≈ ¬a b ¬c | tri< a ¬b ¬c₁ = ⊥-elim (nat-≡< (sym b) a) 
... | tri≈ ¬a refl ¬c | tri≈ ¬a₁ refl ¬c₁ = refl
... | tri≈ ¬a b ¬c | tri> ¬a₁ ¬b c = ⊥-elim (nat-≡< b c) 
... | tri> ¬a ¬b c | tri< a ¬b₁ ¬c = refl
... | tri> ¬a ¬b c | tri≈ ¬a₁ b ¬c = ⊥-elim (nat-≡< b c) 
... | tri> ¬a ¬b c | tri> ¬a₁ ¬b₁ c₁ = ⊥-elim (nat-<> c c₁) 
gcdsym1 : ( i i0 j j0 : ℕ ) → gcd1 i i0 j j0 ≡ gcd1 j j0 i i0
gcdsym1 zero zero zero zero = refl
gcdsym1 zero zero zero (suc j0) = refl
gcdsym1 zero (suc i0) zero zero = refl
gcdsym1 zero (suc i0) zero (suc j0) = gcdsym2 (suc i0) (suc j0)
gcdsym1 zero zero (suc zero) j0 = refl
gcdsym1 zero zero (suc (suc j)) j0 = refl
gcdsym1 zero (suc i0) (suc zero) j0 = refl
gcdsym1 zero (suc i0) (suc (suc j)) j0 = gcdsym1 i0 (suc i0) (suc j) (suc (suc j))
gcdsym1 (suc zero) i0 zero j0 = refl
gcdsym1 (suc (suc i)) i0 zero zero = refl
gcdsym1 (suc (suc i)) i0 zero (suc j0) = gcdsym1 (suc i) (suc (suc i))j0 (suc j0) 
gcdsym1 (suc i) i0 (suc j) j0 = subst₂ (λ j k → j ≡ k ) (sym (gcd22 i _ _ _)) (sym (gcd22 j _ _ _)) (gcdsym1 i i0 j j0 )

gcdsym : { n m : ℕ} → gcd n m ≡ gcd m n
gcdsym {n} {m} = gcdsym1 n n m m 

gcd11 : ( i  : ℕ ) → gcd i i ≡ i
gcd11 i = gcdmm i i 

gcd203 : (i : ℕ) → gcd1 (suc i) (suc i) i i ≡ 1
gcd203 zero = refl
gcd203 (suc i) = gcd205 (suc i) where
   gcd205 : (j : ℕ) → gcd1 (suc j) (suc (suc i)) j (suc i) ≡ 1
   gcd205 zero = refl
   gcd205 (suc j) = subst (λ k → k ≡ 1) (gcd22 (suc j)  (suc (suc i)) j (suc i)) (gcd205 j)

gcd204 : (i : ℕ) → gcd1 1 1 i i ≡ 1
gcd204 zero = refl
gcd204 (suc zero) = refl
gcd204 (suc (suc zero)) = refl
gcd204 (suc (suc (suc i))) = gcd204 (suc (suc i)) 

gcd2 : ( i j : ℕ ) → gcd (i + j) j ≡ gcd i j
gcd2 i j = gcd200 i i j j refl refl where
       gcd202 : (i j1 : ℕ) → (i + suc j1) ≡ suc (i + j1)
       gcd202 zero j1 = refl
       gcd202 (suc i) j1 = cong suc (gcd202 i j1)
       gcd201 : (i i0 j j0 j1 : ℕ) → gcd1 (i + j1) (i0 + suc j) j1 j0 ≡ gcd1 i (i0 + suc j) zero j0
       gcd201 i i0 j j0 zero = subst (λ k → gcd1 k (i0 + suc j) zero j0 ≡ gcd1 i (i0 + suc j) zero j0 ) (+-comm zero i) refl
       gcd201 i i0 j j0 (suc j1) = begin
          gcd1 (i + suc j1)   (i0 + suc j) (suc j1) j0 ≡⟨ cong (λ k → gcd1 k (i0 + suc j) (suc j1) j0 ) (gcd202 i j1) ⟩
          gcd1 (suc (i + j1)) (i0 + suc j) (suc j1) j0 ≡⟨ gcd22 (i + j1) (i0 + suc j) j1 j0 ⟩
          gcd1 (i + j1) (i0 + suc j) j1 j0 ≡⟨ gcd201 i i0 j j0 j1 ⟩
          gcd1 i (i0 + suc j) zero j0 ∎ where open ≡-Reasoning
       gcd200 : (i i0 j j0 : ℕ) → i ≡ i0 → j ≡ j0 → gcd1 (i + j) (i0 + j) j j0 ≡ gcd1 i i j0 j0
       gcd200 i .i zero .0 refl refl = subst (λ k → gcd1 k k zero zero ≡ gcd1 i i zero zero ) (+-comm zero i) refl 
       gcd200 (suc (suc i)) i0 (suc j) (suc j0) i=i0 j=j0 = gcd201 (suc (suc i)) i0 j (suc j0) (suc j)
       gcd200 zero zero (suc zero) .1 i=i0 refl = refl
       gcd200 zero zero (suc (suc j)) .(suc (suc j)) i=i0 refl = begin
          gcd1 (zero + suc (suc j)) (zero + suc (suc j)) (suc (suc j)) (suc (suc j)) ≡⟨ gcdmm (suc (suc j)) (suc (suc j)) ⟩
          suc (suc j) ≡⟨ sym (gcd20 (suc (suc j))) ⟩
          gcd1 zero zero (suc (suc j)) (suc (suc j)) ∎ where open ≡-Reasoning
       gcd200 zero (suc i0) (suc j) .(suc j) () refl
       gcd200 (suc zero) .1 (suc j) .(suc j) refl refl = begin
          gcd1 (1 + suc j) (1 + suc j) (suc j) (suc j) ≡⟨ gcd203 (suc j) ⟩
          1 ≡⟨ sym ( gcd204 (suc j)) ⟩
          gcd1 1 1 (suc j) (suc j) ∎ where open ≡-Reasoning
       gcd200 (suc (suc i)) i0 (suc j) zero i=i0 ()


gcdmul+1 : ( m n : ℕ ) → gcd (m * n + 1) n ≡ 1
gcdmul+1 zero n = gcd204 n
gcdmul+1 (suc m) n = begin
      gcd (suc m * n + 1) n ≡⟨⟩
      gcd (n + m * n + 1) n ≡⟨ cong (λ k → gcd k n ) (begin
         n + m * n + 1 ≡⟨ cong (λ k → k + 1) (+-comm n _) ⟩
         m * n + n + 1 ≡⟨ +-assoc (m * n) _ _ ⟩
         m * n + (n + 1)  ≡⟨ cong (λ k → m * n + k) (+-comm n _) ⟩
         m * n + (1 + n)  ≡⟨ sym ( +-assoc (m * n) _ _ ) ⟩
         m * n + 1 + n ∎ 
       ) ⟩
      gcd (m * n + 1 + n) n ≡⟨ gcd2 (m * n + 1) n ⟩
      gcd (m * n + 1) n ≡⟨ gcdmul+1 m n ⟩
      1 ∎ where open ≡-Reasoning

div+1 : { i k : ℕ } → k > 1 →  Dividable k i →  ¬ Dividable k (suc i)  
div+1 {i} {k} k>1 d d1 = div1 k>1 div+11 where
   div+11 : Dividable k 1
   div+11 = subst (λ g → Dividable k g) (minus+y-y {1} {i} ) ( proj2 (div-div k>1 d d1  ) )

gcd>0 : ( i j : ℕ ) → 0 < i → 0 < j → 0 < gcd i j  
gcd>0 i j 0<i 0<j = gcd>01 i i j j 0<i 0<j where
     gcd>01 : ( i i0 j j0 : ℕ ) → 0 < i0 → 0 < j0  → gcd1 i i0 j j0 > 0
     gcd>01 zero i0 zero j0 0<i 0<j with <-cmp i0 j0
     ... | tri< a ¬b ¬c = 0<i
     ... | tri≈ ¬a refl ¬c = 0<i
     ... | tri> ¬a ¬b c = 0<j
     gcd>01 zero i0 (suc zero) j0 0<i 0<j = s≤s z≤n
     gcd>01 zero zero (suc (suc j)) j0 0<i 0<j = 0<j 
     gcd>01 zero (suc i0) (suc (suc j)) j0 0<i 0<j = gcd>01 i0 (suc i0) (suc j) (suc (suc j)) 0<i (s≤s z≤n) -- 0 < suc (suc j)
     gcd>01 (suc zero) i0 zero j0 0<i 0<j =  s≤s z≤n
     gcd>01 (suc (suc i)) i0 zero zero 0<i 0<j = 0<i 
     gcd>01 (suc (suc i)) i0 zero (suc j0) 0<i 0<j = gcd>01 (suc i) (suc (suc i))  j0 (suc j0) (s≤s z≤n) 0<j 
     gcd>01 (suc i) i0 (suc j) j0 0<i 0<j = subst (λ k → 0 < k ) (sym (gcd033 i i0 j j0 )) (gcd>01 i i0 j j0 0<i 0<j ) where
         gcd033 : (i i0 j j0  : ℕ) → gcd1 (suc i) i0 (suc j) j0 ≡  gcd1 i i0 j j0
         gcd033 zero zero zero zero = refl
         gcd033 zero zero (suc j) zero = refl
         gcd033 (suc i) zero j zero = refl
         gcd033 zero zero zero (suc j0) = refl
         gcd033 (suc i) zero zero (suc j0) = refl
         gcd033 zero zero (suc j) (suc j0) = refl
         gcd033 (suc i) zero (suc j) (suc j0) = refl
         gcd033 zero (suc i0) j j0 = refl
         gcd033 (suc i) (suc i0) j j0 = refl