{- Order as an Indexed Data Type, as done in Agda stdlib and 1Lab -}
module Cubical.Data.Fast.Int.Order where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Foundations.Equiv
open import Cubical.Foundations.Univalence

open import Cubical.Relation.Binary
open import Cubical.Relation.Nullary

open import Cubical.Data.Bool hiding (_≟_ ; _≤_ ; _≥_ ; isProp≤)
open import Cubical.Data.Empty as ⊥
open import Cubical.Data.Sigma
open import Cubical.Data.Sum

open import Cubical.Data.Nat as ℕ
open import Cubical.Data.Nat.Order as ℕ using ()
open import Cubical.Data.Nat.Order.Inductive as ℕ
open import Cubical.Data.Fast.Int as ℤ

private
  variable
    m n o s : ℤ
    k l : ℕ

infix 4 _≤_ _<_ _≥_ _>_

data _≤_ : ℤ → ℤ → Type where
  pos≤pos       : ∀ {x y} → x ℕ.≤ᵗ y → pos x    ≤ pos y
  negsuc≤negsuc : ∀ {x y} → x ℕ.≥ᵗ y → negsuc x ≤ negsuc y
  negsuc≤pos    : ∀ {x y}            → negsuc x ≤ pos y

data _<_ : ℤ → ℤ → Type where
  pos<pos       : ∀ {x y} → x ℕ.<ᵗ y → pos x    < pos y
  negsuc<negsuc : ∀ {x y} → x ℕ.>ᵗ y → negsuc x < negsuc y
  negsuc<pos    : ∀ {x y}            → negsuc x < pos y

_≥_ _>_ : ℤ → ℤ → Type
_≥_ = flip _≤_
_>_ = flip _<_

¬pos≤negsuc : ∀ {x y} → ¬ pos x ≤ negsuc y
¬pos≤negsuc ()

¬pos<negsuc : ∀ {x y} → ¬ pos x < negsuc y
¬pos<negsuc ()

¬≤ℕ→¬pos≤pos : ∀ {x y} → ¬ (x ℕ.≤ᵗ y) → ¬ pos x ≤ pos y
¬≤ℕ→¬pos≤pos ¬p (pos≤pos p) = ¬p p

¬<ℕ→¬pos<pos : ∀ {x y} → ¬ (x ℕ.<ᵗ y) → ¬ pos x < pos y
¬<ℕ→¬pos<pos ¬p (pos<pos p) = ¬p p

¬≥ℕ→¬negsuc≤negsuc : ∀ {x y} → ¬ (x ℕ.≥ᵗ y) → ¬ negsuc x ≤ negsuc y
¬≥ℕ→¬negsuc≤negsuc ¬p (negsuc≤negsuc p) = ¬p p

¬>ℕ→¬negsuc<negsuc : ∀ {x y} → ¬ (x ℕ.>ᵗ y) → ¬ negsuc x < negsuc y
¬>ℕ→¬negsuc<negsuc ¬p (negsuc<negsuc p) = ¬p p

{-# DISPLAY negsuc≤negsuc {x} {y} _ = negsuc x ≤ negsuc y #-}
{-# DISPLAY pos≤pos       {x} {y} _ =    pos x ≤ pos y #-}
{-# DISPLAY negsuc≤pos    {x} {y}   = negsuc x ≤ pos y #-}

{-# DISPLAY negsuc<negsuc {x} {y} _ = negsuc x < negsuc y #-}
{-# DISPLAY pos<pos       {x} {y} _ =    pos x < pos y #-}
{-# DISPLAY negsuc<pos    {x} {y}   = negsuc x < pos y #-}

{-# DISPLAY ¬≤ℕ→¬pos≤pos       {x} {y} _ = ¬ pos x    ≤ pos y    #-}
{-# DISPLAY ¬≥ℕ→¬negsuc≤negsuc {x} {y} _ = ¬ negsuc x ≤ negsuc y #-}
{-# DISPLAY ¬pos≤negsuc        {x} {y}   = ¬    pos x ≤ negsuc y #-}

{-# DISPLAY ¬<ℕ→¬pos<pos       {x} {y} _ = ¬ pos x    < pos y    #-}
{-# DISPLAY ¬>ℕ→¬negsuc<negsuc {x} {y} _ = ¬ negsuc x < negsuc y #-}
{-# DISPLAY ¬pos<negsuc        {x} {y}   = ¬    pos x < negsuc y #-}

isProp≤ : isProp (m ≤ n)
isProp≤ (pos≤pos p)       (pos≤pos q)       = cong pos≤pos (isPropBool→Type p q)
isProp≤  negsuc≤pos        negsuc≤pos       = refl
isProp≤ (negsuc≤negsuc p) (negsuc≤negsuc q) = cong negsuc≤negsuc (isPropBool→Type p q)

isProp< : isProp (m < n)
isProp< (pos<pos p)       (pos<pos q)       = cong pos<pos (isPropBool→Type p q)
isProp<  negsuc<pos        negsuc<pos       = refl
isProp< (negsuc<negsuc p) (negsuc<negsuc q) = cong negsuc<negsuc (isPropBool→Type p q)

_≤?_ ≤Dec : ∀ m n → Dec (m ≤ n)
pos m    ≤? pos n    = mapDec pos≤pos ¬≤ℕ→¬pos≤pos DecBool→Type
pos m    ≤? negsuc n = no ¬pos≤negsuc
negsuc m ≤? pos n    = yes negsuc≤pos
negsuc m ≤? negsuc n = mapDec negsuc≤negsuc ¬≥ℕ→¬negsuc≤negsuc DecBool→Type

≤Dec = _≤?_

_<?_ <Dec : ∀ m n → Dec (m < n)
pos m    <? pos n    = mapDec pos<pos ¬<ℕ→¬pos<pos DecBool→Type
pos m    <? negsuc n = no ¬pos<negsuc
negsuc m <? pos n    = yes negsuc<pos
negsuc m <? negsuc n = mapDec negsuc<negsuc ¬>ℕ→¬negsuc<negsuc DecBool→Type

<Dec = _<?_

≤Stable : ∀ m n → Stable (m ≤ n)
≤Stable m n = Dec→Stable (m ≤? n)

<Stable : ∀ m n → Stable (m < n)
<Stable m n = Dec→Stable (m <? n)

-- auxilary functions to speed up proofs, relying on the decidability of order

recompute< : (m < n) → (m < n)
recompute< p = decRec (idfun _) (λ _ → p) (_ <? _)

recompute≤ : (m ≤ n) → (m ≤ n)
recompute≤ p = decRec (idfun _) (λ _ → p) (_ ≤? _)

recompute¬< : ¬ (m < n) → ¬ (m < n)
recompute¬< p = decRec (λ _ → p) (idfun _) (_ <? _)

recompute¬≤ : ¬ (m ≤ n) → ¬ (m ≤ n)
recompute¬≤ p = decRec (λ _ → p) (idfun _) (_ ≤? _)

-- properties of _<_ and _≤_

zero-≤pos : 0 ≤ pos l
zero-≤pos = pos≤pos tt

zero-<possuc : 0 < pos (suc l)
zero-<possuc = pos<pos tt

negsuc≤-zero : negsuc k ≤ 0
negsuc≤-zero = negsuc≤pos

negsuc<-zero : negsuc k < 0
negsuc<-zero = negsuc<pos

¬-pos<-zero : ¬ (pos k) < 0
¬-pos<-zero (pos<pos ())

suc-≤-suc : m ≤ n → sucℤ m ≤ sucℤ n
suc-≤-suc {pos m}          {pos n}          (pos≤pos p)       = pos≤pos p
suc-≤-suc {negsuc zero}    {pos n}           negsuc≤pos       = pos≤pos tt
suc-≤-suc {negsuc (suc m)} {pos n}           negsuc≤pos       = negsuc≤pos
suc-≤-suc {negsuc zero}    {negsuc zero}    (negsuc≤negsuc p) = pos≤pos tt
suc-≤-suc {negsuc (suc m)} {negsuc zero}    (negsuc≤negsuc p) = negsuc≤pos
suc-≤-suc {negsuc (suc m)} {negsuc (suc n)} (negsuc≤negsuc p) = negsuc≤negsuc p

suc-<-suc : m < n → sucℤ m < sucℤ n
suc-<-suc {pos m}          {pos n}          (pos<pos p)       = pos<pos p
suc-<-suc {negsuc zero}    {pos n}           negsuc<pos       = pos<pos tt
suc-<-suc {negsuc (suc m)} {pos n}           negsuc<pos       = negsuc<pos
suc-<-suc {negsuc (suc m)} {negsuc zero}    (negsuc<negsuc p) = negsuc<pos
suc-<-suc {negsuc (suc m)} {negsuc (suc n)} (negsuc<negsuc p) = negsuc<negsuc p

pred-≤-pred : sucℤ m ≤ sucℤ n → m ≤ n
pred-≤-pred {pos m}          {pos n}          (pos≤pos p)       = pos≤pos p
pred-≤-pred {pos zero}       {negsuc zero}    (pos≤pos ())
pred-≤-pred {negsuc m}       {pos n}           _                = negsuc≤pos
pred-≤-pred {negsuc zero}    {negsuc zero}    (pos≤pos p)       = negsuc≤negsuc tt
pred-≤-pred {negsuc (suc m)} {negsuc zero}     negsuc≤pos       = negsuc≤negsuc tt
pred-≤-pred {negsuc (suc m)} {negsuc (suc n)} (negsuc≤negsuc p) = negsuc≤negsuc p

pred-<-pred : sucℤ m < sucℤ n → m < n
pred-<-pred {pos m}          {pos n}          (pos<pos p)       = pos<pos p
pred-<-pred {pos zero}       {negsuc zero}    (pos<pos ())
pred-<-pred {negsuc m}       {pos n}           _                = negsuc<pos
pred-<-pred {negsuc zero}    {negsuc zero}    (pos<pos ())
pred-<-pred {negsuc (suc m)} {negsuc zero}     negsuc<pos       = negsuc<negsuc tt
pred-<-pred {negsuc (suc m)} {negsuc (suc n)} (negsuc<negsuc p) = negsuc<negsuc p

predℤ-≤-predℤ : m ≤ n → predℤ m ≤ predℤ n
predℤ-≤-predℤ {pos zero}    {pos zero}    (pos≤pos p)       = negsuc≤negsuc tt
predℤ-≤-predℤ {pos zero}    {pos (suc n)} (pos≤pos p)       = negsuc≤pos
predℤ-≤-predℤ {pos (suc m)} {pos (suc n)} (pos≤pos p)       = pos≤pos p
predℤ-≤-predℤ {negsuc m}    {pos zero}     negsuc≤pos       = negsuc≤negsuc tt
predℤ-≤-predℤ {negsuc m}    {pos (suc n)}  negsuc≤pos       = negsuc≤pos
predℤ-≤-predℤ {negsuc m}    {negsuc n}    (negsuc≤negsuc p) = negsuc≤negsuc p

predℤ-<-predℤ : m < n → predℤ m < predℤ n
predℤ-<-predℤ {pos zero}    {pos (suc n)} (pos<pos p)       = negsuc<pos
predℤ-<-predℤ {pos (suc m)} {pos (suc n)} (pos<pos p)       = pos<pos p
predℤ-<-predℤ {negsuc m}    {pos zero}     negsuc<pos       = negsuc<negsuc tt
predℤ-<-predℤ {negsuc m}    {pos (suc n)}  negsuc<pos       = negsuc<pos
predℤ-<-predℤ {negsuc m}    {negsuc n}    (negsuc<negsuc p) = negsuc<negsuc p

pos≤pos→negsuc≥negsuc : pos k ≤ pos l → negsuc k ≥ negsuc l
pos≤pos→negsuc≥negsuc (pos≤pos p) = negsuc≤negsuc p

pos<pos→negsuc>negsuc : pos k < pos l → negsuc k > negsuc l
pos<pos→negsuc>negsuc (pos<pos p) = negsuc<negsuc p

negsuc≤negsuc→pos≥pos : negsuc k ≤ negsuc l → pos k ≥ pos l
negsuc≤negsuc→pos≥pos (negsuc≤negsuc p) = pos≤pos p

negsuc<negsuc→pos>pos : negsuc k < negsuc l → pos k > pos l
negsuc<negsuc→pos>pos (negsuc<negsuc p) = pos<pos p

pos≤pos→neg≥neg : pos k ≤ pos l → neg k ≥ neg l
pos≤pos→neg≥neg {zero}  {zero}  (pos≤pos p) = pos≤pos tt
pos≤pos→neg≥neg {zero}  {suc l} (pos≤pos p) = negsuc≤pos
pos≤pos→neg≥neg {suc k} {suc l} (pos≤pos p) = negsuc≤negsuc p

pos<pos→neg>neg : pos k < pos l → neg k > neg l
pos<pos→neg>neg {zero}  {suc l} (pos<pos p) = negsuc<pos
pos<pos→neg>neg {suc k} {suc l} (pos<pos p) = negsuc<negsuc p

<→suc≤ : m < n → sucℤ m ≤ n
<→suc≤ {pos m}          {pos n}    (pos<pos p)       = pos≤pos p
<→suc≤ {negsuc zero}    {pos n}     negsuc<pos       = pos≤pos tt
<→suc≤ {negsuc (suc m)} {pos n}     negsuc<pos       = negsuc≤pos
<→suc≤ {negsuc (suc m)} {negsuc n} (negsuc<negsuc p) = negsuc≤negsuc p

suc≤→< : sucℤ m ≤ n → m < n
suc≤→< {pos m}          {pos n}    (pos≤pos p)       = pos<pos p
suc≤→< {negsuc m}       {pos n}     _                = negsuc<pos
suc≤→< {negsuc (suc m)} {negsuc n} (negsuc≤negsuc p) = negsuc<negsuc p

<≃suc≤ : (m < n) ≃ (sucℤ m ≤ n)
<≃suc≤ = propBiimpl→Equiv isProp< isProp≤ <→suc≤ suc≤→<

<≡suc≤ : (m < n) ≡ (sucℤ m ≤ n)
<≡suc≤ = ua <≃suc≤

≤→<suc : m ≤ n → m < sucℤ n
≤→<suc {pos m}    {pos n}          (pos≤pos p)       = pos<pos p
≤→<suc {negsuc m} {pos n}           negsuc≤pos       = negsuc<pos
≤→<suc {negsuc m} {negsuc zero}    (negsuc≤negsuc p) = negsuc<pos
≤→<suc {negsuc m} {negsuc (suc n)} (negsuc≤negsuc p) = negsuc<negsuc p

<suc→≤ : m < sucℤ n → m ≤ n
<suc→≤ {pos m}          {pos n}          (pos<pos p)       = pos≤pos p
<suc→≤ {negsuc m}       {pos n}           negsuc<pos       = negsuc≤pos
<suc→≤ {pos m}          {negsuc zero}    (pos<pos ())
<suc→≤ {negsuc m}       {negsuc zero}     negsuc<pos       = negsuc≤negsuc tt
<suc→≤ {negsuc (suc m)} {negsuc (suc n)} (negsuc<negsuc p) = negsuc≤negsuc p

≤≃<suc : (m ≤ n) ≃ (m < sucℤ n)
≤≃<suc = propBiimpl→Equiv isProp≤ isProp< ≤→<suc <suc→≤

≤≡<suc : (m ≤ n) ≡ (m < sucℤ n)
≤≡<suc = ua ≤≃<suc

≤-+o : m ≤ n → m ℤ.+ o ≤ n ℤ.+ o
≤-+o = recompute≤ ∘ proof _ _ _ where
  proof : ∀ m n o → m ≤ n → m ℤ.+ o ≤ n ℤ.+ o
  proof m n (pos zero)       = subst2 _≤_ (sym (ℤ.+IdR m)) (sym (ℤ.+IdR n))
  proof m n (pos (suc k))    = subst2 _≤_
    (+sucℤ m _) (+sucℤ n _) ∘ suc-≤-suc ∘ proof m n (pos k)
  proof m n (negsuc zero)    = subst2 _≤_ (+negsuc0 m) (+negsuc0 n) ∘ predℤ-≤-predℤ
  proof m n (negsuc (suc k)) = subst2 _≤_
    (+predℤ m _) (+predℤ n _) ∘ predℤ-≤-predℤ ∘ proof m n (negsuc k)

<-+o : m < n → (m ℤ.+ o) < (n ℤ.+ o)
<-+o {m} {n} {o} = recompute< ∘ suc≤→< ∘ subst (_≤ _) (sym (sucℤ+ m o)) ∘ ≤-+o ∘ <→suc≤

≤SumRightPos : n ≤ pos k ℤ.+ n
≤SumRightPos {n} {k} = recompute≤ $ subst (_≤ pos k ℤ.+ n) (ℤ.+IdL n) (≤-+o {o = n} zero-≤pos)

<SumRightPosSuc : n < pos (suc k) ℤ.+ n
<SumRightPosSuc {n} {k} = recompute< $ subst (_< pos (suc k) ℤ.+ n) (ℤ.+IdL n) (<-+o {o = n} zero-<possuc)

≤-o+ : m ≤ n → o ℤ.+ m ≤ o ℤ.+ n
≤-o+ {m} {n} {o} = recompute≤ ∘ subst2 (_≤_) (+Comm m o) (+Comm n o) ∘ ≤-+o

<-o+ : m < n → (o ℤ.+ m) < (o ℤ.+ n)
<-o+ {m} {n} {o} = recompute< ∘ subst2 (_<_) (+Comm m o) (+Comm n o) ∘ <-+o

≤SumLeftPos : n ≤ n ℤ.+ pos k
≤SumLeftPos {n} {k} = recompute≤ $ subst (n ≤_) (+Comm (pos k) n) ≤SumRightPos

<SumLeftPosSuc : n < n ℤ.+ pos (suc k)
<SumLeftPosSuc {n} {k} = recompute< $ subst (n <_) (+Comm (pos (suc k)) n) <SumRightPosSuc

isRefl≤ : m ≤ m
isRefl≤ = recompute≤ $ proof _ where
  proof : ∀ m → m ≤ m
  proof (pos zero)       = pos≤pos tt
  proof (pos (suc n))    = suc-≤-suc (proof (pos n))
  proof (negsuc zero)    = negsuc≤negsuc tt
  proof (negsuc (suc n)) = predℤ-≤-predℤ (proof (negsuc n))

≤-suc : m ≤ n → m ≤ sucℤ n
≤-suc = recompute≤ ∘ proof _ _ where
  proof : ∀ m n → m ≤ n → m ≤ sucℤ n
  proof (pos zero)       (pos zero)             (pos≤pos p)       = pos≤pos tt
  proof (pos zero)       (pos (suc n))          (pos≤pos p)       = pos≤pos tt
  proof (pos (suc m))    (pos (suc n))          (pos≤pos p)       =
    suc-≤-suc (proof (pos m) (pos n) (pos≤pos p))
  proof (negsuc m)       (pos n)                 negsuc≤pos       = negsuc≤pos
  proof (negsuc zero)    (negsuc zero)          (negsuc≤negsuc p) = negsuc≤pos
  proof (negsuc (suc m)) (negsuc zero)          (negsuc≤negsuc p) = negsuc≤pos
  proof (negsuc (suc m)) (negsuc (suc zero))    (negsuc≤negsuc p) = negsuc≤negsuc tt
  proof (negsuc (suc m)) (negsuc (suc (suc n))) (negsuc≤negsuc p) =
    predℤ-≤-predℤ (proof (negsuc m) (negsuc (suc n)) (negsuc≤negsuc p))

suc-< : sucℤ m < n → m < n
suc-< = suc≤→< ∘ pred-≤-pred ∘ ≤-suc ∘ <→suc≤

≤-sucℤ : n ≤ sucℤ n
≤-sucℤ = ≤-suc isRefl≤

<-sucℤ : n < sucℤ n
<-sucℤ = ≤→<suc isRefl≤

isTrans≤ : m ≤ n → n ≤ o → m ≤ o
isTrans≤ = (recompute≤ ∘_) ∘ proof _ _ _ where
  proof : ∀ m n o → m ≤ n → n ≤ o → m ≤ o
  proof (pos zero)       (pos zero)       (pos zero)       (pos≤pos p)       (pos≤pos q)       =
    pos≤pos tt
  proof (pos zero)       (pos zero)       (pos (suc o))    (pos≤pos p)       (pos≤pos q)       =
    pos≤pos tt
  proof (pos zero)       (pos (suc n))    (pos (suc o))    (pos≤pos p)       (pos≤pos q)       =
    pos≤pos tt
  proof (pos (suc m))    (pos (suc n))    (pos (suc o))    (pos≤pos p)       (pos≤pos q)       =
    suc-≤-suc (proof (pos m) (pos n) (pos o) (pos≤pos p) (pos≤pos q))
  proof (negsuc m)       (pos n)          (pos o)           negsuc≤pos       (pos≤pos q)       =
    negsuc≤pos
  proof (negsuc m)       (negsuc n)       (pos o)          (negsuc≤negsuc p)  negsuc≤pos       =
    negsuc≤pos
  proof (negsuc zero)    (negsuc zero)    (negsuc zero)    (negsuc≤negsuc p) (negsuc≤negsuc q) =
    negsuc≤negsuc tt
  proof (negsuc (suc m)) (negsuc zero)    (negsuc zero)    (negsuc≤negsuc p) (negsuc≤negsuc q) =
    negsuc≤negsuc tt
  proof (negsuc (suc m)) (negsuc (suc n)) (negsuc zero)    (negsuc≤negsuc p) (negsuc≤negsuc q) =
    negsuc≤negsuc tt
  proof (negsuc (suc m)) (negsuc (suc n)) (negsuc (suc o)) (negsuc≤negsuc p) (negsuc≤negsuc q) =
    predℤ-≤-predℤ (proof (negsuc m) (negsuc n) (negsuc o) (negsuc≤negsuc p) (negsuc≤negsuc q))

isTrans< : m < n → n < o → m < o
isTrans< = (recompute< ∘_) ∘ proof _ _ _ where
  proof : ∀ m n o → m < n → n < o → m < o
  proof (pos zero)       (pos (suc n))    (pos (suc o))    (pos<pos p)       (pos<pos q)       =
    pos<pos tt
  proof (pos (suc m))    (pos (suc n))    (pos (suc o))    (pos<pos p)       (pos<pos q)       =
    suc-<-suc (proof (pos m) (pos n) (pos o) (pos<pos p) (pos<pos q))
  proof (negsuc m)       (pos n)          (pos o)           negsuc<pos       (pos<pos q)       =
    negsuc<pos
  proof (negsuc m)       (negsuc n)       (pos o)          (negsuc<negsuc p)  negsuc<pos       =
    negsuc<pos
  proof (negsuc (suc m)) (negsuc (suc n)) (negsuc zero)    (negsuc<negsuc p) (negsuc<negsuc q) =
    negsuc<negsuc tt
  proof (negsuc (suc m)) (negsuc (suc n)) (negsuc (suc o)) (negsuc<negsuc p) (negsuc<negsuc q) =
    predℤ-<-predℤ (proof (negsuc m) (negsuc n) (negsuc o) (negsuc<negsuc p) (negsuc<negsuc q))

-- this proof will not normalize quickly when m and n are the same large number
isAntisym≤ : m ≤ n → n ≤ m → m ≡ n
isAntisym≤ {pos zero}       {pos zero}       (pos≤pos p)       (pos≤pos q)       = refl
isAntisym≤ {pos (suc m)}    {pos (suc n)}    (pos≤pos p)       (pos≤pos q)       =
  cong sucℤ (isAntisym≤ (pos≤pos p) (pos≤pos q))
isAntisym≤ {negsuc zero}    {negsuc zero}    (negsuc≤negsuc p) (negsuc≤negsuc q) = refl
isAntisym≤ {negsuc (suc m)} {negsuc (suc n)} (negsuc≤negsuc p) (negsuc≤negsuc q) =
  cong predℤ (isAntisym≤ (negsuc≤negsuc p) (negsuc≤negsuc q))

≤Monotone+ : m ≤ n → o ≤ s → m ℤ.+ o ≤ n ℤ.+ s
≤Monotone+ {n = n} p = isTrans≤ (≤-+o p) ∘ ≤-o+ {o = n}

<Monotone+ : m < n → o < s → m ℤ.+ o < n ℤ.+ s
<Monotone+ {n = n} p = isTrans< (<-+o p) ∘ <-o+ {o = n}

≤-o+-cancel : o ℤ.+ m ≤ o ℤ.+ n → m ≤ n
≤-o+-cancel {o} {m} {n} = recompute≤ ∘ subst2 _≤_
  (ℤ.+Assoc (ℤ.- o) o m ∙∙ cong (ℤ._+ m) (ℤ.-Cancel' o) ∙∙ ℤ.+IdL m)
  (ℤ.+Assoc (ℤ.- o) o n ∙∙ cong (ℤ._+ n) (ℤ.-Cancel' o) ∙∙ ℤ.+IdL n)
  ∘ ≤-o+ {o = ℤ.- o}

<-o+-cancel : o ℤ.+ m < o ℤ.+ n → m < n
<-o+-cancel {o} {m} {n} = recompute< ∘ subst2 _<_
  (ℤ.+Assoc (ℤ.- o) o m ∙∙ cong (ℤ._+ m) (ℤ.-Cancel' o) ∙∙ ℤ.+IdL m)
  (ℤ.+Assoc (ℤ.- o) o n ∙∙ cong (ℤ._+ n) (ℤ.-Cancel' o) ∙∙ ℤ.+IdL n)
  ∘ <-o+ {o = ℤ.- o}

≤-+o-cancel : m ℤ.+ o ≤ n ℤ.+ o → m ≤ n
≤-+o-cancel {m} {o} {n} = ≤-o+-cancel {o = o} ∘ subst2 _≤_ (ℤ.+Comm m o) (ℤ.+Comm n o)

<-+o-cancel : m ℤ.+ o < n ℤ.+ o → m < n
<-+o-cancel {m} {o} {n} = <-o+-cancel {o = o} ∘ subst2 _<_ (ℤ.+Comm m o) (ℤ.+Comm n o)

≤-+pos-trans : m ℤ.+ pos k ≤ n → m ≤ n
≤-+pos-trans = isTrans≤ ≤SumLeftPos

≤-pos+-trans : pos k ℤ.+ m ≤ n → m ≤ n
≤-pos+-trans = isTrans≤ ≤SumRightPos

≤-·o : m ≤ n → m ℤ.· pos k ≤ n ℤ.· pos k
≤-·o = recompute≤ ∘ proof _ _ _ where
  proof : ∀ m n k → m ≤ n → m ℤ.· pos k ≤ n ℤ.· pos k
  proof m n zero    _ = subst2 _≤_ (sym (ℤ.·AnnihilR m)) (sym (ℤ.·AnnihilR n)) zero-≤pos
  proof (pos zero)       (pos zero)       (suc k) (pos≤pos p)       = zero-≤pos
  proof (pos zero)       (pos (suc n))    (suc k) (pos≤pos p)       = zero-≤pos
  proof (pos (suc m))    (pos (suc n))    (suc k) (pos≤pos p)       =
    ≤-o+ {o = pos (suc k)} (proof (pos m) (pos n) (suc k) (pos≤pos p))
  proof (negsuc m)       (pos n)          (suc k)  negsuc≤pos       = negsuc≤pos
  proof (negsuc zero)    (negsuc zero)    (suc k) (negsuc≤negsuc p) = isRefl≤
  proof (negsuc (suc m)) (negsuc zero)    (suc k) (negsuc≤negsuc p) =
    pos≤pos→negsuc≥negsuc
      (subst (_≤ pos k ℤ.+ pos (suc m ℕ.· suc k)) (sym (ℤ.+IdR (pos k))) ≤SumLeftPos)
  proof (negsuc (suc m)) (negsuc (suc n)) (suc k) (negsuc≤negsuc p) =
    subst2 _≤_
      (sym (predℤ· (negsuc m) (pos (suc k)))) (sym (predℤ· (negsuc n) (pos (suc k))))
      (≤-o+ {o = negsuc k} (proof (negsuc m) (negsuc n) (suc k) (negsuc≤negsuc p)))

0≤o→≤-·o : 0 ≤ o → m ≤ n → m ℤ.· o ≤ n ℤ.· o
0≤o→≤-·o (pos≤pos p) = ≤-·o

<-·o : m < n → m ℤ.· pos (suc k) < n ℤ.· pos (suc k)
<-·o = recompute< ∘ proof _ _ _ where
  proof : ∀ m n k → m < n → m ℤ.· pos (suc k) < n ℤ.· pos (suc k)
  proof (pos zero)       (pos (suc n))    k (pos<pos p)       = zero-<possuc
  proof (pos (suc m))    (pos (suc n))    k (pos<pos p)       =
    <-o+ {o = pos (suc k)} (proof (pos m) (pos n) k (pos<pos p))
  proof (negsuc m)       (pos n)          k  negsuc<pos       = negsuc<pos
  proof (negsuc (suc m)) (negsuc zero)    k (negsuc<negsuc p) =
    pos<pos→negsuc>negsuc
      (subst (_< pos k ℤ.+ pos (suc m ℕ.· suc k)) (sym (ℤ.+IdR (pos k))) <SumLeftPosSuc)
  proof (negsuc (suc m)) (negsuc (suc n)) k (negsuc<negsuc p) =
    subst2 _<_
      (sym (predℤ· (negsuc m) (pos (suc k)))) (sym (predℤ· (negsuc n) (pos (suc k))))
      (<-o+ {o = negsuc k} (proof (negsuc m) (negsuc n) k (negsuc<negsuc p)))

0<o→<-·o : 0 < o → m < n → m ℤ.· o < n ℤ.· o
0<o→<-·o {pos (suc k)} (pos<pos p) = <-·o

<-weaken : m < n → m ≤ n
<-weaken = <suc→≤ ∘ flip isTrans< <-sucℤ

isIrrefl< : ¬ m < m
isIrrefl< = recompute¬< $ proof _ where
  proof : ∀ m → ¬ m < m
  proof (pos (suc m))    (pos<pos p)       = proof (pos m)    (pos<pos p)
  proof (negsuc (suc m)) (negsuc<negsuc p) = proof (negsuc m) (negsuc<negsuc p)

pos≤0→≡0 : pos k ≤ 0 → pos k ≡ 0
pos≤0→≡0 {zero} (pos≤pos x) = refl

¬m+posk<m : ¬ m ℤ.+ pos k < m
¬m+posk<m {m} {k} = recompute¬< $ ¬-pos<-zero ∘ <-o+-cancel {m} ∘ subst (m ℤ.+ pos k <_) (sym (ℤ.+IdR m))

≤<-trans : o ≤ m → m < n → o < n
≤<-trans p = suc≤→< ∘ isTrans≤ (suc-≤-suc p) ∘ <→suc≤

<≤-trans : o < m → m ≤ n → o < n
<≤-trans = (suc≤→< ∘_) ∘ isTrans≤ ∘ <→suc≤

isAsym< : m < n → ¬ n ≤ m
isAsym< = recompute¬≤ ∘ proof _ _ where
  proof : ∀ m n → m < n → ¬ n ≤ m
  proof (pos (suc m))    (pos (suc n))    (pos<pos p)       (pos≤pos q) =
    proof (pos m) (pos n) (pos<pos p) (pos≤pos q)
  proof (negsuc (suc m)) (negsuc (suc n)) (negsuc<negsuc p) (negsuc≤negsuc q) =
    proof (negsuc m) (negsuc n) (negsuc<negsuc p) (negsuc≤negsuc q)

isAsym'< : ¬ m < n → n ≤ m
isAsym'< = recompute≤ ∘ proof _ _ where
  proof : ∀ m n → ¬ m < n → n ≤ m
  proof (pos m)          (pos zero)       ¬p = zero-≤pos
  proof (pos zero)       (pos (suc n))    ¬p = ⊥.rec (¬p zero-<possuc)
  proof (pos (suc m))    (pos (suc n))    ¬p =
    suc-≤-suc (proof (pos m) (pos n) (¬p ∘ suc-<-suc))
  proof (pos m)          (negsuc n)       ¬p = negsuc≤pos
  proof (negsuc m)       (pos n)          ¬p = ⊥.rec (¬p negsuc<pos)
  proof (negsuc zero)    (negsuc n)       ¬p = negsuc≤negsuc tt
  proof (negsuc (suc m)) (negsuc zero)    ¬p = ⊥.rec (¬p (negsuc<negsuc tt))
  proof (negsuc (suc m)) (negsuc (suc n)) ¬p =
    pred-≤-pred (proof (negsuc m) (negsuc n) (¬p ∘ pred-<-pred))

<-+pos-trans : m ℤ.+ pos k < n → m < n
<-+pos-trans = ≤<-trans ≤SumLeftPos

<-pos+-trans : pos k ℤ.+ m < n → m < n
<-pos+-trans = ≤<-trans ≤SumRightPos

<-+-≤ : m < n → o ≤ s → m ℤ.+ o < n ℤ.+ s
<-+-≤ {n = n} p = <≤-trans (<-+o p) ∘ ≤-o+ {o = n}

-Dist≤ : m ≤ n → (- n) ≤ (- m)
-Dist≤ {pos zero}    {pos zero}    (pos≤pos p)       = pos≤pos tt
-Dist≤ {pos zero}    {pos (suc n)} (pos≤pos p)       = negsuc≤pos
-Dist≤ {pos (suc m)} {pos (suc n)} (pos≤pos p)       = negsuc≤negsuc p
-Dist≤ {negsuc m}    {pos zero}     negsuc≤pos       = pos≤pos tt
-Dist≤ {negsuc m}    {pos (suc n)}  negsuc≤pos       = negsuc≤pos
-Dist≤ {negsuc m}    {negsuc n}    (negsuc≤negsuc p) = pos≤pos p

-Dist< : m < n → (- n) < (- m)
-Dist< {pos zero}    {pos (suc n)} (pos<pos p)       = negsuc<pos
-Dist< {pos (suc m)} {pos (suc n)} (pos<pos p)       = negsuc<negsuc p
-Dist< {negsuc m}    {pos zero}     negsuc<pos       = pos<pos tt
-Dist< {negsuc m}    {pos (suc n)}  negsuc<pos       = negsuc<pos
-Dist< {negsuc m}    {negsuc n}    (negsuc<negsuc p) = pos<pos p

-pos≤ : m - (pos k) ≤ m
-pos≤ {m} {k} = recompute≤ $ subst (m - pos k ≤_) (ℤ.+IdR m) (≤-o+ {o = m} (-Dist≤ zero-≤pos))

≤→0≤Δ : m ≤ n → 0 ≤ n ℤ.- m
≤→0≤Δ {m} {n} = recompute≤ ∘ subst (_≤ n ℤ.- m) (ℤ.-Cancel m) ∘ ≤-+o

<→0<Δ : m < n → 0 < n ℤ.- m
<→0<Δ {m} {n} = recompute< ∘ subst (_< n ℤ.- m) (ℤ.-Cancel m) ∘ <-+o

0≤Δ→≤ : 0 ≤ n ℤ.- m → m ≤ n
0≤Δ→≤ {n} {m} = recompute≤ ∘ subst2 _≤_ (ℤ.+IdL m) (ℤ.minusPlus m n) ∘ ≤-+o

0<Δ→< : 0 < n ℤ.- m → m < n
0<Δ→< {n} {m} = recompute< ∘ subst2 _<_ (ℤ.+IdL m) (ℤ.minusPlus m n) ∘ <-+o

0≤→abs≡id : 0 ≤ n → pos (abs n) ≡ n
0≤→abs≡id {pos n} _ = refl

0<→abs≡id : 0 < n → pos (abs n) ≡ n
0<→abs≡id {pos n} _ = refl

·suc≤0 : m ℤ.· (pos (suc k)) ≤ 0 → m ≤ 0
·suc≤0 {pos zero} (pos≤pos p) = pos≤pos tt
·suc≤0 {negsuc n}  _          = negsuc≤pos

·suc<0 : m ℤ.· (pos (suc k)) < 0 → m < 0
·suc<0 {pos n}    (pos<pos ())
·suc<0 {negsuc n}  _          = negsuc<pos

0≤·suc-cancel : 0 ≤ m ℤ.· pos (suc k) → 0 ≤ m
0≤·suc-cancel {pos n} _ = zero-≤pos

0<·suc-cancel : 0 < m ℤ.· pos (suc k) → 0 < m
0<·suc-cancel {pos (suc n)} (pos<pos p) = zero-<possuc

0≤suc·-cancel : 0 ≤ pos (suc k) ℤ.· m → 0 ≤ m
0≤suc·-cancel {m = pos n} _ = zero-≤pos

0<suc·-cancel : 0 < pos (suc k) ℤ.· m → 0 < m
0<suc·-cancel {k} {pos zero}    p = subst (0 <_) (ℤ.·AnnihilR (pos (suc k))) p
0<suc·-cancel {k} {pos (suc n)} _ = zero-<possuc

≤-·o-cancel : m ℤ.· pos (suc k) ≤ n ℤ.· pos (suc k) → m ≤ n
≤-·o-cancel {m} {n = n} = 0≤Δ→≤ ∘ 0≤·suc-cancel
  ∘ subst (0 ≤_) (cong (n ℤ.· _ ℤ.+_) (ℤ.-DistL· m _) ∙ sym (ℤ.·DistL+ n (ℤ.- m) _))
  ∘ ≤→0≤Δ

<-·o-cancel : m ℤ.· pos (suc k) < n ℤ.· pos (suc k) → m < n
<-·o-cancel {m} {n = n} = 0<Δ→< ∘ 0<·suc-cancel
  ∘ subst (0 <_) (cong (n ℤ.· _ ℤ.+_) (ℤ.-DistL· m _) ∙ sym (ℤ.·DistL+ n (ℤ.- m) _))
  ∘ <→0<Δ

0<o→≤-·o-cancel : 0 < o → m ℤ.· o ≤ n ℤ.· o → m ≤ n
0<o→≤-·o-cancel {pos (suc k)} (pos<pos p) = ≤-·o-cancel

0<o→<-·o-cancel : 0 < o → m ℤ.· o < n ℤ.· o → m < n
0<o→<-·o-cancel {pos (suc k)} (pos<pos p) = <-·o-cancel

≤-o·-cancel : (pos (suc k)) ℤ.· m ≤ (pos (suc k)) ℤ.· n → m ≤ n
≤-o·-cancel {m = m} {n} = ≤-·o-cancel ∘ subst2 _≤_ (ℤ.·Comm _ m) (ℤ.·Comm _ n)

<-o·-cancel : (pos (suc k)) ℤ.· m < (pos (suc k)) ℤ.· n → m < n
<-o·-cancel {m = m} {n} = <-·o-cancel ∘ subst2 _<_ (ℤ.·Comm _ m) (ℤ.·Comm _ n)

0<o→≤-o·-cancel : 0 < o → o ℤ.· m ≤ o ℤ.· n → m ≤ n
0<o→≤-o·-cancel {pos (suc k)} (pos<pos p) = ≤-o·-cancel

0<o→<-o·-cancel : 0 < o → o ℤ.· m < o ℤ.· n → m < n
0<o→<-o·-cancel {pos (suc k)} (pos<pos p) = <-o·-cancel

≤max : m ≤ ℤ.max m n
≤max {pos zero}       {pos n}          = zero-≤pos
≤max {pos (suc m)}    {pos zero}       = isRefl≤
≤max {pos (suc m)}    {pos (suc n)} with m ℕ.<ᵇ? n
... | no ¬p = isRefl≤
... | yes p = <-weaken (pos<pos p)
≤max {pos m}          {negsuc n}       = isRefl≤
≤max {negsuc m}       {pos n}          = negsuc≤pos
≤max {negsuc zero}    {negsuc n}       = isRefl≤
≤max {negsuc (suc m)} {negsuc zero}    = negsuc≤negsuc tt
≤max {negsuc (suc m)} {negsuc (suc n)} with m ℕ.<ᵇ? n
... | no ¬p = isAsym'< (¬>ℕ→¬negsuc<negsuc ¬p)
... | yes p = isRefl≤

-- this proof will not normalize quickly when m and n are the same large number
≤→max : m ≤ n → ℤ.max m n ≡ n
≤→max {pos zero}       {pos n}           p                = refl
≤→max {pos (suc m)}    {pos (suc n)}    (pos≤pos p) with m ℕ.<ᵇ? n
... | no ¬q = isAntisym≤ (pos≤pos p) (isAsym'< (¬<ℕ→¬pos<pos ¬q))
... | yes q = refl
≤→max {negsuc m}       {pos n}           _                = refl
≤→max {negsuc zero}    {negsuc zero}    (negsuc≤negsuc p) = refl
≤→max {negsuc (suc m)} {negsuc zero}    (negsuc≤negsuc p) = refl
≤→max {negsuc (suc m)} {negsuc (suc n)} (negsuc≤negsuc p) with m ℕ.<ᵇ? n
... | no ¬q = refl
... | yes q = isAntisym≤ (negsuc≤negsuc p) (<-weaken (negsuc<negsuc q))

min≤ : ℤ.min m n ≤ m
min≤ {pos zero}       {pos n}          = zero-≤pos
min≤ {pos (suc m)}    {pos zero}       = zero-≤pos
min≤ {pos (suc m)}    {pos (suc n)} with m ℕ.<ᵇ? n
... | no ¬p = isAsym'< (¬<ℕ→¬pos<pos ¬p)
... | yes p = isRefl≤
min≤ {pos m}          {negsuc n}       = negsuc≤pos
min≤ {negsuc m}       {pos n}          = isRefl≤
min≤ {negsuc zero}    {negsuc n}       = negsuc≤negsuc tt
min≤ {negsuc (suc m)} {negsuc zero}    = isRefl≤
min≤ {negsuc (suc m)} {negsuc (suc n)} with m ℕ.<ᵇ? n
... | no ¬p = isRefl≤
... | yes p = <-weaken (negsuc<negsuc p)

-- this proof will not normalize quickly when m and n are the same large number
≤→min : m ≤ n → ℤ.min m n ≡ m
≤→min {pos zero}       {pos n}           _                = refl
≤→min {pos (suc m)}    {pos (suc n)}    (pos≤pos p) with m ℕ.<ᵇ? n
... | no ¬q = isAntisym≤ (isAsym'< (¬<ℕ→¬pos<pos ¬q)) (pos≤pos p)
... | yes q = refl
≤→min {negsuc m}       {pos n}           _                = refl
≤→min {negsuc zero}    {negsuc zero}    (negsuc≤negsuc p) = refl
≤→min {negsuc (suc m)} {negsuc zero}    (negsuc≤negsuc p) = refl
≤→min {negsuc (suc m)} {negsuc (suc n)} (negsuc≤negsuc p) with m ℕ.<ᵇ? n
... | no ¬q = refl
... | yes q = isAntisym≤ (<-weaken (negsuc<negsuc q)) (negsuc≤negsuc p)

≤MonotoneMin : m ≤ n → o ≤ s → ℤ.min m o ≤ ℤ.min n s
≤MonotoneMin {m} {n} {o} {s} p q = recompute≤ $
  subst (_≤ ℤ.min n s) (
      sym (minAssoc n s (ℤ.min m o))
    ∙ cong (ℤ.min n) (
        minAssoc s m o ∙ cong (flip ℤ.min o) (ℤ.minComm s m) ∙ sym (minAssoc m s o))
    ∙ minAssoc n m (ℤ.min s o)
    ∙ cong₂ ℤ.min (ℤ.minComm n m ∙ ≤→min p)
      (ℤ.minComm s o ∙ ≤→min q))
    min≤

≤MonotoneMax : m ≤ n → o ≤ s → ℤ.max m o ≤ ℤ.max n s
≤MonotoneMax {m} {n} {o} {s} p q = recompute≤ $
  subst (ℤ.max m o ≤_) (
      sym (maxAssoc m o (ℤ.max n s)) ∙
      cong (ℤ.max m) (
        maxAssoc o n s
      ∙ cong (flip ℤ.max s) (ℤ.maxComm o n)
      ∙ sym (maxAssoc n o s)) ∙ maxAssoc m n (ℤ.max o s)
      ∙ cong₂ ℤ.max (≤→max p) (≤→max q))
    ≤max

0<+ : ∀ m n → 0 < m ℤ.+ n → (0 < m) ⊎ (0 < n)
0<+ (pos zero)    (pos (suc n)) (pos<pos p) = inr zero-<possuc
0<+ (pos (suc m)) (pos zero)    (pos<pos p) = inl zero-<possuc
0<+ (pos (suc m)) (pos (suc n)) (pos<pos p) = inr zero-<possuc -- alternative : inl zero-<possuc
0<+ (pos (suc m)) (negsuc n)     _          = inl zero-<possuc
0<+ (negsuc m)    (pos (suc n))  _          = inr zero-<possuc

Σℕ→≤ : Σ[ k ∈ ℕ ] m ℤ.+ pos k ≡ n → m ≤ n
Σℕ→≤ = recompute≤ ∘ uncurry λ _ → flip (subst (_ ≤_)) ≤SumLeftPos

Σℕ→< : Σ[ k ∈ ℕ ] m ℤ.+ pos (suc k) ≡ n → m < n
Σℕ→< = recompute< ∘ uncurry λ _ → flip (subst (_ <_)) <SumLeftPosSuc

-- the first component will normalize quickly, but not the path itself
≤→Σℕ : m ≤ n → Σ[ k ∈ ℕ ] m ℤ.+ pos k ≡ n
≤→Σℕ {m} {n} p .fst = abs (n - m)
≤→Σℕ {m} {n} p .snd =
  m ℤ.+ pos (abs (n - m)) ≡⟨ cong (m ℤ.+_) (0≤→abs≡id (≤→0≤Δ p)) ⟩
  m ℤ.+ (n - m)           ≡⟨ ℤ.+Comm m (n - m) ⟩
  (n - m) ℤ.+ m           ≡⟨ ℤ.minusPlus m n ⟩
  n                       ∎

-- the first component will normalize quickly, but not the path itself
<→Σℕ : m < n → Σ[ k ∈ ℕ ] m ℤ.+ pos (suc k) ≡ n
<→Σℕ {m} = map-snd (sym (+sucℤ m _) ∙∙ sucℤ+ m _ ∙∙_) ∘ ≤→Σℕ ∘ <→suc≤

data Trichotomy m n : Type where
  lt : m < n → Trichotomy m n
  eq : m ≡ n → Trichotomy m n
  gt : n < m → Trichotomy m n

Trichotomy-suc : Trichotomy m n → Trichotomy (sucℤ m) (sucℤ n)
Trichotomy-suc (lt m<n) = lt (suc-<-suc m<n)
Trichotomy-suc (eq m≡n) = eq (cong sucℤ m≡n)
Trichotomy-suc (gt n<m) = gt (suc-<-suc n<m)

Trichotomy-pred : Trichotomy (sucℤ m) (sucℤ n) → Trichotomy m n
Trichotomy-pred (lt m<n) = lt (pred-<-pred m<n)
Trichotomy-pred (eq m≡n) = eq (sym (predSuc _) ∙ cong predℤ m≡n ∙ predSuc _)
Trichotomy-pred (gt n<m) = gt (pred-<-pred n<m)

-- this proof will decide quickly among the cases `lt`, `gt`, `eq`
-- however, the path for the proof of the `eq` case will normalize slowly
_≟_ : ∀ m n → Trichotomy m n
pos m    ≟ pos n with m ℕ.≟ n
... | ℕ.lt p = lt $ recompute< $ pos<pos {m} {n} (ℕ.<→<ᵗ p)
... | ℕ.eq p = eq (cong pos p)
... | ℕ.gt p = gt $ recompute< $ pos<pos {n} {m} (ℕ.<→<ᵗ p)
pos m    ≟ negsuc n = gt negsuc<pos
negsuc m ≟ pos n    = lt negsuc<pos
negsuc m ≟ negsuc n with m ℕ.≟ n
... | ℕ.lt p = gt $ recompute< $ negsuc<negsuc {n} {m} (ℕ.<→<ᵗ p)
... | ℕ.eq p = eq (cong negsuc p)
... | ℕ.gt p = lt $ recompute< $ negsuc<negsuc {m} {n} (ℕ.<→<ᵗ p)

-- alternative proof
_≟'_ : ∀ m n → Trichotomy m n
pos zero       ≟' pos zero       = eq refl
pos zero       ≟' pos (suc n)    = lt zero-<possuc
pos (suc m)    ≟' pos zero       = gt zero-<possuc
pos (suc m)    ≟' pos (suc n)    = Trichotomy-suc (pos m ≟' pos n)
pos m          ≟' negsuc n       = gt negsuc<pos
negsuc m       ≟' pos n          = lt negsuc<pos
negsuc zero    ≟' negsuc zero    = eq refl
negsuc zero    ≟' negsuc (suc n) = gt (negsuc<negsuc tt)
negsuc (suc m) ≟' negsuc zero    = lt (negsuc<negsuc tt)
negsuc (suc m) ≟' negsuc (suc n) = Trichotomy-pred (negsuc m ≟' negsuc n)

-- raw comparisons, without the proof terms
compare : ℤ → ℤ → Ordering
compare m n with m ≟ n
... | lt _ = LT
... | eq _ = EQ
... | gt _ = GT

compare' : ℤ → ℤ → Ordering
compare' m n with m ≟' n
... | lt _ = LT
... | eq _ = EQ
... | gt _ = GT

private

  test₀ : compare -4294967296  4295967296 ≡ LT
  test₀ = refl

  test₁ : compare -4294967296 -4294967296 ≡ EQ
  test₁ = refl

  test₂ : compare -4294967296 -4295967296 ≡ GT
  test₂ = refl

  test₀' : compare' -4294967296  4295967296 ≡ LT
  test₀' = refl

  {- This would take much longer to typecheck:

  test₁' : compare' -4294967296 -4294967296 ≡ EQ
  test₁' = refl

  test₂' : compare' -4294967296 -4295967296 ≡ GT
  test₂' = refl

  -}