Library Stdlib.Arith.PeanoNat
Implementation of NAxiomsSig by nat
Operations over nat are defined in a separate module
When including property functors, inline t eq zero one two lt le succ
All operations are well-defined (trivial here since eq is Leibniz)
Bi-directional induction.
Recursion function
Remaining constants not defined in Stdlib.Init.Nat
NB: Aliasing
le is mandatory, since only a Definition can implement
an interface Parameter...
Basic specifications : pred add sub mul
Decidability of equality over nat.
Ternary comparison
With
nat, it would be easier to prove first
compare_spec,
then the properties below. But then we wouldn't be able to
benefit from functor
BoolOrderFacts
Some more advanced properties of comparison and orders,
including compare_spec and lt_irrefl and lt_eq_cases.
We can now derive all properties of basic functions and orders,
and use these properties for proving the specs of more advanced
functions.
The y <> 0 hypothesis is needed to fit in NAxiomsSig.
Lemma iter_swap_gen A B (
f:
A -> B) (
g:
A -> A) (
h:
B -> B) :
(forall a,
f (
g a)
= h (
f a)
) -> forall n a,
f (
iter n g a)
= iter n h (
f a).
Lemma iter_swap :
forall n (
A:
Type) (
f:
A -> A) (
x:
A),
iter n f (
f x)
= f (
iter n f x).
Lemma iter_succ :
forall n (
A:
Type) (
f:
A -> A) (
x:
A),
iter (
S n)
f x = f (
iter n f x).
Lemma iter_succ_r :
forall n (
A:
Type) (
f:
A -> A) (
x:
A),
iter (
S n)
f x = iter n f (
f x).
Lemma iter_add :
forall p q (
A:
Type) (
f:
A -> A) (
x:
A),
iter (
p+q)
f x = iter p f (
iter q f x).
Lemma iter_ind (
A:
Type) (
f:
A -> A) (
a:
A) (
P:
nat -> A -> Prop) :
P 0
a ->
(forall n a',
P n a' -> P (
S n) (
f a')
) ->
forall n,
P n (
iter n f a).
Lemma iter_rect (
A:
Type) (
f:
A -> A) (
a:
A) (
P:
nat -> A -> Type) :
P 0
a ->
(forall n a',
P n a' -> P (
S n) (
f a')
) ->
forall n,
P n (
iter n f a).
Lemma iter_invariant :
forall (
n:
nat) (
A:
Type) (
f:
A -> A) (
Inv:
A -> Prop),
(forall x:
A,
Inv x -> Inv (
f x)
) ->
forall x:
A,
Inv x -> Inv (
iter n f x).
Definition double_S :
forall n,
double (
S n)
= S (
S (
double n))
:=
fun n =>
add_succ_r (
S n)
n.
Definition double_add :
forall n m,
double (
n + m)
= double n + double m
:=
fun n m =>
add_shuffle1 n m n m.
Lemma double_twice :
forall n,
double n = 2
*n.
Module Type PrivateBitwiseSpec.
Parameter testbit_odd_0 :
forall a :
nat,
testbit (
add (
mul 2
a) 1) 0
= true.
Parameter testbit_even_0 :
forall a :
nat,
testbit (
mul 2
a) 0
= false.
Parameter testbit_odd_succ :
forall a n :
nat,
le 0
n ->
testbit (
add (
mul 2
a) 1) (
succ n)
= testbit a n.
Parameter testbit_even_succ :
forall a n :
nat,
le 0
n ->
testbit (
mul 2
a) (
succ n)
= testbit a n.
Parameter testbit_neg_r :
forall a n :
nat,
lt n 0
-> testbit a n = false.
Parameter shiftr_spec :
forall a n m :
nat,
le 0
m ->
testbit (
shiftr a n)
m = testbit a (
add m n).
Parameter shiftl_spec_high :
forall a n m :
nat,
le 0
m ->
le n m -> testbit (
shiftl a n)
m = testbit a (
sub m n).
Parameter shiftl_spec_low :
forall a n m :
nat,
lt m n -> testbit (
shiftl a n)
m = false.
Parameter land_spec :
forall a b n :
nat,
testbit (
land a b)
n = testbit a n && testbit b n.
Parameter lor_spec :
forall a b n :
nat,
testbit (
lor a b)
n = testbit a n || testbit b n.
Parameter ldiff_spec :
forall a b n :
nat,
testbit (
ldiff a b)
n = testbit a n && negb (
testbit b n).
Parameter lxor_spec :
forall a b n :
nat,
testbit (
lxor a b)
n = xorb (
testbit a n) (
testbit b n).
Parameter div2_spec :
forall a :
nat,
eq (
div2 a) (
shiftr a 1).
Parameter div2_double :
forall n,
div2 (2
*n)
= n.
Parameter div2_succ_double :
forall n,
div2 (
S (2
*n))
= n.
Parameter div2_bitwise :
forall op n a b,
div2 (
bitwise op (
S n)
a b)
= bitwise op n (
div2 a) (
div2 b).
Parameter odd_bitwise :
forall op n a b,
odd (
bitwise op (
S n)
a b)
= op (
odd a) (
odd b).
Parameter testbit_bitwise_1 :
forall op,
(forall b,
op false b = false) ->
forall n m a b,
a<=n ->
testbit (
bitwise op n a b)
m = op (
testbit a m) (
testbit b m).
Parameter testbit_bitwise_2 :
forall op,
op false false = false ->
forall n m a b,
a<=n -> b<=n ->
testbit (
bitwise op n a b)
m = op (
testbit a m) (
testbit b m).
End PrivateBitwiseSpec.
Module PrivateImplementsBitwiseSpec :
PrivateBitwiseSpec.
Lemma div2_double n :
div2 (2
*n)
= n.
Lemma div2_succ_double n :
div2 (
S (2
*n))
= n.
Lemma le_div2 n :
div2 (
S n)
<= n.
Lemma lt_div2 n : 0
< n -> div2 n < n.
Lemma div2_decr a n :
a <= S n -> div2 a <= n.
Lemma testbit_0_l :
forall n,
testbit 0
n = false.
Lemma testbit_odd_0 a :
testbit (2
*a+1) 0
= true.
Lemma testbit_even_0 a :
testbit (2
*a) 0
= false.
Lemma testbit_odd_succ' a n :
testbit (2
*a+1) (
S n)
= testbit a n.
Lemma testbit_even_succ' a n :
testbit (2
*a) (
S n)
= testbit a n.
Lemma shiftr_specif :
forall a n m,
testbit (
shiftr a n)
m = testbit a (
m+n).
Lemma shiftl_specif_high :
forall a n m,
n<=m ->
testbit (
shiftl a n)
m = testbit a (
m-n).
Lemma shiftl_spec_low :
forall a n m,
m<n ->
testbit (
shiftl a n)
m = false.
Lemma div2_bitwise :
forall op n a b,
div2 (
bitwise op (
S n)
a b)
= bitwise op n (
div2 a) (
div2 b).
Lemma odd_bitwise :
forall op n a b,
odd (
bitwise op (
S n)
a b)
= op (
odd a) (
odd b).
Lemma testbit_bitwise_1 :
forall op,
(forall b,
op false b = false) ->
forall n m a b,
a<=n ->
testbit (
bitwise op n a b)
m = op (
testbit a m) (
testbit b m).
Lemma testbit_bitwise_2 :
forall op,
op false false = false ->
forall n m a b,
a<=n -> b<=n ->
testbit (
bitwise op n a b)
m = op (
testbit a m) (
testbit b m).
Lemma land_spec a b n :
testbit (
land a b)
n = testbit a n && testbit b n.
Lemma ldiff_spec a b n :
testbit (
ldiff a b)
n = testbit a n && negb (
testbit b n).
Lemma lor_spec a b n :
testbit (
lor a b)
n = testbit a n || testbit b n.
Lemma lxor_spec a b n :
testbit (
lxor a b)
n = xorb (
testbit a n) (
testbit b n).
Lemma div2_spec a :
div2 a = shiftr a 1.
Aliases with extra dummy hypothesis, to fulfil the interface
Properties of advanced functions (pow, sqrt, log2, ...)
Properties of tail-recursive addition and multiplication
Additional results about Even and Odd
Inductive definition of even and odd
Inductive Even_alt :
nat -> Prop :=
|
Even_alt_O :
Even_alt 0
|
Even_alt_S :
forall n,
Odd_alt n -> Even_alt (
S n)
with Odd_alt :
nat -> Prop :=
|
Odd_alt_S :
forall n,
Even_alt n -> Odd_alt (
S n).
Lemma Even_alt_Even :
forall n,
Even_alt n <-> Even n.
Lemma Odd_alt_Odd :
forall n,
Odd_alt n <-> Odd n.
Scheme Odd_alt_Even_alt_ind :=
Minimality for Odd_alt Sort Prop
with Even_alt_Odd_alt_ind :=
Minimality for Even_alt Sort Prop.
Lemma Odd_Even_ind (
P Q :
nat -> Prop) :
(forall n,
Even n -> Q n -> P (
S n)
) ->
Q 0
-> (forall n,
Odd n -> P n -> Q (
S n)
) -> forall n,
Odd n -> P n.
Lemma Even_Odd_ind (
P Q :
nat -> Prop) :
(forall n,
Even n -> Q n -> P (
S n)
) ->
Q 0
-> (forall n,
Odd n -> P n -> Q (
S n)
) -> forall n,
Even n -> Q n.
Scheme Odd_alt_Even_alt_sind :=
Minimality for Odd_alt Sort SProp
with Even_alt_Odd_alt_sind :=
Minimality for Even_alt Sort SProp.
Lemma Odd_Even_sind (
P Q :
nat -> SProp) :
(forall n,
Even n -> Q n -> P (
S n)
) ->
Q 0
-> (forall n,
Odd n -> P n -> Q (
S n)
) -> forall n,
Odd n -> P n.
Lemma Even_Odd_sind (
P Q :
nat -> SProp) :
(forall n,
Even n -> Q n -> P (
S n)
) ->
Q 0
-> (forall n,
Odd n -> P n -> Q (
S n)
) -> forall n,
Even n -> Q n.
additional versions of parity predicates in Type
useful for eliminating into Type, but still with opaque proofs
Re-export notations that should be available even when
the Nat module is not imported.
Bind Scope nat_scope with Nat.t nat.
Infix "^" :=
Nat.pow :
nat_scope.
Infix "=?" :=
Nat.eqb (
at level 70) :
nat_scope.
Infix "<=?" :=
Nat.leb (
at level 70) :
nat_scope.
Infix "<?" :=
Nat.ltb (
at level 70) :
nat_scope.
Infix "?=" :=
Nat.compare (
at level 70) :
nat_scope.
Infix "/" :=
Nat.div :
nat_scope.
Infix "mod" :=
Nat.modulo (
at level 40,
no associativity) :
nat_scope.
#[
global]
Hint Unfold Nat.le :
core.
#[
global]
Hint Unfold Nat.lt :
core.
#[
local]
Definition lt_n_Sm_le := (
fun n m => (
proj1 (
Nat.lt_succ_r n m))).
Register lt_n_Sm_le as num.nat.lt_n_Sm_le.
#[
local]
Definition le_lt_n_Sm := (
fun n m => (
proj2 (
Nat.lt_succ_r n m))).
Register le_lt_n_Sm as num.nat.le_lt_n_Sm.
#[
local]
Definition lt_S_n := (
fun n m => (
proj2 (
Nat.succ_lt_mono n m))).
Register lt_S_n as num.nat.lt_S_n.
Register Nat.le_lt_trans as num.nat.le_lt_trans.
#[
local]
Definition pred_of_minus := (
fun n =>
eq_sym (
Nat.sub_1_r n)).
Register pred_of_minus as num.nat.pred_of_minus.
Register Nat.le_trans as num.nat.le_trans.
Register Nat.nlt_0_r as num.nat.nlt_0_r.
Nat contains an
order tactic for natural numbers
Note that
Nat.order is domain-agnostic: it will not prove
1<=2 or
x<=x+x, but rather things like
x<=y -> y<=x -> x=y.