{-# OPTIONS --type-in-type
#-}
open import NeilPrelude
open import Nat
open import NatProps
open import Recursion
module NatOrd where
infix 3 _≤ℕ_ _<ℕ_
infix 8 _<=ℕ_
_<=ℕ_ : ℕ → ℕ → Bool
O <=ℕ _ = true
(S _) <=ℕ O = false
S m <=ℕ S n = m <=ℕ n
data _<ℕ_ : ℕ → ℕ → Set where
<O : {n : ℕ} → O <ℕ S n
<S : {m n : ℕ} → m <ℕ n → S m <ℕ S n
<ℕ-trans : Transitive _<ℕ_
<ℕ-trans <O (<S _) = <O
<ℕ-trans (<S p) (<S q) = <S (<ℕ-trans p q)
≮O : {n : ℕ} → Not (n <ℕ O)
≮O ()
O≠S : {n : ℕ} → O ≢ S n
O≠S ()
S≠O : {n : ℕ} → S n ≢ O
S≠O ()
<ℕ-injS : {m n : ℕ} → S m <ℕ S n → m <ℕ n
<ℕ-injS (<S p) = p
<ℕ-trich : Trichotomous {ℕ} _<ℕ_
<ℕ-trich {O} {O} = inl (refl , ≮O , ≮O)
<ℕ-trich {O} {S m} = inrl (O≠S , <O , ≮O)
<ℕ-trich {S n} {O} = inrr (S≠O , ≮O , <O)
<ℕ-trich {S n} {S m} with <ℕ-trich {n} {m}
<ℕ-trich {S n} {S m} | inl (eq , mn , nm) = inl (cong S eq , mn ∘ <ℕ-injS , nm ∘ <ℕ-injS)
<ℕ-trich {S n} {S m} | inr (inl (eq , mn , nm)) = inrl (eq ∘ S-inj , <S mn , nm ∘ <ℕ-injS)
<ℕ-trich {S n} {S m} | inr (inr (eq , mn , nm)) = inrr (eq ∘ S-inj , mn ∘ <ℕ-injS , <S nm)
import StrictTotalOrder
open StrictTotalOrder _<ℕ_ <ℕ-trans <ℕ-trich public
_≤ℕ_ : Rel ℕ
_≤ℕ_ = _≤_
≤ℕ-antisymℕ : Antisymmetric _≤ℕ_
≤ℕ-antisymℕ = antisymmetric
≤ℕ-trans : Transitive _≤ℕ_
≤ℕ-trans = ≤-trans
≤ℕ-total : Total _≤ℕ_
≤ℕ-total = totality
≤ℕ-injS : {m n : ℕ} → S m ≤ S n → m ≤ n
≤ℕ-injS (inl (<S p)) = inl p
≤ℕ-injS (inr refl) = ≤-refl
≤O : {n : ℕ} → O ≤ n
≤O {O} = ≤-refl
≤O {S _} = inl <O
≤S : {m n : ℕ} → m ≤ n → S m ≤ S n
≤S (inl p) = inl (<S p)
≤S (inr refl) = ≤-refl
1≤Sn : {n : ℕ} → 1 ≤ S n
1≤Sn = ≤S ≤O
n<S' : (n : ℕ) → n < S n
n<S' = natrec <O <S
n<S : {n : ℕ} → n < S n
n<S {n} = n<S' n
S≤n : {n : ℕ} → Not (S n ≤ n)
S≤n {O} (inl ())
S≤n {O} (inr ())
S≤n {S n} p = S≤n {n} (≤ℕ-injS p)
<S→≤ : {m n : ℕ} → m < S n → m ≤ n
<S→≤ <O = ≤O
<S→≤ .{_} {O} (<S ())
<S→≤ .{_} {S n} (<S p) = ≤S (<S→≤ p)
S≰O : {n : ℕ} → Not (S n ≤ O)
S≰O (inl ())
S≰O (inr ())
Compareℕ : ℕ → ℕ → Set
Compareℕ = OrdCompare
compareℕ : (m n : ℕ) → Compareℕ m n
compareℕ = compare
compareS : {m n : ℕ} → Compareℕ m n → Compareℕ (S m) (S n)
compareS refl = refl
compareS (less p) = less (<S p)
compareS (more p) = more (<S p)
Accℕ : ℕ → Set
Accℕ = Acc ℕ _<ℕ_
accℕAux : (m n : ℕ) → m < n → Accℕ m
accℕAux O n p = acc-init (λ m → λ ())
accℕAux .(S m) .(S n) (<S {m} {n} p) = acc (λ l lt → accℕAux l n (≤<-trans (<S→≤ lt) p))
accℕ : {n : ℕ} → Accℕ n
accℕ {n} = accℕAux n (S n) n<S
compareℕ⁺ : (m n : ℕ⁺) → Compareℕ (m -1) (n -1)
compareℕ⁺ (S m) (S n) = compare m n
safeMinus : (m n : ℕ) → n ≤ℕ m → ℕ
safeMinus m O p = m
safeMinus (S m) (S n) p = safeMinus m n (≤ℕ-injS p)
safeMinus O (S n) (inl ())
safeMinus O (S n) (inr ())
safeMinus⁺ : (m n : ℕ) → S n ≤ℕ m → ℕ⁺
safeMinus⁺ O O (inl ())
safeMinus⁺ O O (inr ())
safeMinus⁺ (S m) O p = S m
safeMinus⁺ O (S n) (inl ())
safeMinus⁺ O (S n) (inr ())
safeMinus⁺ (S m) (S n) p = safeMinus⁺ m n (≤ℕ-injS p)
Quotient = ℕ
Remainder = ℕ
private divminus : (m n : ℕ) → m ≥ n → n > O → Σ ℕ (\ k → k <ℕ m)
divminus ._ ._ (inr refl) <O = O , <O
divminus O .(S n) (inl ()) (<O {n})
divminus (S m) .1 (inl p) (<O {O}) = m , n<S
divminus (S m) .(S (S n)) (inl p) (<O {S n}) = second' (flip <-trans n<S) (divminus m (S n) (inl (<ℕ-injS p)) <O)
divide : ℕ → (d : ℕ) → d > O → Quotient × Remainder
divide n d gt = wfrec n divAux accℕ
where
divAux : (m : ℕ) → Accℕ m → ((z : ℕ) → z <ℕ m → Quotient × Remainder) → Quotient × Remainder
divAux O a f = O , O
divAux m a f with compareℕ m d
divAux .d a f | refl = 1 , O
divAux m a f | less p = O , m
divAux m a f | more p = (first S ∘ uncurry f ∘ divminus m d (inl p)) gt
div : ℕ → (n : ℕ) → n > O → Quotient
div m n = fst ∘ divide m n
_%_ : ℕ → (n : ℕ) → n > O → Remainder
_%_ m n = snd ∘ divide m n
half : ℕ → ℕ
half n = div n 2 <O