{-# OPTIONS --without-K --safe --no-universe-polymorphism --no-sized-types --no-guardedness --no-subtyping #-} module Agda.Builtin.Nat where open import Agda.Builtin.Bool data Nat : Set where zero : Nat suc : (n : Nat) Nat {-# BUILTIN NATURAL Nat #-} infix 4 _==_ _<_ infixl 6 _+_ _-_ infixl 7 _*_ _+_ : Nat Nat Nat zero + m = m suc n + m = suc (n + m) {-# BUILTIN NATPLUS _+_ #-} _-_ : Nat Nat Nat n - zero = n zero - suc m = zero suc n - suc m = n - m {-# BUILTIN NATMINUS _-_ #-} _*_ : Nat Nat Nat zero * m = zero suc n * m = m + n * m {-# BUILTIN NATTIMES _*_ #-} _==_ : Nat Nat Bool zero == zero = true suc n == suc m = n == m _ == _ = false {-# BUILTIN NATEQUALS _==_ #-} _<_ : Nat Nat Bool _ < zero = false zero < suc _ = true suc n < suc m = n < m {-# BUILTIN NATLESS _<_ #-} -- Helper function div-helper for Euclidean division. --------------------------------------------------------------------------- -- -- div-helper computes n / 1+m via iteration on n. -- -- n div (suc m) = div-helper 0 m n m -- -- The state of the iterator has two accumulator variables: -- -- k: The quotient, returned once n=0. Initialized to 0. -- -- j: A counter, initialized to the divisor m, decreased on each iteration step. -- Once it reaches 0, the quotient k is increased and j reset to m, -- starting the next countdown. -- -- Under the precondition j ≤ m, the invariant is -- -- div-helper k m n j = k + (n + m - j) div (1 + m) div-helper : (k m n j : Nat) Nat div-helper k m zero j = k div-helper k m (suc n) zero = div-helper (suc k) m n m div-helper k m (suc n) (suc j) = div-helper k m n j {-# BUILTIN NATDIVSUCAUX div-helper #-} -- Proof of the invariant by induction on n. -- -- clause 1: div-helper k m 0 j -- = k by definition -- = k + (0 + m - j) div (1 + m) since m - j < 1 + m -- -- clause 2: div-helper k m (1 + n) 0 -- = div-helper (1 + k) m n m by definition -- = 1 + k + (n + m - m) div (1 + m) by induction hypothesis -- = 1 + k + n div (1 + m) by simplification -- = k + (n + (1 + m)) div (1 + m) by expansion -- = k + (1 + n + m - 0) div (1 + m) by expansion -- -- clause 3: div-helper k m (1 + n) (1 + j) -- = div-helper k m n j by definition -- = k + (n + m - j) div (1 + m) by induction hypothesis -- = k + ((1 + n) + m - (1 + j)) div (1 + m) by expansion -- -- Q.e.d. -- Helper function mod-helper for the remainder computation. --------------------------------------------------------------------------- -- -- (Analogous to div-helper.) -- -- mod-helper computes n % 1+m via iteration on n. -- -- n mod (suc m) = mod-helper 0 m n m -- -- The invariant is: -- -- m = k + j ==> mod-helper k m n j = (n + k) mod (1 + m). mod-helper : (k m n j : Nat) Nat mod-helper k m zero j = k mod-helper k m (suc n) zero = mod-helper 0 m n m mod-helper k m (suc n) (suc j) = mod-helper (suc k) m n j {-# BUILTIN NATMODSUCAUX mod-helper #-} -- Proof of the invariant by induction on n. -- -- clause 1: mod-helper k m 0 j -- = k by definition -- = (0 + k) mod (1 + m) since m = k + j, thus k < m -- -- clause 2: mod-helper k m (1 + n) 0 -- = mod-helper 0 m n m by definition -- = (n + 0) mod (1 + m) by induction hypothesis -- = (n + (1 + m)) mod (1 + m) by expansion -- = (1 + n) + k) mod (1 + m) since k = m (as l = 0) -- -- clause 3: mod-helper k m (1 + n) (1 + j) -- = mod-helper (1 + k) m n j by definition -- = (n + (1 + k)) mod (1 + m) by induction hypothesis -- = ((1 + n) + k) mod (1 + m) by commutativity -- -- Q.e.d.