module Data.Nat.Base where
import Level using (zero)
open import Function using (_∘_)
open import Relation.Binary
open import Relation.Binary.Core
open import Relation.Binary.PropositionalEquality.Core
import Relation.Binary.PropositionalEquality.TrustMe as TrustMe
open import Relation.Nullary using (¬_; Dec; yes; no)
infix 4 _≤_ _<_ _≥_ _>_ _≰_ _≮_ _≱_ _≯_
data ℕ : Set where
zero : ℕ
suc : (n : ℕ) → ℕ
data _≤_ : Rel ℕ Level.zero where
z≤n : ∀ {n} → zero ≤ n
s≤s : ∀ {m n} (m≤n : m ≤ n) → suc m ≤ suc n
{-# BUILTIN NATURAL ℕ #-}
infixl 6 _+_ _∸_
infixl 7 _*_
_+_ : ℕ → ℕ → ℕ
zero + n = n
suc m + n = suc (m + n)
{-# BUILTIN NATPLUS _+_ #-}
_∸_ : ℕ → ℕ → ℕ
m ∸ zero = m
zero ∸ suc n = zero
suc m ∸ suc n = m ∸ n
{-# BUILTIN NATMINUS _∸_ #-}
_*_ : ℕ → ℕ → ℕ
zero * n = zero
suc m * n = n + m * n
{-# BUILTIN NATTIMES _*_ #-}
_<_ : Rel ℕ Level.zero
m < n = suc m ≤ n
_≥_ : Rel ℕ Level.zero
m ≥ n = n ≤ m
_>_ : Rel ℕ Level.zero
m > n = n < m
_≰_ : Rel ℕ Level.zero
a ≰ b = ¬ a ≤ b
_≮_ : Rel ℕ Level.zero
a ≮ b = ¬ a < b
_≱_ : Rel ℕ Level.zero
a ≱ b = ¬ a ≥ b
_≯_ : Rel ℕ Level.zero
a ≯ b = ¬ a > b
infix 4 _≤′_ _<′_ _≥′_ _>′_
data _≤′_ (m : ℕ) : ℕ → Set where
≤′-refl : m ≤′ m
≤′-step : ∀ {n} (m≤′n : m ≤′ n) → m ≤′ suc n
_<′_ : Rel ℕ Level.zero
m <′ n = suc m ≤′ n
_≥′_ : Rel ℕ Level.zero
m ≥′ n = n ≤′ m
_>′_ : Rel ℕ Level.zero
m >′ n = n <′ m
record _≤″_ (m n : ℕ) : Set where
constructor less-than-or-equal
field
{k} : ℕ
proof : m + k ≡ n
infix 4 _≤″_ _<″_ _≥″_ _>″_
_<″_ : Rel ℕ Level.zero
m <″ n = suc m ≤″ n
_≥″_ : Rel ℕ Level.zero
m ≥″ n = n ≤″ m
_>″_ : Rel ℕ Level.zero
m >″ n = n <″ m
erase : ∀ {m n} → m ≤″ n → m ≤″ n
erase (less-than-or-equal eq) = less-than-or-equal (TrustMe.erase eq)
fold : {a : Set} → a → (a → a) → ℕ → a
fold z s zero = z
fold z s (suc n) = s (fold z s n)
module GeneralisedArithmetic {a : Set} (0# : a) (1+ : a → a) where
add : ℕ → a → a
add n z = fold z 1+ n
mul : (+ : a → a → a) → (ℕ → a → a)
mul _+_ n x = fold 0# (λ s → x + s) n
pred : ℕ → ℕ
pred zero = zero
pred (suc n) = n
infixl 7 _⊓_
infixl 6 _+⋎_ _⊔_
_+⋎_ : ℕ → ℕ → ℕ
zero +⋎ n = n
suc m +⋎ n = suc (n +⋎ m)
_⊔_ : ℕ → ℕ → ℕ
zero ⊔ n = n
suc m ⊔ zero = suc m
suc m ⊔ suc n = suc (m ⊔ n)
_⊓_ : ℕ → ℕ → ℕ
zero ⊓ n = zero
suc m ⊓ zero = zero
suc m ⊓ suc n = suc (m ⊓ n)
⌊_/2⌋ : ℕ → ℕ
⌊ 0 /2⌋ = 0
⌊ 1 /2⌋ = 0
⌊ suc (suc n) /2⌋ = suc ⌊ n /2⌋
⌈_/2⌉ : ℕ → ℕ
⌈ n /2⌉ = ⌊ suc n /2⌋
infix 4 _≟_ _≤?_
_≟_ : Decidable {A = ℕ} _≡_
zero ≟ zero = yes refl
suc m ≟ suc n with m ≟ n
suc m ≟ suc .m | yes refl = yes refl
suc m ≟ suc n | no prf = no (prf ∘ (λ p → subst (λ x → m ≡ pred x) p refl))
zero ≟ suc n = no λ()
suc m ≟ zero = no λ()
≤-pred : ∀ {m n} → suc m ≤ suc n → m ≤ n
≤-pred (s≤s m≤n) = m≤n
_≤?_ : Decidable _≤_
zero ≤? _ = yes z≤n
suc m ≤? zero = no λ()
suc m ≤? suc n with m ≤? n
... | yes m≤n = yes (s≤s m≤n)
... | no m≰n = no (m≰n ∘ ≤-pred)
data Ordering : Rel ℕ Level.zero where
less : ∀ m k → Ordering m (suc (m + k))
equal : ∀ m → Ordering m m
greater : ∀ m k → Ordering (suc (m + k)) m
compare : ∀ m n → Ordering m n
compare zero zero = equal zero
compare (suc m) zero = greater zero m
compare zero (suc n) = less zero n
compare (suc m) (suc n) with compare m n
compare (suc .m) (suc .(suc m + k)) | less m k = less (suc m) k
compare (suc .m) (suc .m) | equal m = equal (suc m)
compare (suc .(suc m + k)) (suc .m) | greater m k = greater (suc m) k