# Prelude.Nat

(-) : (m : Nat) -> (n : Nat) -> {auto smaller : LTE n m} -> Nat
  Fixity
    Left associative, precedence 8
record Additive

  A wrapper for Nat that specifies the semigroup and monoid implementations that use (+)

  GetAdditive : Nat -> Additive
  __pi_arg : (rec : Additive) -> Nat
data CmpNat : Nat -> Nat -> Type
  CmpLT : (y : Nat) -> CmpNat x (x + S y)
  CmpEQ : CmpNat x x
  CmpGT : (x : Nat) -> CmpNat (y + S x) y
GT : Nat -> Nat -> Type

  Strict greater than

GTE : Nat -> Nat -> Type

  Greater than or equal to

GetAdditive : Nat -> Additive
GetMultiplicative : Nat -> Multiplicative
data IsSucc : (n : Nat) -> Type

  Proof that `n` is not equal to Z

  ItIsSucc : IsSucc (S n)
LT : Nat -> Nat -> Type

  Strict less than

data LTE : (n : Nat) -> (m : Nat) -> Type

  Proofs that `n` is less than or equal to `m`

  n

    the smaller number

  m

    the larger number

  LTEZero : LTE 0 right

    Zero is the smallest Nat

  LTESucc : LTE left right -> LTE (S left) (S right)

    If n <= m, then n + 1 <= m + 1

LTESuccZeroFalse : (n : Nat) -> lte (S n) 0 = False
record Multiplicative

  A wrapper for Nat that specifies the semigroup and monoid implementations that use (*)

  GetMultiplicative : Nat -> Multiplicative
  __pi_arg : (rec : Multiplicative) -> Nat
data Nat : Type

  Natural numbers: unbounded, unsigned integers which can be pattern
  matched.

  Z : Nat

    Zero

  S : Nat -> Nat

    Successor

data NotBothZero : (n : Nat) -> (m : Nat) -> Type

  Proofs that `n` or `m` is not equal to Z

  LeftIsNotZero : NotBothZero (S n) m
  RightIsNotZero : NotBothZero n (S m)
SIsNotZ : (S x = 0) -> Void

  The proof that no successor of a natural number can be zero.

      modNatNZ 10 3 SIsNotZ

cmp : (x : Nat) -> (y : Nat) -> CmpNat x y
divCeil : Nat -> Nat -> Nat
divCeilNZ : Nat -> (y : Nat) -> Not (y = fromInteger 0) -> Nat
divNat : Nat -> Nat -> Nat
divNatNZ : Nat -> (y : Nat) -> Not (y = 0) -> Nat

  Division where the divisor is not zero.

      divNatNZ 100 2 SIsNotZ

eqSucc : (left : Nat) -> (right : Nat) -> (p : left = right) -> S left = S right

  S preserves equality

fact : Nat -> Nat

  Factorial function

fib : Nat -> Nat

  Fibonacci numbers

fromIntegerNat : Integer -> Nat

  Convert an Integer to a Nat, mapping negative numbers to 0

fromLteSucc : LTE (S m) (S n) -> LTE m n

  If two numbers are ordered, their predecessors are too

gcd : (a : Nat) -> (b : Nat) -> {auto ok : NotBothZero a b} -> Nat
gt : Nat -> Nat -> Bool

  Boolean test than one Nat is strictly greater than another

gte : Nat -> Nat -> Bool

  Boolean test than one Nat is greater than or equal to another

hyper : Nat -> Nat -> Nat -> Nat
ifThenElseMultMultLeft : (cond : Bool) -> (left : Nat) -> (t : Nat) -> (f : Nat) -> left * ifThenElse cond (Delay t) (Delay f) = ifThenElse cond (Delay (left * t)) (Delay (left * f))
ifThenElseMultMultRight : (cond : Bool) -> (right : Nat) -> (t : Nat) -> (f : Nat) -> ifThenElse cond (Delay t) (Delay f) * right = ifThenElse cond (Delay (t * right)) (Delay (f * right))
ifThenElsePlusPlusLeft : (cond : Bool) -> (left : Nat) -> (t : Nat) -> (f : Nat) -> left + ifThenElse cond (Delay t) (Delay f) = ifThenElse cond (Delay (left + t)) (Delay (left + f))
ifThenElsePlusPlusRight : (cond : Bool) -> (right : Nat) -> (t : Nat) -> (f : Nat) -> ifThenElse cond (Delay t) (Delay f) + right = ifThenElse cond (Delay (t + right)) (Delay (f + right))
ifThenElseSuccSucc : (cond : Bool) -> (t : Nat) -> (f : Nat) -> S (ifThenElse cond (Delay t) (Delay f)) = ifThenElse cond (Delay (S t)) (Delay (S f))
isItSucc : (n : Nat) -> Dec (IsSucc n)

  A decision procedure for `IsSucc`

isLTE : (m : Nat) -> (n : Nat) -> Dec (LTE m n)

  A decision procedure for `LTE`

isSucc : Nat -> Bool
isZero : Nat -> Bool
lcm : Nat -> Nat -> Nat
log2 : Nat -> Nat
log2NZ : (x : Nat) -> Not (x = 0) -> Nat
lt : Nat -> Nat -> Bool

  Boolean test than one Nat is strictly less than another

lte : Nat -> Nat -> Bool

  Boolean test than one Nat is less than or equal to another

lteAddRight : (n : Nat) -> LTE n (plus n m)
lteNTrue : (n : Nat) -> lte n n = True
lteRefl : LTE n n

  `LTE` is reflexive.

lteSuccLeft : LTE (S n) m -> LTE n m

  n + 1 < m implies n < m

lteSuccRight : LTE n m -> LTE n (S m)

  n < m implies n < m + 1

lteTransitive : LTE n m -> LTE m p -> LTE n p

  `LTE` is transitive

maximum : Nat -> Nat -> Nat

  Find the greatest of two natural numbers

maximumAssociative : (l : Nat) -> (c : Nat) -> (r : Nat) -> maximum l (maximum c r) = maximum (maximum l c) r
maximumCommutative : (l : Nat) -> (r : Nat) -> maximum l r = maximum r l
maximumIdempotent : (n : Nat) -> maximum n n = n
maximumSuccSucc : (left : Nat) -> (right : Nat) -> S (maximum left right) = maximum (S left) (S right)
maximumZeroNLeft : (left : Nat) -> maximum left 0 = left
maximumZeroNRight : (right : Nat) -> maximum 0 right = right
minimum : Nat -> Nat -> Nat

  Find the least of two natural numbers

minimumAssociative : (l : Nat) -> (c : Nat) -> (r : Nat) -> minimum l (minimum c r) = minimum (minimum l c) r
minimumCommutative : (l : Nat) -> (r : Nat) -> minimum l r = minimum r l
minimumIdempotent : (n : Nat) -> minimum n n = n
minimumSuccSucc : (left : Nat) -> (right : Nat) -> minimum (S left) (S right) = S (minimum left right)
minimumZeroZeroLeft : (left : Nat) -> minimum left (fromInteger 0) = 0
minimumZeroZeroRight : (right : Nat) -> minimum (fromInteger 0) right = 0
minus : Nat -> Nat -> Nat

  Subtract natural numbers. If the second number is larger than the first, return 0.

minusMinusMinusPlus : (left : Nat) -> (centre : Nat) -> (right : Nat) -> minus (minus left centre) right = minus left (centre + right)
minusOneSuccN : (n : Nat) -> 1 = minus (S n) n
minusPlusZero : (n : Nat) -> (m : Nat) -> minus n (n + m) = 0
minusSuccOne : (n : Nat) -> minus (S n) (fromInteger 1) = n
minusSuccPred : (left : Nat) -> (right : Nat) -> minus left (S right) = pred (minus left right)
minusSuccSucc : (left : Nat) -> (right : Nat) -> minus (S left) (S right) = minus left right
minusZeroLeft : (right : Nat) -> minus (fromInteger 0) right = 0
minusZeroN : (n : Nat) -> 0 = minus n n
minusZeroRight : (left : Nat) -> minus left (fromInteger 0) = left
modNat : Nat -> Nat -> Nat
modNatNZ : Nat -> (y : Nat) -> Not (y = 0) -> Nat

  Modulus function where the divisor is not zero.

      modNatNZ 100 2 SIsNotZ

mult : Nat -> Nat -> Nat

  Multiply natural numbers

multAssociative : (left : Nat) -> (centre : Nat) -> (right : Nat) -> left * (centre * right) = left * centre * right
multCommutative : (left : Nat) -> (right : Nat) -> left * right = right * left
multDistributesOverMinusLeft : (left : Nat) -> (centre : Nat) -> (right : Nat) -> minus left centre * right = minus (left * right) (centre * right)
multDistributesOverMinusRight : (left : Nat) -> (centre : Nat) -> (right : Nat) -> left * minus centre right = minus (left * centre) (left * right)
multDistributesOverPlusLeft : (left : Nat) -> (centre : Nat) -> (right : Nat) -> (left + centre) * right = left * right + centre * right
multDistributesOverPlusRight : (left : Nat) -> (centre : Nat) -> (right : Nat) -> left * (centre + right) = left * centre + left * right
multLeftSuccPlus : (left : Nat) -> (right : Nat) -> S left * right = right + left * right
multOneLeftNeutral : (right : Nat) -> fromInteger 1 * right = right
multOneRightNeutral : (left : Nat) -> left * fromInteger 1 = left
multPowerPowerPlus : (base : Nat) -> (exp : Nat) -> (exp' : Nat) -> power base exp * power base exp' = power base (exp + exp')
multRightSuccPlus : (left : Nat) -> (right : Nat) -> left * S right = left + left * right
multZeroLeftZero : (right : Nat) -> 0 * right = 0
multZeroRightZero : (left : Nat) -> left * 0 = 0
notLTImpliesGTE : Not (LT a b) -> GTE a b

  If a number is not less than another, it is greater than or equal to it

plus : (n : Nat) -> (m : Nat) -> Nat

  Add two natural numbers.

  n

    the number to case-split on

  m

    the other number

plusAssociative : (left : Nat) -> (centre : Nat) -> (right : Nat) -> left + (centre + right) = left + centre + right
plusCommutative : (left : Nat) -> (right : Nat) -> left + right = right + left
plusConstantLeft : (left : Nat) -> (right : Nat) -> (c : Nat) -> (p : left = right) -> c + left = c + right
plusConstantRight : (left : Nat) -> (right : Nat) -> (c : Nat) -> (p : left = right) -> left + c = right + c
plusLeftCancel : (left : Nat) -> (right : Nat) -> (right' : Nat) -> (p : left + right = left + right') -> right = right'
plusLeftLeftRightZero : (left : Nat) -> (right : Nat) -> (p : left + right = left) -> right = 0
plusMinusLeftCancel : (left : Nat) -> (right : Nat) -> (right' : Nat) -> minus (left + right) (left + right') = minus right right'
plusOneSucc : (right : Nat) -> fromInteger 1 + right = S right
plusRightCancel : (left : Nat) -> (left' : Nat) -> (right : Nat) -> (p : left + right = left' + right) -> left = left'
plusSuccRightSucc : (left : Nat) -> (right : Nat) -> S (left + right) = left + S right
plusZeroLeftNeutral : (right : Nat) -> fromInteger 0 + right = right
plusZeroRightNeutral : (left : Nat) -> left + fromInteger 0 = left
power : Nat -> Nat -> Nat

  Exponentiation of natural numbers

powerOneNeutral : (base : Nat) -> power base (fromInteger 1) = base
powerOneSuccOne : (exp : Nat) -> power (fromInteger 1) exp = 1
powerPowerMultPower : (base : Nat) -> (exp : Nat) -> (exp' : Nat) -> power (power base exp) exp' = power base (exp * exp')
powerSuccPowerLeft : (base : Nat) -> (exp : Nat) -> power base (S exp) = base * power base exp
powerSuccSuccMult : (base : Nat) -> power base (fromInteger 2) = mult base base
powerZeroOne : (base : Nat) -> power base (fromInteger 0) = 1
pred : Nat -> Nat

  The predecessor of a natural number. `pred Z` is `Z`.

predSucc : (n : Nat) -> pred (S n) = n
sucMaxL : (l : Nat) -> maximum (S l) l = S l
sucMaxR : (l : Nat) -> maximum l (S l) = S l
sucMinL : (l : Nat) -> minimum (S l) l = l
sucMinR : (l : Nat) -> minimum l (S l) = l
succInjective : (left : Nat) -> (right : Nat) -> (p : S left = S right) -> left = right

  S is injective

succNotLTEzero : Not (LTE (S m) 0)

  A successor is never less than or equal zero

toIntNat : Nat -> Int

  Cast Nat to Int
  Note that this can overflow

toIntegerNat : Nat -> Integer

  Convert a Nat to an Integer