Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************) (* * The Coq Proof Assistant / The Coq Development Team *) (* v * INRIA, CNRS and contributors - Copyright 1999-2018 *) (* <O___,, * (see CREDITS file for the list of authors) *) (* \VV/ **************************************************************) (* // * This file is distributed under the terms of the *) (* * GNU Lesser General Public License Version 2.1 *) (* * (see LICENSE file for the text of the license) *) (************************************************************************) Require Export BinNums. Require Import BinPos RelationClasses Morphisms Setoid Equalities OrdersFacts GenericMinMax Bool NAxioms NMaxMin NProperties. Require BinNatDef. (**********************************************************************)
(**********************************************************************)
The type N and its constructors N0 and Npos are now
defined in BinNums.v
Every definitions and properties about binary natural numbers
are placed in a module N for qualification purpose.
Local Open Scope N_scope.
Every definitions and early properties about positive numbers
are placed in a module N for qualification purpose.
Module N
<: NAxiomsSig
<: UsualOrderedTypeFull
<: UsualDecidableTypeFull
<: TotalOrder.
Definitions of operations, now in a separate file
Include BinNatDef.N.
When including property functors, only inline t eq zero one two
Set Inline Level 30.
Logical predicates
Definition eq := @Logic.eq N. Definition eq_equiv := @eq_equivalence N. Definition lt x y := (x ?= y) = Lt. Definition gt x y := (x ?= y) = Gt. Definition le x y := (x ?= y) <> Gt. Definition ge x y := (x ?= y) <> Lt. Infix "<=" := le : N_scope. Infix "<" := lt : N_scope. Infix ">=" := ge : N_scope. Infix ">" := gt : N_scope. Notation "x <= y <= z" := (x <= y /\ y <= z) : N_scope. Notation "x <= y < z" := (x <= y /\ y < z) : N_scope. Notation "x < y < z" := (x < y /\ y < z) : N_scope. Notation "x < y <= z" := (x < y /\ y <= z) : N_scope. Definition divide p q := exists r, q = r*p. Notation "( p | q )" := (divide p q) (at level 0) : N_scope. Definition Even n := exists m, n = 2*m. Definition Odd n := exists m, n = 2*m+1.
Proofs of morphisms, obvious since eq is Leibniz
Local Obligation Tactic := simpl_relation. Definition succ_wd : Proper (eq==>eq) succ := _. Definition pred_wd : Proper (eq==>eq) pred := _. Definition add_wd : Proper (eq==>eq==>eq) add := _. Definition sub_wd : Proper (eq==>eq==>eq) sub := _. Definition mul_wd : Proper (eq==>eq==>eq) mul := _. Definition lt_wd : Proper (eq==>eq==>iff) lt := _. Definition div_wd : Proper (eq==>eq==>eq) div := _. Definition mod_wd : Proper (eq==>eq==>eq) modulo := _. Definition pow_wd : Proper (eq==>eq==>eq) pow := _. Definition testbit_wd : Proper (eq==>eq==>Logic.eq) testbit := _.
Decidability of equality.
forall n m : N, {n = m} + {n <> m}forall n m : N, {n = m} + {n <> m}apply Pos.eq_dec. Defined.n, m:Np, p0:positive{p = p0} + {p <> p0}
Discrimination principle
n:N{p : positive | n = pos p} + {n = 0}n:N{p : positive | n = pos p} + {n = 0}left; exists p; auto. Defined.p:positive{p0 : positive | pos p = pos p0} + {pos p = 0}
Convenient induction principles
Definition binary_rect (P:N -> Type) (f0 : P 0) (f2 : forall n, P n -> P (double n)) (fS2 : forall n, P n -> P (succ_double n)) (n : N) : P n := let P' p := P (pos p) in let f2' p := f2 (pos p) in let fS2' p := fS2 (pos p) in match n with | 0 => f0 | pos p => positive_rect P' fS2' f2' (fS2 0 f0) p end. Definition binary_rec (P:N -> Set) := binary_rect P. Definition binary_ind (P:N -> Prop) := binary_rect P.
Peano induction on binary natural numbers
Definition peano_rect (P : N -> Type) (f0 : P 0) (f : forall n : N, P n -> P (succ n)) (n : N) : P n := let P' p := P (pos p) in let f' p := f (pos p) in match n with | 0 => f0 | pos p => Pos.peano_rect P' (f 0 f0) f' p end.P:N -> Typea:P 0f:forall n : N, P n -> P (succ n)peano_rect P a f 0 = areflexivity. Qed.P:N -> Typea:P 0f:forall n : N, P n -> P (succ n)peano_rect P a f 0 = aP:N -> Typea:P 0f:forall n0 : N, P n0 -> P (succ n0)n:Npeano_rect P a f (succ n) = f n (peano_rect P a f n)P:N -> Typea:P 0f:forall n0 : N, P n0 -> P (succ n0)n:Npeano_rect P a f (succ n) = f n (peano_rect P a f n)P:N -> Typea:P 0f:forall n : N, P n -> P (succ n)f 0 a = f 0 aP:N -> Typea:P 0f:forall n : N, P n -> P (succ n)p:positivePos.peano_rect (fun p0 : positive => P (pos p0)) (f 0 a) (fun p0 : positive => f (pos p0)) (Pos.succ p) = f (pos p) (Pos.peano_rect (fun p0 : positive => P (pos p0)) (f 0 a) (fun p0 : positive => f (pos p0)) p)now rewrite Pos.peano_rect_succ. Qed. Definition peano_ind (P : N -> Prop) := peano_rect P. Definition peano_rec (P : N -> Set) := peano_rect P.P:N -> Typea:P 0f:forall n : N, P n -> P (succ n)p:positivePos.peano_rect (fun p0 : positive => P (pos p0)) (f 0 a) (fun p0 : positive => f (pos p0)) (Pos.succ p) = f (pos p) (Pos.peano_rect (fun p0 : positive => P (pos p0)) (f 0 a) (fun p0 : positive => f (pos p0)) p)P:N -> Seta:P 0f:forall n : N, P n -> P (succ n)peano_rec P a f 0 = aapply peano_rect_base. Qed.P:N -> Seta:P 0f:forall n : N, P n -> P (succ n)peano_rec P a f 0 = aP:N -> Seta:P 0f:forall n0 : N, P n0 -> P (succ n0)n:Npeano_rec P a f (succ n) = f n (peano_rec P a f n)apply peano_rect_succ. Qed.P:N -> Seta:P 0f:forall n0 : N, P n0 -> P (succ n0)n:Npeano_rec P a f (succ n) = f n (peano_rec P a f n)
Generic induction / recursion
forall A : N -> Prop, Proper (Logic.eq ==> iff) A -> A 0 -> (forall n : N, A n <-> A (succ n)) -> forall n : N, A nforall A : N -> Prop, Proper (Logic.eq ==> iff) A -> A 0 -> (forall n : N, A n <-> A (succ n)) -> forall n : N, A nA:N -> PropA_wd:Proper (Logic.eq ==> iff) AA0:A 0AS:forall n : N, A n <-> A (succ n)forall n : N, A nA:N -> PropA_wd:Proper (Logic.eq ==> iff) AA0:A 0AS:forall n : N, A n <-> A (succ n)A 0A:N -> PropA_wd:Proper (Logic.eq ==> iff) AA0:A 0AS:forall n : N, A n <-> A (succ n)forall n : N, A n -> A (succ n)intros; now apply -> AS. Qed. Definition recursion {A} : A -> (N -> A -> A) -> N -> A := peano_rect (fun _ => A).A:N -> PropA_wd:Proper (Logic.eq ==> iff) AA0:A 0AS:forall n : N, A n <-> A (succ n)forall n : N, A n -> A (succ n)A:TypeAeq:relation AProper (Aeq ==> (Logic.eq ==> Aeq ==> Aeq) ==> Logic.eq ==> Aeq) recursionA:TypeAeq:relation AProper (Aeq ==> (Logic.eq ==> Aeq ==> Aeq) ==> Logic.eq ==> Aeq) recursionA:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x, x':NEx:x = x'Aeq (recursion a f x) (recursion a' f' x')A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x:NAeq (recursion a f x) (recursion a' f' x)A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'Aeq (recursion a f 0) (recursion a' f' 0)A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x:NIHx:Aeq (recursion a f x) (recursion a' f' x)Aeq (recursion a f (succ x)) (recursion a' f' (succ x))A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x:NIHx:Aeq (recursion a f x) (recursion a' f' x)Aeq (recursion a f (succ x)) (recursion a' f' (succ x))A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x:NIHx:Aeq (peano_rect (fun _ : N => A) a f x) (peano_rect (fun _ : N => A) a' f' x)Aeq (peano_rect (fun _ : N => A) a f (succ x)) (peano_rect (fun _ : N => A) a' f' (succ x))now apply Ef. Qed.A:TypeAeq:relation Aa, a':AEa:Aeq a a'f, f':N -> A -> AEf:(Logic.eq ==> Aeq ==> Aeq)%signature f f'x:NIHx:Aeq (peano_rect (fun _ : N => A) a f x) (peano_rect (fun _ : N => A) a' f' x)Aeq (f x (peano_rect (fun _ : N => A) a f x)) (f' x (peano_rect (fun _ : N => A) a' f' x))A:Typea:Af:N -> A -> Arecursion a f 0 = areflexivity. Qed.A:Typea:Af:N -> A -> Arecursion a f 0 = aA:TypeAeq:relation Aa:Af:N -> A -> AAeq a a -> Proper (Logic.eq ==> Aeq ==> Aeq) f -> forall n : N, Aeq (recursion a f (succ n)) (f n (recursion a f n))A:TypeAeq:relation Aa:Af:N -> A -> AAeq a a -> Proper (Logic.eq ==> Aeq ==> Aeq) f -> forall n : N, Aeq (recursion a f (succ n)) (f n (recursion a f n))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fn:NAeq (peano_rect (fun _ : N => A) a f (succ n)) (f n (peano_rect (fun _ : N => A) a f n))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fAeq (peano_rect (fun _ : N => A) a f (succ 0)) (f 0 (peano_rect (fun _ : N => A) a f 0))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fn:NIHn:Aeq (peano_rect (fun _ : N => A) a f (succ n)) (f n (peano_rect (fun _ : N => A) a f n))Aeq (peano_rect (fun _ : N => A) a f (succ (succ n))) (f (succ n) (peano_rect (fun _ : N => A) a f (succ n)))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fAeq (f 0 (peano_rect (fun _ : N => A) a f 0)) (f 0 (peano_rect (fun _ : N => A) a f 0))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fn:NIHn:Aeq (peano_rect (fun _ : N => A) a f (succ n)) (f n (peano_rect (fun _ : N => A) a f n))Aeq (peano_rect (fun _ : N => A) a f (succ (succ n))) (f (succ n) (peano_rect (fun _ : N => A) a f (succ n)))A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fn:NIHn:Aeq (peano_rect (fun _ : N => A) a f (succ n)) (f n (peano_rect (fun _ : N => A) a f n))Aeq (peano_rect (fun _ : N => A) a f (succ (succ n))) (f (succ n) (peano_rect (fun _ : N => A) a f (succ n)))now apply f_wd. Qed.A:TypeAeq:relation Aa:Af:N -> A -> Aa_wd:Aeq a af_wd:Proper (Logic.eq ==> Aeq ==> Aeq) fn:NIHn:Aeq (f n (peano_rect (fun _ : N => A) a f n)) (f n (peano_rect (fun _ : N => A) a f n))Aeq (f (succ n) (f n (peano_rect (fun _ : N => A) a f n))) (f (succ n) (f n (peano_rect (fun _ : N => A) a f n)))
Specification of constants
1 = succ 0reflexivity. Qed.1 = succ 02 = succ 1reflexivity. Qed.2 = succ 1pred 0 = 0reflexivity. Qed.pred 0 = 0
Properties of mixed successor and predecessor.
p:positivePos.pred_N p = pred (pos p)now destruct p. Qed.p:positivePos.pred_N p = pred (pos p)n:Npos (succ_pos n) = succ nnow destruct n. Qed.n:Npos (succ_pos n) = succ nn:NPos.pred_N (succ_pos n) = nn:NPos.pred_N (succ_pos n) = nPos.pred_N (succ_pos 0) = 0p:positivePos.pred_N (succ_pos (pos p)) = pos papply Pos.pred_N_succ. Qed.p:positivePos.pred_N (succ_pos (pos p)) = pos pp:positivesucc (Pos.pred_N p) = pos pp:positivesucc (Pos.pred_N p) = pos pp:positivepos (Pos.succ (Pos.pred_double p)) = pos p~0apply Pos.succ_pred_double. Qed.p:positivePos.succ (Pos.pred_double p) = (p~0)%positive
Properties of successor and predecessor
n:Npred (succ n) = nn:Npred (succ n) = np:positivepred (succ (pos p)) = pos papply Pos.pred_N_succ. Qed.p:positivePos.pred_N (Pos.succ p) = pos pn:Npred n = n - 1now destruct n as [|[p|p|]]. Qed.n:Npred n = n - 1n:Nsucc n <> 0now destruct n. Qed.n:Nsucc n <> 0
Specification of addition
n:N0 + n = nreflexivity. Qed.n:N0 + n = nn, m:Nsucc n + m = succ (n + m)destruct n, m; unfold succ, add; now rewrite ?Pos.add_1_l, ?Pos.add_succ_l. Qed.n, m:Nsucc n + m = succ (n + m)
Specification of subtraction.
n:Nn - 0 = nnow destruct n. Qed.n:Nn - 0 = nn, m:Nn - succ m = pred (n - m)n, m:Nn - succ m = pred (n - m)p:positivepos p - succ 0 = pred (pos p - 0)p, q:positivepos p - succ (pos q) = pred (pos p - pos q)p, q:positivepos p - succ (pos q) = pred (pos p - pos q)p, q:positivematch Pos.sub_mask p (Pos.succ q) with | Pos.IsPos p0 => pos p0 | _ => 0 end = pred match Pos.sub_mask p q with | Pos.IsPos p0 => pos p0 | _ => 0 endnow destruct (Pos.sub_mask p q) as [|[r|r|]|]. Qed.p, q:positivematch Pos.pred_mask (Pos.sub_mask p q) with | Pos.IsPos p0 => pos p0 | _ => 0 end = pred match Pos.sub_mask p q with | Pos.IsPos p0 => pos p0 | _ => 0 end
Specification of multiplication
n:N0 * n = 0reflexivity. Qed.n:N0 * n = 0n, m:Nsucc n * m = n * m + mn, m:Nsucc n * m = n * m + mp, p0:positivepos (Pos.succ p * p0) = pos (p * p0 + p0)p, p0:positive(Pos.succ p * p0)%positive = (p * p0 + p0)%positiveapply Pos.mul_succ_l. Qed.p, p0:positive(Pos.succ p * p0)%positive = (p0 + p * p0)%positive
Specification of boolean comparisons.
n, m:N(n =? m) = true <-> n = mn, m:N(n =? m) = true <-> n = mn, m:positive(n =? m)%positive = true <-> pos n = pos mn, m:positiven = m <-> pos n = pos mn, m:positiveH:n = mpos n = pos mn, m:positiveH:pos n = pos mn = mnow destr_eq H. Qed.n, m:positiveH:pos n = pos mn = mn, m:N(n <? m) = true <-> n < mn, m:N(n <? m) = true <-> n < mdestruct compare; easy'. Qed.n, m:Nmatch n ?= m with | Lt => true | _ => false end = true <-> (n ?= m) = Ltn, m:N(n <=? m) = true <-> n <= mn, m:N(n <=? m) = true <-> n <= mdestruct compare; easy'. Qed.n, m:Nmatch n ?= m with | Gt => false | _ => true end = true <-> (n ?= m) <> Gt
Basic properties of comparison
n, m:N(n ?= m) = Eq <-> n = mdestruct n, m; simpl; rewrite ?Pos.compare_eq_iff; split; congruence. Qed.n, m:N(n ?= m) = Eq <-> n = mn, m:N(n ?= m) = Lt <-> n < mreflexivity. Qed.n, m:N(n ?= m) = Lt <-> n < mn, m:N(n ?= m) <> Gt <-> n <= mreflexivity. Qed.n, m:N(n ?= m) <> Gt <-> n <= mn, m:N(m ?= n) = CompOpp (n ?= m)n, m:N(m ?= n) = CompOpp (n ?= m)apply Pos.compare_antisym. Qed.p, p0:positive(p0 ?= p)%positive = CompOpp (p ?= p0)%positive
Some more advanced properties of comparison and orders,
including compare_spec and lt_irrefl and lt_eq_cases.
Include BoolOrderFacts.
Specification of minimum and maximum
n, m:Nn <= m -> min n m = nn, m:Nn <= m -> min n m = nn, m:N(n ?= m) <> Gt -> match n ?= m with | Gt => m | _ => n end = nnow destruct 1. Qed.n, m:NGt <> Gt -> m = nn, m:Nm <= n -> min n m = mn, m:Nm <= n -> min n m = mn, m:N(m ?= n) <> Gt -> match n ?= m with | Gt => m | _ => n end = mn, m:NCompOpp (n ?= m) <> Gt -> match n ?= m with | Gt => m | _ => n end = mnow destruct 2. Qed.n, m:Nn < m -> CompOpp Lt <> Gt -> n = mn, m:Nm <= n -> max n m = nn, m:Nm <= n -> max n m = nn, m:N(m ?= n) <> Gt -> match n ?= m with | Gt => n | _ => m end = nn, m:NCompOpp (n ?= m) <> Gt -> match n ?= m with | Gt => n | _ => m end = nnow destruct 2. Qed.n, m:Nn < m -> CompOpp Lt <> Gt -> m = nn, m:Nn <= m -> max n m = mn, m:Nn <= m -> max n m = mn, m:N(n ?= m) <> Gt -> match n ?= m with | Gt => n | _ => m end = mnow destruct 1. Qed.n, m:NGt <> Gt -> n = m
Specification of lt and le.
n, m:Nn < succ m <-> n <= mn, m:Nn < succ m <-> n <= mp:positivepos p < 1 <-> pos p <= 0p, q:positivepos p < pos (Pos.succ q) <-> pos p <= pos qp:positivepos p < 1 -> pos p <= 0p:positivepos p <= 0 -> pos p < 1p, q:positivepos p < pos (Pos.succ q) <-> pos p <= pos qp:positivepos p <= 0 -> pos p < 1p, q:positivepos p < pos (Pos.succ q) <-> pos p <= pos qapply Pos.lt_succ_r. Qed.p, q:positivepos p < pos (Pos.succ q) <-> pos p <= pos q
We can now derive all properties of basic functions and orders,
and use these properties for proving the specs of more advanced
functions.
Include NBasicProp <+ UsualMinMaxLogicalProperties <+ UsualMinMaxDecProperties.
Properties of double and succ_double
n:Ndouble n = 2 * nreflexivity. Qed.n:Ndouble n = 2 * nn:Nsucc_double n = 2 * n + 1now destruct n. Qed.n:Nsucc_double n = 2 * n + 1n, m:Ndouble (n + m) = double n + double mnow destruct n, m. Qed.n, m:Ndouble (n + m) = double n + double mn, m:Nsucc_double (n + m) = double n + succ_double mnow destruct n, m. Qed.n, m:Nsucc_double (n + m) = double n + succ_double mn, m:Ndouble (n * m) = double n * mnow destruct n, m. Qed.n, m:Ndouble (n * m) = double n * mn, m:Nsucc_double n * m = double n * m + mn, m:Nsucc_double n * m = double n * m + mnow rewrite Pos.add_comm. Qed.p, p0:positivepos (p0 + (p * p0)~0) = pos (p * p0)~0 + pos p0n:Ndiv2 (double n) = nnow destruct n. Qed.n:Ndiv2 (double n) = nn:Ndiv2 (succ_double n) = nnow destruct n. Qed.n:Ndiv2 (succ_double n) = nn, m:Ndouble n = double m -> n = mn, m:Ndouble n = double m -> n = mn, m:NH:double n = double mn = mapply div2_double. Qed.n, m:NH:double n = double mdiv2 (double m) = mn, m:Nsucc_double n = succ_double m -> n = mn, m:Nsucc_double n = succ_double m -> n = mn, m:NH:succ_double n = succ_double mn = mapply div2_succ_double. Qed.n, m:NH:succ_double n = succ_double mdiv2 (succ_double m) = mn, m:Nn < m -> succ_double n < double mn, m:Nn < m -> succ_double n < double mn, m:positiveH:pos n < pos msucc_double (pos n) < double (pos m)now rewrite Pos.compare_xI_xO, H. Qed.n, m:positiveH:(n ?= m)%positive = Lt(n~1 ?= m~0)%positive = Ltn, m:Nn < m -> double n < double mdestruct n as [|n], m as [|m]; intros H; try easy. Qed.n, m:Nn < m -> double n < double mn, m:Nn <= m -> double n <= double mdestruct n as [|n], m as [|m]; intros H; try easy. Qed.n, m:Nn <= m -> double n <= double mn, m:Nn < m -> succ_double n < succ_double mdestruct n as [|n], m as [|m]; intros H; try easy. Qed.n, m:Nn < m -> succ_double n < succ_double mn, m:Nn <= m -> succ_double n <= succ_double mdestruct n as [|n], m as [|m]; intros H; try easy. Qed.n, m:Nn <= m -> succ_double n <= succ_double m
0 is the least natural number
n:N(n ?= 0) <> Ltnow destruct n. Qed.n:N(n ?= 0) <> Lt
Specifications of power
n:Nn ^ 0 = 1reflexivity. Qed.n:Nn ^ 0 = 1n, p:N0 <= p -> n ^ succ p = n * n ^ pn, p:N0 <= p -> n ^ succ p = n * n ^ pn, p:Nn ^ succ p = n * n ^ papply Pos.pow_succ_r. Qed.p0, p:positive(p0 ^ Pos.succ p)%positive = (p0 * p0 ^ p)%positiven, p:Np < 0 -> n ^ p = 0now destruct p. Qed.n, p:Np < 0 -> n ^ p = 0
Specification of square
n:Nsquare n = n * nn:Nsquare n = n * np:positivesquare (pos p) = pos p * pos pp:positivepos (Pos.square p) = pos (p * p)apply Pos.square_spec. Qed.p:positivePos.square p = (p * p)%positive
Specification of Base-2 logarithm
n:Nn <> 0 -> size n = succ (log2 n)n:Nn <> 0 -> size n = succ (log2 n)now destruct 1. Qed.0 <> 0 -> size 0 = succ (log2 0)n:Nn < 2 ^ size nn:Nn < 2 ^ size n0 < 2 ^ size 0p:positivepos p < 2 ^ size (pos p)p:positivepos p < 2 ^ size (pos p)apply Pos.size_gt. Qed.p:positivepos p < pos (2 ^ Pos.size p)n:N2 ^ size n <= succ_double nn:N2 ^ size n <= succ_double n2 ^ size 0 <= succ_double 0p:positive2 ^ size (pos p) <= succ_double (pos p)p:positive2 ^ size (pos p) <= succ_double (pos p)p:positivepos (2 ^ Pos.size p) <= pos p~1apply Pos.lt_le_incl, Pos.lt_succ_r, Pos.size_le. Qed.p:positive(2 ^ Pos.size p <= Pos.succ p~0)%positiven:N0 < n -> 2 ^ log2 n <= n < 2 ^ succ (log2 n)n:N0 < n -> 2 ^ log2 n <= n < 2 ^ succ (log2 n)p:positivepos (2 ^ Pos.size p) <= pos p~1p:positivepos p~1 < pos (2 ^ Pos.succ (Pos.size p))p:positivepos (2 ^ Pos.size p) <= pos p~0p:positivepos p~0 < pos (2 ^ Pos.succ (Pos.size p))1 <= 11 < pos (2 ^ 1)p:positivepos p~1 < pos (2 ^ Pos.succ (Pos.size p))p:positivepos (2 ^ Pos.size p) <= pos p~0p:positivepos p~0 < pos (2 ^ Pos.succ (Pos.size p))1 <= 11 < pos (2 ^ 1)p:positivepos (2 ^ Pos.size p) <= pos p~0p:positivepos p~0 < pos (2 ^ Pos.succ (Pos.size p))1 <= 11 < pos (2 ^ 1)p:positivepos p~0 < pos (2 ^ Pos.succ (Pos.size p))1 <= 11 < pos (2 ^ 1)1 <= 11 < pos (2 ^ 1)reflexivity. Qed.1 < pos (2 ^ 1)n:Nn <= 0 -> log2 n = 0n:Nn <= 0 -> log2 n = 0Hn:0 <= 0log2 0 = 0p:positiveHn:pos p <= 0log2 (pos p) = 0now destruct Hn. Qed.p:positiveHn:pos p <= 0log2 (pos p) = 0
Specification of parity functions
n:Neven n = true <-> Even nn:Neven n = true <-> Even neven 0 = true <-> Even 0p:positiveeven (pos p) = true <-> Even (pos p)even 0 = true -> Even 0Even 0 -> even 0 = truep:positiveeven (pos p) = true <-> Even (pos p)Even 0 -> even 0 = truep:positiveeven (pos p) = true <-> Even (pos p)p:positiveeven (pos p) = true <-> Even (pos p)p:positiveEven (pos p~1) -> false = truep:positivetrue = true -> Even (pos p~0)Even 1 -> false = truep:positivem:NH:pos p~1 = 2 * mfalse = truep:positivetrue = true -> Even (pos p~0)Even 1 -> false = truep:positivetrue = true -> Even (pos p~0)Even 1 -> false = trueEven 1 -> false = truenow destruct m. Qed.m:NH:1 = 2 * mfalse = truen:Nodd n = true <-> Odd nn:Nodd n = true <-> Odd nodd 0 = true <-> Odd 0p:positiveodd (pos p) = true <-> Odd (pos p)odd 0 = true -> Odd 0Odd 0 -> odd 0 = truep:positiveodd (pos p) = true <-> Odd (pos p)Odd 0 -> odd 0 = truep:positiveodd (pos p) = true <-> Odd (pos p)m:NH:0 = 2 * m + 1odd 0 = truep:positiveodd (pos p) = true <-> Odd (pos p)p:positiveodd (pos p) = true <-> Odd (pos p)p:positiveodd (pos p~1) = true -> Odd (pos p~1)p:positiveOdd (pos p~0) -> odd (pos p~0) = trueodd 1 = true -> Odd 1p:positiveOdd (pos p~0) -> odd (pos p~0) = trueodd 1 = true -> Odd 1p:positivem:NH:pos p~0 = 2 * m + 1odd (pos p~0) = trueodd 1 = true -> Odd 1now exists 0. Qed.odd 1 = true -> Odd 1
Specification of the euclidean division
a:positiveb:Nlet (q, r) := pos_div_eucl a b in pos a = q * b + ra:positiveb:Nlet (q, r) := pos_div_eucl a b in pos a = q * b + r(* a~1 *)a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r) in pos a~1 = q * b + ra:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r) in pos a~1 = q0 * b + r0a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r) in succ_double (pos a) = q0 * b + r0a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r) in double q * b + succ_double r = q0 * b + r0a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= succ_double rdouble q * b + succ_double r = succ_double q * b + (succ_double r - b)a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= succ_double rdouble q * b + succ_double r = double q * b + (b + (succ_double r - b))a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= succ_double rsucc_double r = b + (succ_double r - b)a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + r(* a~0 *)a:positiveb:NIHa:let (q, r) := pos_div_eucl a b in pos a = q * b + rlet (q, r) := let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q * b + rb:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? double r then (succ_double q, double r - b) else (double q, double r) in pos a~0 = q0 * b + r0b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? double r then (succ_double q, double r - b) else (double q, double r) in double (pos a) = q0 * b + r0b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rlet (q0, r0) := if b <=? double r then (succ_double q, double r - b) else (double q, double r) in double q * b + double r = q0 * b + r0b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= double rdouble q * b + double r = succ_double q * b + (double r - b)b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= double rdouble q * b + double r = double q * b + (b + (double r - b))b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra:positiveb, q, r:NIHa:pos a = q * b + rH:b <= double rdouble r = b + (double r - b)b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + r(* 1 *) now destruct b as [|[ | | ]]. Qed.b:Nlet (q, r) := match b with | 1 => (1, 0) | _ => (0, 1) end in 1 = q * b + ra, b:Nlet (q, r) := div_eucl a b in a = b * q + ra, b:Nlet (q, r) := div_eucl a b in a = b * q + ra, b:positivelet (q, r) := pos_div_eucl a (pos b) in pos a = pos b * q + ra, b:positive(let (q, r) := pos_div_eucl a (pos b) in pos a = q * pos b + r) -> let (q, r) := pos_div_eucl a (pos b) in pos a = pos b * q + rnow rewrite mul_comm. Qed.a, b:positiven, n0:Npos a = n * pos b + n0 -> pos a = pos b * n + n0a, b:Na = b * (a / b) + a mod ba, b:Na = b * (a / b) + a mod ba, b:N(let (q, r) := div_eucl a b in a = b * q + r) -> a = b * (a / b) + a mod bnow destruct div_eucl. Qed.a, b:N(let (q, r) := div_eucl a b in a = b * q + r) -> a = b * fst (div_eucl a b) + snd (div_eucl a b)a, b:Nb <> 0 -> a = b * (a / b) + a mod ba, b:Nb <> 0 -> a = b * (a / b) + a mod bapply div_mod'. Qed.a, b:Na = b * (a / b) + a mod ba:positiveb:Nb <> 0 -> snd (pos_div_eucl a b) < ba:positiveb:Nb <> 0 -> snd (pos_div_eucl a b) < ba:positiveb:NHb:b <> 0snd (pos_div_eucl a b) < b(* a~1 *)a:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r)) < ba:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bsnd (if b <=? succ_double r then (succ_double q, succ_double r - b) else (double q, succ_double r)) < ba:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= succ_double rsucc_double r - b < ba:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= succ_double rb + (succ_double r - b) < b + ba:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= succ_double rsucc_double r < b + ba:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba, b:positiveHb:pos b <> 0q, r:NIHa:r < pos bH:pos b <= succ_double rsucc_double r < pos b~0a:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < b(* a~0 *)a:positiveb:NHb:b <> 0IHa:snd (pos_div_eucl a b) < bsnd (let (q, r) := pos_div_eucl a b in if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bsnd (if b <=? double r then (succ_double q, double r - b) else (double q, double r)) < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= double rdouble r - b < bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= double rb + (double r - b) < b + bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba:positiveb:NHb:b <> 0q, r:NIHa:r < bH:b <= double rdouble r < b + bb:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba, b:positiveHb:pos b <> 0q, r:NIHa:r < pos bH:pos b <= double rdouble r < pos b~0b:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < b(* 1 *) destruct b as [|[ | | ]]; easy || (now destruct Hb). Qed.b:NHb:b <> 0snd match b with | 1 => (1, 0) | _ => (0, 1) end < ba, b:Nb <> 0 -> a mod b < ba, b:Nb <> 0 -> a mod b < ba:N0 <> 0 -> a mod 0 < 0a:Nb:positivepos b <> 0 -> a mod pos b < pos ba:Nb:positivepos b <> 0 -> a mod pos b < pos bb:positivepos b <> 0 -> 0 mod pos b < pos ba, b:positivepos b <> 0 -> pos a mod pos b < pos ba, b:positivepos b <> 0 -> pos a mod pos b < pos ba, b:positivepos b <> 0 -> snd (div_eucl (pos a) (pos b)) < pos bapply pos_div_eucl_remainder. Qed.a, b:positivepos b <> 0 -> snd (pos_div_eucl a (pos b)) < pos ba, b:N0 <= a -> 0 < b -> 0 <= a mod b < ba, b:N0 <= a -> 0 < b -> 0 <= a mod b < ba, b:NH:0 < b0 <= a mod b < ba, b:NH:0 < b0 <= a mod ba, b:NH:0 < ba mod b < ba, b:NH:0 < ba mod b < bnow destruct b. Qed.a, b:NH:0 < bb <> 0
Specification of square root
n:Nfst (sqrtrem n) = sqrt nn:Nfst (sqrtrem n) = sqrt nfst (sqrtrem 0) = sqrt 0p:positivefst (sqrtrem (pos p)) = sqrt (pos p)p:positivefst (sqrtrem (pos p)) = sqrt (pos p)p:positivefst (let (s, m) := Pos.sqrtrem p in match m with | Pos.IsPos r => (pos s, pos r) | _ => (pos s, 0) end) = pos (fst (Pos.sqrtrem p))now destruct r. Qed.p, s:positiver:Pos.maskfst match r with | Pos.IsPos r0 => (pos s, pos r0) | _ => (pos s, 0) end = pos (fst (s, r))n:Nlet (s, r) := sqrtrem n in n = s * s + r /\ r <= 2 * sn:Nlet (s, r) := sqrtrem n in n = s * s + r /\ r <= 2 * slet (s, r) := sqrtrem 0 in 0 = s * s + r /\ r <= 2 * sp:positivelet (s, r) := sqrtrem (pos p) in pos p = s * s + r /\ r <= 2 * sp:positivelet (s, r) := sqrtrem (pos p) in pos p = s * s + r /\ r <= 2 * sp:positivePos.SqrtSpec (Pos.sqrtrem p) p -> let (s, r) := sqrtrem (pos p) in pos p = s * s + r /\ r <= 2 * sdestruct 1; simpl; subst; now split. Qed.p:positivePos.SqrtSpec (Pos.sqrtrem p) p -> let (s, r) := let (s, m) := Pos.sqrtrem p in match m with | Pos.IsPos r => (pos s, pos r) | _ => (pos s, 0) end in pos p = s * s + r /\ r <= match s with | 0 => 0 | pos q => pos q~0 endn:N0 <= n -> let s := sqrt n in s * s <= n < succ s * succ sn:N0 <= n -> let s := sqrt n in s * s <= n < succ s * succ sn:Nlet s := sqrt n in s * s <= n < succ s * succ slet s := sqrt 0 in s * s <= 0 < succ s * succ sp:positivelet s := sqrt (pos p) in s * s <= pos p < succ s * succ sapply (Pos.sqrt_spec p). Qed.p:positivelet s := sqrt (pos p) in s * s <= pos p < succ s * succ sn:Nn < 0 -> sqrt n = 0now destruct n. Qed.n:Nn < 0 -> sqrt n = 0
Specification of gcd
The first component of ggcd is gcd
a, b:Nfst (ggcd a b) = gcd a ba, b:Nfst (ggcd a b) = gcd a bp, q:positivefst (let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb))) = pos (Pos.gcd p q)destruct Pos.ggcd as (g,(aa,bb)); simpl; now f_equal. Qed.p, q:positiveH:fst (Pos.ggcd p q) = Pos.gcd p qfst (let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb))) = pos (Pos.gcd p q)
The other components of ggcd are indeed the correct factors.
a, b:Nlet '(g, (aa, bb)) := ggcd a b in a = g * aa /\ b = g * bba, b:Nlet '(g, (aa, bb)) := ggcd a b in a = g * aa /\ b = g * bbq:positive0 = 0 /\ pos q = pos (q * 1)p:positivepos p = pos (p * 1) /\ 0 = 0p, q:positivelet '(g, (aa, bb)) := let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb)) in pos p = g * aa /\ pos q = g * bbp:positivepos p = pos (p * 1) /\ 0 = 0p, q:positivelet '(g, (aa, bb)) := let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb)) in pos p = g * aa /\ pos q = g * bbp, q:positivelet '(g, (aa, bb)) := let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb)) in pos p = g * aa /\ pos q = g * bbp, q:positive(let '(g, (aa, bb)) := Pos.ggcd p q in p = (g * aa)%positive /\ q = (g * bb)%positive) -> let '(g, (aa, bb)) := let '(g, (aa, bb)) := Pos.ggcd p q in (pos g, (pos aa, pos bb)) in pos p = g * aa /\ pos q = g * bbdestruct 1; split; now f_equal. Qed.p, q, g, aa, bb:positivep = (g * aa)%positive /\ q = (g * bb)%positive -> pos p = pos (g * aa) /\ pos q = pos (g * bb)
We can use this fact to prove a part of the gcd correctness
a, b:N(gcd a b | a)a, b:N(gcd a b | a)a, b:N(fst (ggcd a b) | a)a, b:N(let '(g, (aa, bb)) := ggcd a b in a = g * aa /\ b = g * bb) -> (fst (ggcd a b) | a)a, b, g, aa, bb:Na = g * aa /\ b = g * bb -> (g | a)a, b, g, aa, bb:NH:a = g * aa(g | a)now rewrite mul_comm. Qed.a, b, g, aa, bb:NH:a = g * aaa = aa * ga, b:N(gcd a b | b)a, b:N(gcd a b | b)a, b:N(fst (ggcd a b) | b)a, b:N(let '(g, (aa, bb)) := ggcd a b in a = g * aa /\ b = g * bb) -> (fst (ggcd a b) | b)a, b, g, aa, bb:Na = g * aa /\ b = g * bb -> (g | b)a, b, g, aa, bb:NH:b = g * bb(g | b)now rewrite mul_comm. Qed.a, b, g, aa, bb:NH:b = g * bbb = bb * g
We now prove directly that gcd is the greatest amongst common divisors
a, b, c:N(c | a) -> (c | b) -> (c | gcd a b)a, b, c:N(c | a) -> (c | b) -> (c | gcd a b)p, q:positivec:N(c | pos p) -> (c | pos q) -> (c | pos (Pos.gcd p q))p, q:positive(0 | pos p) -> (0 | pos q) -> (0 | pos (Pos.gcd p q))p, q, r:positive(pos r | pos p) -> (pos r | pos q) -> (pos r | pos (Pos.gcd p q))p, q:positives:NH:pos p = s * 0(0 | pos q) -> (0 | pos (Pos.gcd p q))p, q, r:positive(pos r | pos p) -> (pos r | pos q) -> (pos r | pos (Pos.gcd p q))p, q, r:positive(pos r | pos p) -> (pos r | pos q) -> (pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)(pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)(r | p)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)(r | q)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positive(pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)p = (s * r)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)(r | q)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positive(pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)(r | q)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positive(pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)q = (t * r)%positivep, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positive(pos r | pos (Pos.gcd p q))p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positive(pos r | pos (Pos.gcd p q))simpl; now f_equal. Qed.p, q, r, s:positiveHs:pos p = pos (s * r)t:positiveHt:pos q = pos (t * r)u:positiveH:Pos.gcd p q = (u * r)%positivepos (Pos.gcd p q) = pos u * pos ra, b:N0 <= gcd a bapply le_0_l. Qed.a, b:N0 <= gcd a b
Specification of bitwise functions
Correctness proofs for testbit.
a:Ntestbit (2 * a) 0 = falsenow destruct a. Qed.a:Ntestbit (2 * a) 0 = falsea:Ntestbit (2 * a + 1) 0 = truenow destruct a. Qed.a:Ntestbit (2 * a + 1) 0 = truea, n:N0 <= n -> testbit a (succ n) = testbit (div2 a) na, n:N0 <= n -> testbit a (succ n) = testbit (div2 a) ndestruct a as [|[a|a| ]], n as [|n]; simpl; trivial; f_equal; apply Pos.pred_N_succ. Qed.a, n:Ntestbit a (succ n) = testbit (div2 a) na, n:N0 <= n -> testbit (2 * a + 1) (succ n) = testbit a na, n:N0 <= n -> testbit (2 * a + 1) (succ n) = testbit a na, n:NH:0 <= ntestbit (2 * a + 1) (succ n) = testbit a na, n:NH:0 <= ntestbit (div2 (2 * a + 1)) n = testbit a nnow destruct a. Qed.a, n:NH:0 <= ndiv2 (2 * a + 1) = aa, n:N0 <= n -> testbit (2 * a) (succ n) = testbit a na, n:N0 <= n -> testbit (2 * a) (succ n) = testbit a na, n:NH:0 <= ntestbit (2 * a) (succ n) = testbit a na, n:NH:0 <= ntestbit (div2 (2 * a)) n = testbit a nnow destruct a. Qed.a, n:NH:0 <= ndiv2 (2 * a) = aa, n:Nn < 0 -> testbit a n = falsenow destruct n. Qed.a, n:Nn < 0 -> testbit a n = false
Correctness proofs for shifts
a, n:Nshiftr a (succ n) = div2 (shiftr a n)a, n:Nshiftr a (succ n) = div2 (shiftr a n)apply Pos.iter_succ. Qed.a:Np:positivePos.iter div2 a (Pos.succ p) = div2 (Pos.iter div2 a p)a, n:Nshiftl a (succ n) = double (shiftl a n)a, n:Nshiftl a (succ n) = double (shiftl a n)p0, p:positivepos (Pos.iter xO p0 (Pos.succ p)) = pos (Pos.iter xO p0 p)~0apply Pos.iter_succ. Qed.p0, p:positivePos.iter xO p0 (Pos.succ p) = ((Pos.iter xO p0 p)~0)%positivea, n, m:N0 <= m -> testbit (shiftr a n) m = testbit a (m + n)a, n, m:N0 <= m -> testbit (shiftr a n) m = testbit a (m + n)a, n, m:Ntestbit (shiftr a n) m = testbit a (m + n)n:Nforall a m : N, testbit (shiftr a n) m = testbit a (m + n)a, m:Ntestbit (shiftr a 0) m = testbit a (m + 0)n:NIHn:forall a0 m0 : N, testbit (shiftr a0 n) m0 = testbit a0 (m0 + n)a, m:Ntestbit (shiftr a (succ n)) m = testbit a (m + succ n)n:NIHn:forall a0 m0 : N, testbit (shiftr a0 n) m0 = testbit a0 (m0 + n)a, m:Ntestbit (shiftr a (succ n)) m = testbit a (m + succ n)now rewrite <- IHn, testbit_succ_r_div2, shiftr_succ_r by apply le_0_l. Qed.n:NIHn:forall a0 m0 : N, testbit (shiftr a0 n) m0 = testbit a0 (m0 + n)a, m:Ntestbit (shiftr a (succ n)) m = testbit a (succ m + n)a, n, m:N0 <= m -> n <= m -> testbit (shiftl a n) m = testbit a (m - n)a, n, m:N0 <= m -> n <= m -> testbit (shiftl a n) m = testbit a (m - n)a, n, m:NH:n <= mtestbit (shiftl a n) m = testbit a (m - n)a, n, m:NH:n <= mtestbit (shiftl a n) (m - n + n) = testbit a (m - n)a, n, m:NH:n <= mm':=m - n:Ntestbit (shiftl a n) (m' + n) = testbit a m'a, n, m:NH:n <= mm':Ntestbit (shiftl a n) (m' + n) = testbit a m'a, n, m':Ntestbit (shiftl a n) (m' + n) = testbit a m'n:Nforall a m' : N, testbit (shiftl a n) (m' + n) = testbit a m'a, m:Ntestbit (shiftl a 0) (m + 0) = testbit a mn:NIHn:forall a0 m' : N, testbit (shiftl a0 n) (m' + n) = testbit a0 m'a, m:Ntestbit (shiftl a (succ n)) (m + succ n) = testbit a mn:NIHn:forall a0 m' : N, testbit (shiftl a0 n) (m' + n) = testbit a0 m'a, m:Ntestbit (shiftl a (succ n)) (m + succ n) = testbit a mn:NIHn:forall a0 m' : N, testbit (shiftl a0 n) (m' + n) = testbit a0 m'a, m:Ntestbit (double (shiftl a n)) (m + succ n) = testbit a mnow rewrite testbit_succ_r_div2, div2_double by apply le_0_l. Qed.n:NIHn:forall a0 m' : N, testbit (shiftl a0 n) (m' + n) = testbit a0 m'a, m:Ntestbit (double (shiftl a n)) (succ (m + n)) = testbit a ma, n, m:Nm < n -> testbit (shiftl a n) m = falsea, n, m:Nm < n -> testbit (shiftl a n) m = falsen:Nforall a m : N, m < n -> testbit (shiftl a n) m = falsea, m:NH:m < 0testbit (shiftl a 0) m = falsen:NIHn:forall a0 m0 : N, m0 < n -> testbit (shiftl a0 n) m0 = falsea, m:NH:m < succ ntestbit (shiftl a (succ n)) m = falsea, m:NH:m < 0(0 ?= m) = Gtn:NIHn:forall a0 m0 : N, m0 < n -> testbit (shiftl a0 n) m0 = falsea, m:NH:m < succ ntestbit (shiftl a (succ n)) m = falsen:NIHn:forall a0 m0 : N, m0 < n -> testbit (shiftl a0 n) m0 = falsea, m:NH:m < succ ntestbit (shiftl a (succ n)) m = falsen:NIHn:forall a0 m0 : N, m0 < n -> testbit (shiftl a0 n) m0 = falsea, m:NH:m < succ ntestbit (double (shiftl a n)) m = falsen:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:NH:0 < succ ntestbit (double (shiftl a n)) 0 = falsen:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ ntestbit (double (shiftl a n)) (pos p) = falsen:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ ntestbit (double (shiftl a n)) (pos p) = falsen:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ ntestbit (shiftl a n) (Pos.pred_N p) = falsen:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ nPos.pred_N p < nn:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ n1 + Pos.pred_N p < 1 + nn:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ nsucc (0 + Pos.pred_N p) < succ (0 + n)now rewrite succ_pos_pred. Qed.n:NIHn:forall a0 m : N, m < n -> testbit (shiftl a0 n) m = falsea:Np:positiveH:pos p < succ nsucc (Pos.pred_N p) < succ na:Ndiv2 a = shiftr a 1reflexivity. Qed.a:Ndiv2 a = shiftr a 1
Semantics of bitwise operations
p, p':positiven:Ntestbit (Pos.lxor p p') n = xorb (Pos.testbit p n) (Pos.testbit p' n)p, p':positiven:Ntestbit (Pos.lxor p p') n = xorb (Pos.testbit p n) (Pos.testbit p' n)induction p as [p IH|p IH|]; intros [p'|p'|] [|n]; trivial; simpl; (specialize (IH p'); destruct Pos.lxor; trivial; now rewrite <-IH) || (now destruct Pos.testbit). Qed.p:positiveforall (p' : positive) (n : N), testbit (Pos.lxor p p') n = xorb (Pos.testbit p n) (Pos.testbit p' n)a, a', n:Ntestbit (lxor a a') n = xorb (testbit a n) (testbit a' n)a, a', n:Ntestbit (lxor a a') n = xorb (testbit a n) (testbit a' n)p:positiven:NPos.testbit p n = (if Pos.testbit p n then true else false)p:positiven:NPos.testbit p n = xorb (Pos.testbit p n) falsep, p0:positiven:Ntestbit (Pos.lxor p p0) n = xorb (Pos.testbit p n) (Pos.testbit p0 n)p:positiven:NPos.testbit p n = xorb (Pos.testbit p n) falsep, p0:positiven:Ntestbit (Pos.lxor p p0) n = xorb (Pos.testbit p n) (Pos.testbit p0 n)apply pos_lxor_spec. Qed.p, p0:positiven:Ntestbit (Pos.lxor p p0) n = xorb (Pos.testbit p n) (Pos.testbit p0 n)p, p':positiven:NPos.testbit (Pos.lor p p') n = Pos.testbit p n || Pos.testbit p' np, p':positiven:NPos.testbit (Pos.lor p p') n = Pos.testbit p n || Pos.testbit p' ninduction p as [p IH|p IH|]; intros [p'|p'|] [|n]; trivial; simpl; apply IH || now rewrite orb_false_r. Qed.p:positiveforall (p' : positive) (n : N), Pos.testbit (Pos.lor p p') n = Pos.testbit p n || Pos.testbit p' na, a', n:Ntestbit (lor a a') n = testbit a n || testbit a' na, a', n:Ntestbit (lor a a') n = testbit a n || testbit a' np:positiven:NPos.testbit p n = Pos.testbit p n || falsep, p0:positiven:NPos.testbit (Pos.lor p p0) n = Pos.testbit p n || Pos.testbit p0 napply pos_lor_spec. Qed.p, p0:positiven:NPos.testbit (Pos.lor p p0) n = Pos.testbit p n || Pos.testbit p0 np, p':positiven:Ntestbit (Pos.land p p') n = Pos.testbit p n && Pos.testbit p' np, p':positiven:Ntestbit (Pos.land p p') n = Pos.testbit p n && Pos.testbit p' ninduction p as [p IH|p IH|]; intros [p'|p'|] [|n]; trivial; simpl; (specialize (IH p'); destruct Pos.land; trivial; now rewrite <-IH) || (now rewrite andb_false_r). Qed.p:positiveforall (p' : positive) (n : N), testbit (Pos.land p p') n = Pos.testbit p n && Pos.testbit p' na, a', n:Ntestbit (land a a') n = testbit a n && testbit a' na, a', n:Ntestbit (land a a') n = testbit a n && testbit a' np:positiven:Nfalse = Pos.testbit p n && falsep, p0:positiven:Ntestbit (Pos.land p p0) n = Pos.testbit p n && Pos.testbit p0 napply pos_land_spec. Qed.p, p0:positiven:Ntestbit (Pos.land p p0) n = Pos.testbit p n && Pos.testbit p0 np, p':positiven:Ntestbit (Pos.ldiff p p') n = Pos.testbit p n && negb (Pos.testbit p' n)p, p':positiven:Ntestbit (Pos.ldiff p p') n = Pos.testbit p n && negb (Pos.testbit p' n)induction p as [p IH|p IH|]; intros [p'|p'|] [|n]; trivial; simpl; (specialize (IH p'); destruct Pos.ldiff; trivial; now rewrite <-IH) || (now rewrite andb_true_r). Qed.p:positiveforall (p' : positive) (n : N), testbit (Pos.ldiff p p') n = Pos.testbit p n && negb (Pos.testbit p' n)a, a', n:Ntestbit (ldiff a a') n = testbit a n && negb (testbit a' n)a, a', n:Ntestbit (ldiff a a') n = testbit a n && negb (testbit a' n)p:positiven:NPos.testbit p n = Pos.testbit p n && truep, p0:positiven:Ntestbit (Pos.ldiff p p0) n = Pos.testbit p n && negb (Pos.testbit p0 n)apply pos_ldiff_spec. Qed.p, p0:positiven:Ntestbit (Pos.ldiff p p0) n = Pos.testbit p n && negb (Pos.testbit p0 n)
Instantiation of generic properties of advanced functions
(pow, sqrt, log2, div, gcd, ...)
Include NExtraProp.
In generic statements, the predicates lt and le have been
favored, whereas gt and ge don't even exist in the abstract
layers. The use of gt and ge is hence not recommended. We provide
here the bare minimal results to related them with lt and le.
n, m:Nn > m <-> m < nn, m:Nn > m <-> m < nnow rewrite compare_antisym, CompOpp_iff. Qed.n, m:N(n ?= m) = Gt <-> (m ?= n) = Ltn, m:Nn > m -> m < napply gt_lt_iff. Qed.n, m:Nn > m -> m < nn, m:Nn < m -> m > napply gt_lt_iff. Qed.n, m:Nn < m -> m > nn, m:Nn >= m <-> m <= nn, m:Nn >= m <-> m <= nnow rewrite compare_antisym, CompOpp_iff. Qed.n, m:N(n ?= m) <> Lt <-> (m ?= n) <> Gtn, m:Nn >= m -> m <= napply ge_le_iff. Qed.n, m:Nn >= m -> m <= nn, m:Nn <= m -> m >= napply ge_le_iff. Qed.n, m:Nn <= m -> m >= n
Auxiliary results about right shift on positive numbers,
used in BinInt
forall (p : positive) (n m : N), m < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m = trueforall (p : positive) (n m : N), m < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m = truep:positiveforall m : N, m < 0 -> testbit (Pos.pred_N (Pos.shiftl p 0)) m = truep:positiven:NIHn:forall m : N, m < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m = trueforall m : N, m < succ n -> testbit (Pos.pred_N (Pos.shiftl p (succ n))) m = truep:positiven:NIHn:forall m : N, m < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m = trueforall m : N, m < succ n -> testbit (Pos.pred_N (Pos.shiftl p (succ n))) m = truep:positiven:NIHn:forall m0 : N, m0 < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = truem:NH:m < succ ntestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = truep:positiven:NIHn:forall m0 : N, m0 < n -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = truem:NH:m < succ ntestbit (Pos.pred_N match succ n with | 0%N => p | pos n0 => Pos.iter xO p n0 end) m = truep:positiveIHn:forall m0 : N, m0 < 0 -> testbit (Pos.pred_N p) m0 = truem:NH:m < 1Pos.testbit (Pos.pred_double p) m = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)testbit (Pos.pred_N (Pos.iter xO p (Pos.succ n))) m = truep:positiveIHn:forall m : N, m < 0 -> testbit (Pos.pred_N p) m = trueH:0 < 1Pos.testbit (Pos.pred_double p) 0 = truep:positiveIHn:forall m : N, m < 0 -> testbit (Pos.pred_N p) m = truep0:positiveH:pos p0 < 1Pos.testbit (Pos.pred_double p) (pos p0) = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)testbit (Pos.pred_N (Pos.iter xO p (Pos.succ n))) m = truep:positiveIHn:forall m : N, m < 0 -> testbit (Pos.pred_N p) m = truep0:positiveH:pos p0 < 1Pos.testbit (Pos.pred_double p) (pos p0) = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)testbit (Pos.pred_N (Pos.iter xO p (Pos.succ n))) m = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)testbit (Pos.pred_N (Pos.iter xO p (Pos.succ n))) m = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)testbit (Pos.pred_N (Pos.iter xO p n)~0) m = truep, n:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N (Pos.iter xO p n)) m0 = truem:NH:m < pos (Pos.succ n)Pos.testbit (Pos.pred_double (Pos.iter xO p n)) m = truep, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:NH:m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) m = truep, n, u:positiveIHn:forall m : N, m < pos n -> testbit (Pos.pred_N u) m = trueH:0 < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) 0 = truep, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) (pos m) = truep, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) (pos m) = truep, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) (pos m) = testbit (Pos.pred_N u) (Pos.pred_N m)p, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.pred_N m < pos np, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) (pos m) = testbit (2 * Pos.pred_N u + 1) (succ (Pos.pred_N m))p, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)0 <= Pos.pred_N mp, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.pred_N m < pos np, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.testbit (Pos.pred_double u) (pos m) = testbit (2 * Pos.pred_N u + 1) (pos m)p, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)0 <= Pos.pred_N mp, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.pred_N m < pos np, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)0 <= Pos.pred_N mp, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.pred_N m < pos np, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)Pos.pred_N m < pos nnow rewrite succ_pos_pred. Qed.p, n, u:positiveIHn:forall m0 : N, m0 < pos n -> testbit (Pos.pred_N u) m0 = truem:positiveH:pos m < pos (Pos.succ n)succ (Pos.pred_N m) < succ (pos n)forall (p : positive) (n m : N), n <= m -> testbit (Pos.pred_N (Pos.shiftl p n)) m = testbit (shiftl (Pos.pred_N p) n) mforall (p : positive) (n m : N), n <= m -> testbit (Pos.pred_N (Pos.shiftl p n)) m = testbit (shiftl (Pos.pred_N p) n) mp:positivem:NH:0 <= mtestbit (Pos.pred_N (Pos.shiftl p 0)) m = testbit (shiftl (Pos.pred_N p) 0) mp:positiven:NIHn:forall m0 : N, n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = testbit (shiftl (Pos.pred_N p) n) m0m:NH:succ n <= mtestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = testbit (shiftl (Pos.pred_N p) (succ n)) mp:positivem:NH:0 <= mtestbit (Pos.pred_N (Pos.shiftl p 0)) m = testbit match Pos.pred_N p with | 0 => 0 | pos a => pos (Pos.shiftl a 0) end mp:positiven:NIHn:forall m0 : N, n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = testbit (shiftl (Pos.pred_N p) n) m0m:NH:succ n <= mtestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = testbit (shiftl (Pos.pred_N p) (succ n)) mp:positivem:NH:0 <= mtestbit (Pos.pred_N p) m = testbit match Pos.pred_N p with | 0 => 0 | pos a => pos a end mp:positiven:NIHn:forall m0 : N, n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = testbit (shiftl (Pos.pred_N p) n) m0m:NH:succ n <= mtestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = testbit (shiftl (Pos.pred_N p) (succ n)) mp:positiven:NIHn:forall m0 : N, n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = testbit (shiftl (Pos.pred_N p) n) m0m:NH:succ n <= mtestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = testbit (shiftl (Pos.pred_N p) (succ n)) mp:positiven:NIHn:forall m0 : N, n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p n)) m0 = testbit (shiftl (Pos.pred_N p) n) m0m:NH:succ n <= mtestbit (Pos.pred_N (Pos.shiftl p (succ n))) m = testbit (double (shiftl (Pos.pred_N p) n)) mp:positiveIHn:forall m0 : N, 0 <= m0 -> testbit (Pos.pred_N (Pos.shiftl p 0)) m0 = testbit (shiftl (Pos.pred_N p) 0) m0m:NH:succ 0 <= mtestbit (Pos.pred_N (Pos.shiftl p (succ 0))) m = testbit (double (shiftl (Pos.pred_N p) 0)) mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:NH:succ (pos n) <= mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) m = testbit (double (shiftl (Pos.pred_N p) (pos n))) mp:positiveIHn:forall m : N, 0 <= m -> testbit (Pos.pred_N (Pos.shiftl p 0)) m = testbit (shiftl (Pos.pred_N p) 0) mH:succ 0 <= 0testbit (Pos.pred_N (Pos.shiftl p (succ 0))) 0 = testbit (double (shiftl (Pos.pred_N p) 0)) 0p:positiveIHn:forall m0 : N, 0 <= m0 -> testbit (Pos.pred_N (Pos.shiftl p 0)) m0 = testbit (shiftl (Pos.pred_N p) 0) m0m:positiveH:succ 0 <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ 0))) (pos m) = testbit (double (shiftl (Pos.pred_N p) 0)) (pos m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:NH:succ (pos n) <= mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) m = testbit (double (shiftl (Pos.pred_N p) (pos n))) mp:positiveIHn:forall m0 : N, 0 <= m0 -> testbit (Pos.pred_N (Pos.shiftl p 0)) m0 = testbit (shiftl (Pos.pred_N p) 0) m0m:positiveH:succ 0 <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ 0))) (pos m) = testbit (double (shiftl (Pos.pred_N p) 0)) (pos m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:NH:succ (pos n) <= mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) m = testbit (double (shiftl (Pos.pred_N p) (pos n))) mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:NH:succ (pos n) <= mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) m = testbit (double (shiftl (Pos.pred_N p) (pos n))) mp, n:positiveIHn:forall m : N, pos n <= m -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m = testbit (shiftl (Pos.pred_N p) (pos n)) mH:succ (pos n) <= 0testbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) 0 = testbit (double (shiftl (Pos.pred_N p) (pos n))) 0p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) (pos m) = testbit (double (shiftl (Pos.pred_N p) (pos n))) (pos m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) (pos m) = testbit (double (shiftl (Pos.pred_N p) (pos n))) (pos m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) (succ (Pos.pred_N m)) = testbit (double (shiftl (Pos.pred_N p) (pos n))) (succ (Pos.pred_N m))p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) (succ (Pos.pred_N m)) = testbit (shiftl (Pos.pred_N p) (pos n)) (Pos.pred_N m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (Pos.pred_N (Pos.shiftl p (succ (pos n)))) (succ (Pos.pred_N m)) = testbit (Pos.pred_N (Pos.shiftl p (pos n))) (Pos.pred_N m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mtestbit (div2 (Pos.pred_N (Pos.shiftl p (succ (pos n))))) (Pos.pred_N m) = testbit (Pos.pred_N (Pos.shiftl p (pos n))) (Pos.pred_N m)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mdiv2 (Pos.pred_N (Pos.shiftl p (succ (pos n)))) = Pos.pred_N (Pos.shiftl p (pos n))p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mdiv2 (Pos.pred_N (Pos.iter xO p (Pos.succ n))) = Pos.pred_N (Pos.iter xO p n)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mdiv2 (Pos.pred_N (Pos.iter xO p n)~0) = Pos.pred_N (Pos.iter xO p n)p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mp, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos mpos n <= Pos.pred_N mnow rewrite succ_pos_pred. Qed.p, n:positiveIHn:forall m0 : N, pos n <= m0 -> testbit (Pos.pred_N (Pos.shiftl p (pos n))) m0 = testbit (shiftl (Pos.pred_N p) (pos n)) m0m:positiveH:succ (pos n) <= pos msucc (pos n) <= succ (Pos.pred_N m)p:positivePos.pred_N (Pos.div2_up p) = div2 (Pos.pred_N p)p:positivePos.pred_N (Pos.div2_up p) = div2 (Pos.pred_N p)p:positivePos.pred_N (Pos.div2_up p~1) = div2 (Pos.pred_N p~1)p:positivePos.pred_N (Pos.div2_up p~0) = div2 (Pos.pred_N p~0)p:positivePos.pred_N (Pos.succ p) = pos pp:positivePos.pred_N (Pos.div2_up p~0) = div2 (Pos.pred_N p~0)destruct p; simpl; trivial. Qed. End N. Bind Scope N_scope with N.t N.p:positivePos.pred_N (Pos.div2_up p~0) = div2 (Pos.pred_N p~0)
Exportation of notations
Numeral Notation N N.of_uint N.to_uint : N_scope. Infix "+" := N.add : N_scope. Infix "-" := N.sub : N_scope. Infix "*" := N.mul : N_scope. Infix "^" := N.pow : N_scope. Infix "?=" := N.compare (at level 70, no associativity) : N_scope. Infix "<=" := N.le : N_scope. Infix "<" := N.lt : N_scope. Infix ">=" := N.ge : N_scope. Infix ">" := N.gt : N_scope. Notation "x <= y <= z" := (x <= y /\ y <= z) : N_scope. Notation "x <= y < z" := (x <= y /\ y < z) : N_scope. Notation "x < y < z" := (x < y /\ y < z) : N_scope. Notation "x < y <= z" := (x < y /\ y <= z) : N_scope. Infix "=?" := N.eqb (at level 70, no associativity) : N_scope. Infix "<=?" := N.leb (at level 70, no associativity) : N_scope. Infix "<?" := N.ltb (at level 70, no associativity) : N_scope. Infix "/" := N.div : N_scope. Infix "mod" := N.modulo (at level 40, no associativity) : N_scope. Notation "( p | q )" := (N.divide p q) (at level 0) : N_scope.
Compatibility notations
Notation N_rect := N_rect (only parsing). Notation N_rec := N_rec (only parsing). Notation N_ind := N_ind (only parsing). Notation N0 := N0 (only parsing). Notation Npos := N.pos (only parsing). Notation Ndouble_plus_one := N.succ_double (only parsing). Notation Nplus := N.add (only parsing). Notation Nminus := N.sub (only parsing). Notation Nmult := N.mul (only parsing). Notation nat_of_N := N.to_nat (only parsing). Notation N_of_nat := N.of_nat (only parsing). Notation Nrect := N.peano_rect (only parsing). Notation Nrect_base := N.peano_rect_base (only parsing). Notation Nrect_step := N.peano_rect_succ (only parsing). Notation Nind := N.peano_ind (only parsing). Notation Nrec := N.peano_rec (only parsing). Notation Nrec_base := N.peano_rec_base (only parsing). Notation Nrec_succ := N.peano_rec_succ (only parsing). Notation Npred_minus := N.pred_sub (only parsing). Notation Ppred_N_spec := N.pos_pred_spec (only parsing). Notation Ppred_Nsucc := N.pos_pred_succ (only parsing). Notation Nplus_0_l := N.add_0_l (only parsing). Notation Nplus_0_r := N.add_0_r (only parsing). Notation Nplus_comm := N.add_comm (only parsing). Notation Nplus_assoc := N.add_assoc (only parsing). Notation Nplus_succ := N.add_succ_l (only parsing). Notation Nsucc_0 := N.succ_0_discr (only parsing). Notation Nminus_N0_Nle := N.sub_0_le (only parsing). Notation Nminus_0_r := N.sub_0_r (only parsing). Notation Nminus_succ_r:= N.sub_succ_r (only parsing). Notation Nmult_0_l := N.mul_0_l (only parsing). Notation Nmult_1_l := N.mul_1_l (only parsing). Notation Nmult_1_r := N.mul_1_r (only parsing). Notation Nmult_comm := N.mul_comm (only parsing). Notation Nmult_assoc := N.mul_assoc (only parsing). Notation Nmult_plus_distr_r := N.mul_add_distr_r (only parsing). Notation Nle_0 := N.le_0_l (only parsing). Notation Ncompare_Eq_eq := N.compare_eq (only parsing). Notation Ncompare_eq_correct := N.compare_eq_iff (only parsing). Notation Nle_lteq := N.lt_eq_cases (only parsing). Notation Ncompare_0 := N.compare_0_r (only parsing). Notation Ndouble_div2 := N.div2_double (only parsing). Notation Ndouble_plus_one_div2 := N.div2_succ_double (only parsing). Notation Ndouble_plus_one_inj := N.succ_double_inj (only parsing). Notation Nlt_not_eq := N.lt_neq (only parsing). Notation Ngt_Nlt := N.gt_lt (only parsing).
More complex compatibility facts, expressed as lemmas
(to preserve scopes for instance)
Proof (proj1 (N.add_cancel_l m p n)).n, m, p:Nn + m = n + p -> m = pProof (eq_trans (N.mul_succ_l n m) (N.add_comm _ _)).n, m:NN.succ n * m = m + n * mProof (N.mul_add_distr_l p n m).n, m, p:Np * (n + m) = p * n + p * mProof (fun H => proj1 (N.mul_cancel_r n m p H)).n, m, p:Np <> 0 -> n * p = m * p -> n = mProof (eq_sym (N.compare_antisym n m)). Definition N_ind_double a P f0 f2 fS2 := N.binary_ind P f0 f2 fS2 a. Definition N_rec_double a P f0 f2 fS2 := N.binary_rec P f0 f2 fS2 a.n, m:NCompOpp (n ?= m) = (m ?= n)
Not kept : Ncompare_n_Sm Nplus_lt_cancel_l