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) *) (************************************************************************) (* Evgeny Makarov, INRIA, 2007 *) (************************************************************************) Require Import NAxioms NProperties OrdersFacts.
Implementation of NAxiomsSig by nat
Module Nat
<: NAxiomsSig
<: UsualDecidableTypeFull
<: OrderedTypeFull
<: TotalOrder.
Operations over nat are defined in a separate module
Include Coq.Init.Nat.
When including property functors, inline t eq zero one two lt le succ
Set Inline Level 50.
All operations are well-defined (trivial here since eq is Leibniz)
Definition eq_equiv : Equivalence (@eq nat) := eq_equivalence. Local Obligation Tactic := simpl_relation. Instance succ_wd : Proper (eq==>eq) S. Instance pred_wd : Proper (eq==>eq) pred. Instance add_wd : Proper (eq==>eq==>eq) plus. Instance sub_wd : Proper (eq==>eq==>eq) minus. Instance mul_wd : Proper (eq==>eq==>eq) mult. Instance pow_wd : Proper (eq==>eq==>eq) pow. Instance div_wd : Proper (eq==>eq==>eq) div. Instance mod_wd : Proper (eq==>eq==>eq) modulo. Instance lt_wd : Proper (eq==>eq==>iff) lt. Instance testbit_wd : Proper (eq==>eq==>eq) testbit.
Bi-directional induction.
forall A : nat -> Prop, Proper (eq ==> iff) A -> A 0 -> (forall n : nat, A n <-> A (S n)) -> forall n : nat, A nforall A : nat -> Prop, Proper (eq ==> iff) A -> A 0 -> (forall n : nat, A n <-> A (S n)) -> forall n : nat, A nA:nat -> PropA_wd:Proper (eq ==> iff) AA0:A 0AS:forall n : nat, A n <-> A (S n)forall n : nat, A nA:nat -> PropA_wd:Proper (eq ==> iff) AA0:A 0AS:forall n : nat, A n <-> A (S n)A 0A:nat -> PropA_wd:Proper (eq ==> iff) AA0:A 0AS:forall n : nat, A n <-> A (S n)forall n : nat, A n -> A (S n)intros; now apply -> AS. Qed.A:nat -> PropA_wd:Proper (eq ==> iff) AA0:A 0AS:forall n : nat, A n <-> A (S n)forall n : nat, A n -> A (S n)
Recursion function
Definition recursion {A} : A -> (nat -> A -> A) -> nat -> A := nat_rect (fun _ => A).A:TypeAeq:relation AProper (Aeq ==> (eq ==> Aeq ==> Aeq) ==> eq ==> Aeq) recursionA:TypeAeq:relation AProper (Aeq ==> (eq ==> Aeq ==> Aeq) ==> eq ==> Aeq) recursionA:TypeAeq:relation Aa, a':AHa:Aeq a a'f, f':nat -> A -> AHf:(eq ==> Aeq ==> Aeq)%signature f f'n, n':natHn:n = n'Aeq (recursion a f n) (recursion a' f' n')A:TypeAeq:relation Aa, a':AHa:Aeq a a'f, f':nat -> A -> AHf:(eq ==> Aeq ==> Aeq)%signature f f'n:natAeq (recursion a f n) (recursion a' f' n)apply Hf; auto. Qed.A:TypeAeq:relation Aa, a':AHa:Aeq a a'f, f':nat -> A -> AHf:(eq ==> Aeq ==> Aeq)%signature f f'n:natIHn:Aeq (recursion a f n) (recursion a' f' n)Aeq (f n (recursion a f n)) (f' n (recursion a' f' n))forall (A : Type) (a : A) (f : nat -> A -> A), recursion a f 0 = areflexivity. Qed.forall (A : Type) (a : A) (f : nat -> A -> A), recursion a f 0 = aforall (A : Type) (Aeq : relation A) (a : A) (f : nat -> A -> A), Aeq a a -> Proper (eq ==> Aeq ==> Aeq) f -> forall n : nat, Aeq (recursion a f (S n)) (f n (recursion a f n))unfold Proper, respectful in *; induction n; simpl; auto. Qed.forall (A : Type) (Aeq : relation A) (a : A) (f : nat -> A -> A), Aeq a a -> Proper (eq ==> Aeq ==> Aeq) f -> forall n : nat, Aeq (recursion a f (S n)) (f n (recursion a f n))
NB: Aliasing le is mandatory, since only a Definition can implement
an interface Parameter...
Definition eq := @Logic.eq nat. Definition le := Peano.le. Definition lt := Peano.lt.
n:natpred (S n) = nreflexivity. Qed.n:natpred (S n) = npred 0 = 0reflexivity. Qed.pred 0 = 01 = 1reflexivity. Qed.1 = 12 = 2reflexivity. Qed.2 = 2n:nat0 + n = nreflexivity. Qed.n:nat0 + n = nn, m:natS n + m = S (n + m)reflexivity. Qed.n, m:natS n + m = S (n + m)n:natn - 0 = nnow destruct n. Qed.n:natn - 0 = nn, m:natn - S m = pred (n - m)n, m:natn - S m = pred (n - m)n:natforall m : nat, n - S m = pred (n - m)apply sub_0_r. Qed.n:natIHn:forall m : nat, n - S m = pred (n - m)n - 0 = nn:nat0 * n = 0reflexivity. Qed.n:nat0 * n = 0n, m:natS n * m = n * m + mn, m:natS n * m = n * m + mn, m:natsucc_r:forall x y : nat, x + S y = S (x + y)S n * m = n * m + mn, m:natsucc_r:forall x y : nat, x + S y = S (x + y)forall x y : nat, x + y = y + xn, m:natsucc_r:forall x y : nat, x + S y = S (x + y)comm:forall x y : nat, x + y = y + xS n * m = n * m + mn, m:natsucc_r:forall x y : nat, x + S y = S (x + y)forall x y : nat, x + y = y + xintros; rewrite succ_r; now f_equal.n, m:natsucc_r:forall x0 y : nat, x0 + S y = S (x0 + y)x:natIHx:forall y : nat, x + y = y + xforall y : nat, S (x + y) = y + S xnow rewrite comm. Qed.n, m:natsucc_r:forall x y : nat, x + S y = S (x + y)comm:forall x y : nat, x + y = y + xS n * m = n * m + mn, m:natn < S m <-> n <= mn, m:natn < S m <-> n <= mn, m:natn < S m -> n <= mn, m:natn <= m -> n < S minduction 1; auto. Qed.n, m:natn <= m -> n < S m
n, m:nat(n =? m) = true <-> n = mn, m:nat(n =? m) = true <-> n = mn:natforall m : nat, (n =? m) = true <-> n = mn:natIHn:forall m0 : nat, (n =? m0) = true <-> n = m0m:natn = m -> S n = S mn:natIHn:forall m0 : nat, (n =? m0) = true <-> n = m0m:natS n = S m -> n = mnow intros ->.n:natIHn:forall m0 : nat, (n =? m0) = true <-> n = m0m:natn = m -> S n = S mnow injection 1. Qed.n:natIHn:forall m0 : nat, (n =? m0) = true <-> n = m0m:natS n = S m -> n = mn, m:nat(n <=? m) = true <-> n <= mn, m:nat(n <=? m) = true <-> n <= mn:natforall m : nat, (n <=? m) = true <-> n <= mtrue = true <-> 0 <= 0m:nattrue = true <-> 0 <= S mn:natIHn:forall m : nat, (n <=? m) = true <-> n <= mfalse = true <-> S n <= 0n:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:nat(n <=? m) = true <-> S n <= S mnow split.true = true <-> 0 <= 0m:nattrue = true <-> 0 <= S mintros; apply Peano.le_0_n.m:nattrue = true -> 0 <= S mnow split.n:natIHn:forall m : nat, (n <=? m) = true <-> n <= mfalse = true <-> S n <= 0n:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:nat(n <=? m) = true <-> S n <= S mn:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:natn <= m -> S n <= S mn:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:natS n <= S m -> n <= mapply Peano.le_n_S.n:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:natn <= m -> S n <= S mapply Peano.le_S_n. Qed.n:natIHn:forall m0 : nat, (n <=? m0) = true <-> n <= m0m:natS n <= S m -> n <= mn, m:nat(n <? m) = true <-> n < mapply leb_le. Qed.n, m:nat(n <? m) = true <-> n < m
forall n m : nat, {n = m} + {n <> m}forall n m : nat, {n = m} + {n <> m}{0 = 0} + {0 <> 0}m:nat{0 = S m} + {0 <> S m}n:natIHn:forall m : nat, {n = m} + {n <> m}{S n = 0} + {S n <> 0}n:natIHn:forall m0 : nat, {n = m0} + {n <> m0}m:nat{S n = S m} + {S n <> S m}now left.{0 = 0} + {0 <> 0}now right.m:nat{0 = S m} + {0 <> S m}now right.n:natIHn:forall m : nat, {n = m} + {n <> m}{S n = 0} + {S n <> 0}destruct (IHn m); [left|right]; auto. Defined.n:natIHn:forall m0 : nat, {n = m0} + {n <> m0}m:nat{S n = S m} + {S n <> S m}
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
n, m:nat(n ?= m) = Eq <-> n = mrevert m; induction n; destruct m; simpl; rewrite ?IHn; split; auto; easy. Qed.n, m:nat(n ?= m) = Eq <-> n = mn, m:nat(n ?= m) = Lt <-> n < mn, m:nat(n ?= m) = Lt <-> n < mm:natLt = Lt -> 0 < S mn:natIHn:forall m0 : nat, (n ?= m0) = Lt <-> n < m0m:natn < m -> S n < S mn:natIHn:forall m0 : nat, (n ?= m0) = Lt <-> n < m0m:natS n < S m -> n < mm:natLt = Lt -> 0 < S mapply Peano.le_n_S, Peano.le_0_n.m:nat0 < S mapply Peano.le_n_S.n:natIHn:forall m0 : nat, (n ?= m0) = Lt <-> n < m0m:natn < m -> S n < S mapply Peano.le_S_n. Qed.n:natIHn:forall m0 : nat, (n ?= m0) = Lt <-> n < m0m:natS n < S m -> n < mn, m:nat(n ?= m) <> Gt <-> n <= mn, m:nat(n ?= m) <> Gt <-> n <= mEq <> Gt <-> 0 <= 0m:natLt <> Gt <-> 0 <= S mn:natIHn:forall m : nat, (n ?= m) <> Gt <-> n <= mGt <> Gt <-> S n <= 0n:natIHn:forall m0 : nat, (n ?= m0) <> Gt <-> n <= m0m:natn <= m <-> S n <= S mnow split.Eq <> Gt <-> 0 <= 0m:natLt <> Gt <-> 0 <= S mm:natH:Lt <> Gt0 <= S mm:natH:0 <= S mLt <> Gteasy.m:natH:0 <= S mLt <> Gtn:natIHn:forall m : nat, (n ?= m) <> Gt <-> n <= mGt <> Gt <-> S n <= 0n:natIHn:forall m : nat, (n ?= m) <> Gt <-> n <= mGt <> Gt -> S n <= 0n:natIHn:forall m : nat, (n ?= m) <> Gt <-> n <= mS n <= 0 -> Gt <> Gtinversion 1.n:natIHn:forall m : nat, (n ?= m) <> Gt <-> n <= mS n <= 0 -> Gt <> Gtn:natIHn:forall m0 : nat, (n ?= m0) <> Gt <-> n <= m0m:natn <= m <-> S n <= S mn:natIHn:forall m0 : nat, (n ?= m0) <> Gt <-> n <= m0m:natH:n <= mS n <= S mn:natIHn:forall m0 : nat, (n ?= m0) <> Gt <-> n <= m0m:natH:S n <= S mn <= mnow apply Peano.le_S_n. Qed.n:natIHn:forall m0 : nat, (n ?= m0) <> Gt <-> n <= m0m:natH:S n <= S mn <= mn, m:nat(m ?= n) = CompOpp (n ?= m)revert m; induction n; destruct m; simpl; trivial. Qed.n, m:nat(m ?= n) = CompOpp (n ?= m)n, m:nat(S n ?= S m) = (n ?= m)reflexivity. Qed. (* BUG: Ajout d'un cas * après preuve finie (deuxième niveau +++*** ) : * ---> Anomaly: Uncaught exception Proofview.IndexOutOfRange(_). Please report. *)n, m:nat(S n ?= S m) = (n ?= m)
forall n m : nat, m <= n -> max n m = nexact Peano.max_l. Qed.forall n m : nat, m <= n -> max n m = nforall n m : nat, n <= m -> max n m = mexact Peano.max_r. Qed.forall n m : nat, n <= m -> max n m = mforall n m : nat, n <= m -> min n m = nexact Peano.min_l. Qed.forall n m : nat, n <= m -> min n m = nforall n m : nat, m <= n -> min n m = mexact Peano.min_r. Qed.forall n m : nat, m <= n -> min n m = m
Some more advanced properties of comparison and orders,
including compare_spec and lt_irrefl and lt_eq_cases.
Include BoolOrderFacts.
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.
inversion 1. Qed.a, b:natb < 0 -> a ^ b = 0a:nata ^ 0 = 1reflexivity. Qed.a:nata ^ 0 = 1a, b:nat0 <= b -> a ^ S b = a * a ^ breflexivity. Qed.a, b:nat0 <= b -> a ^ S b = a * a ^ b
n:natsquare n = n * nreflexivity. Qed.n:natsquare n = n * n
Definition Even n := exists m, n = 2*m. Definition Odd n := exists m, n = 2*m+1. Module Private_Parity.~ Even 1~ Even 1n:natH:1 = 2 * S nFalsenow rewrite <- plus_n_Sm in H. Qed.n:natH:1 = S (n + S (n + 0))Falsen:natEven n <-> Even (S (S n))n:natEven n <-> Even (S (S n))n, m:natH:n = 2 * mEven (S (S n))n, m:natH:S (S n) = 2 * mEven nn, m:natH:n = 2 * mEven (S (S n))n, m:natH:n = 2 * mS (S n) = 2 * S mn, m:natH:n = 2 * mS (S (2 * m)) = 2 * S mnow rewrite plus_n_Sm.n, m:natH:n = 2 * mS (S (m + (m + 0))) = S (m + S (m + 0))n, m:natH:S (S n) = 2 * mEven nn, m:natH:S (S n) = 2 * S mEven nn, m:natH:S (S n) = 2 * S mn = 2 * mn, m:natH:S (S n) = S (m + S (m + 0))n = 2 * mnow inversion H. Qed.n, m:natH:S (S n) = S (S (m + (m + 0)))n = 2 * m~ Odd 0now intros ([|], H). Qed.~ Odd 0n:natOdd n <-> Odd (S (S n))n:natOdd n <-> Odd (S (S n))n, m:natH:n = 2 * m + 1Odd (S (S n))n, m:natH:S (S n) = 2 * m + 1Odd nn, m:natH:n = 2 * m + 1Odd (S (S n))n, m:natH:n = 2 * m + 1S (S n) = 2 * S m + 1n, m:natH:n = 2 * m + 1S (S (2 * m + 1)) = 2 * S m + 1now rewrite <- (plus_n_Sm m).n, m:natH:n = 2 * m + 1S (S (m + (m + 0) + 1)) = S (m + S (m + 0) + 1)n, m:natH:S (S n) = 2 * m + 1Odd nn, m:natH:S (S n) = 2 * S m + 1Odd nn, m:natH:S (S n) = 2 * S m + 1n = 2 * m + 1n, m:natH:S (S n) = S (m + S (m + 0) + 1)n = 2 * m + 1n, m:natH:S (S n) = S (S (m + S (m + 0) + 0))n = 2 * m + 1n, m:natH:S (S n) = S (S (m + S (m + 0) + 0))H1:n = m + S (m + 0) + 0m + S (m + 0) + 0 = 2 * m + 1now rewrite <- !plus_n_Sm, <- !plus_n_O. Qed. End Private_Parity. Import Private_Parity.n, m:natH:S (S n) = S (S (m + S (m + 0) + 0))H1:n = m + S (m + 0) + 0m + S (m + 0) + 0 = m + (m + 0) + 1forall n : nat, even n = true <-> Even nforall n : nat, even n = true <-> Even neven_spec:forall n : nat, even n = true <-> Even nforall n : nat, even n = true <-> Even neven_spec:forall n : nat, even n = true <-> Even ntrue = true <-> Even 0even_spec:forall n : nat, even n = true <-> Even nfalse = true <-> Even 1even_spec:forall n0 : nat, even n0 = true <-> Even n0n:nateven n = true <-> Even (S (S n))split; [ now exists 0 | trivial ].even_spec:forall n : nat, even n = true <-> Even ntrue = true <-> Even 0split; [ discriminate | intro H; elim (Even_1 H) ].even_spec:forall n : nat, even n = true <-> Even nfalse = true <-> Even 1even_spec:forall n0 : nat, even n0 = true <-> Even n0n:nateven n = true <-> Even (S (S n))apply Even_2. Qed.even_spec:forall n0 : nat, even n0 = true <-> Even n0n:natEven n <-> Even (S (S n))forall n : nat, odd n = true <-> Odd nforall n : nat, odd n = true <-> Odd nforall n : nat, negb (even n) = true <-> Odd nodd_spec:forall n : nat, negb (even n) = true <-> Odd nforall n : nat, negb (even n) = true <-> Odd nodd_spec:forall n : nat, negb (even n) = true <-> Odd nfalse = true <-> Odd 0odd_spec:forall n : nat, negb (even n) = true <-> Odd ntrue = true <-> Odd 1odd_spec:forall n0 : nat, negb (even n0) = true <-> Odd n0n:natnegb (even n) = true <-> Odd (S (S n))split; [ discriminate | intro H; elim (Odd_0 H) ].odd_spec:forall n : nat, negb (even n) = true <-> Odd nfalse = true <-> Odd 0split; [ now exists 0 | trivial ].odd_spec:forall n : nat, negb (even n) = true <-> Odd ntrue = true <-> Odd 1odd_spec:forall n0 : nat, negb (even n0) = true <-> Odd n0n:natnegb (even n) = true <-> Odd (S (S n))apply Odd_2. Qed.odd_spec:forall n0 : nat, negb (even n0) = true <-> Odd n0n:natOdd n <-> Odd (S (S n))
forall x y q u : nat, u <= y -> let (q', u') := divmod x y q u in x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yforall x y q u : nat, u <= y -> let (q', u') := divmod x y q u in x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yforall y q u : nat, u <= y -> let (q', u') := divmod 0 y q u in 0 + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y q u : nat, u <= y -> let (q', u') := divmod x y q u in x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yforall y q u : nat, u <= y -> let (q', u') := divmod (S x) y q u in S x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= ysimpl; intuition.forall y q u : nat, u <= y -> let (q', u') := divmod 0 y q u in 0 + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y q u : nat, u <= y -> let (q', u') := divmod x y q u in x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yforall y q u : nat, u <= y -> let (q', u') := divmod (S x) y q u in S x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:u <= ylet (q', u') := divmod (S x) y q u in S x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q', u') := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q' + (y0 - u') /\ u' <= y0y, q:natH:0 <= ylet (q', u') := divmod x y (S q) y in S x + S y * q + (y - 0) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= ylet (q', u') := divmod x y q u in S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q', u') := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q' + (y0 - u') /\ u' <= y0y, q:natH:0 <= ylet (q', u') := divmod x y (S q) y in S x + S y * q + (y - 0) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q', u') := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q' + (y0 - u') /\ u' <= y0y, q:natH:0 <= y(let (q', u') := divmod x y (S q) y in x + S y * S q + (y - y) = S y * q' + (y - u') /\ u' <= y) -> let (q', u') := divmod x y (S q) y in S x + S y * q + (y - 0) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q'0, u'0) := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q:natH:0 <= yq', u':natx + S y * S q + (y - y) = S y * q' + (y - u') /\ u' <= y -> S x + S y * q + (y - 0) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q'0, u'0) := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q:natH:0 <= yq', u':natEQ:x + S y * S q + (y - y) = S y * q' + (y - u')LE:u' <= yS x + S y * q + (y - 0) = S y * q' + (y - u')now rewrite !add_succ_l, <- add_succ_r, <- add_assoc, mul_succ_r.x:natIHx:forall y0 q0 u : nat, u <= y0 -> let (q'0, u'0) := divmod x y0 q0 u in x + S y0 * q0 + (y0 - u) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q:natH:0 <= yq', u':natEQ:x + S y * S q + (y - y) = S y * q' + (y - u')LE:u' <= yS x + S y * q + y = x + S y * S qx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= ylet (q', u') := divmod x y q u in S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yu <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yH':u <= ylet (q', u') := divmod x y q u in S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yu <= ydo 2 constructor.x:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yu <= S ux:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yH':u <= ylet (q', u') := divmod x y q u in S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q', u') := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q' + (y0 - u') /\ u' <= y0y, q, u:natH:S u <= yH':u <= y(let (q', u') := divmod x y q u in x + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= y) -> let (q', u') := divmod x y q u in S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q'0, u'0) := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q, u:natH:S u <= yH':u <= yq', u':natx + S y * q + (y - u) = S y * q' + (y - u') /\ u' <= y -> S x + S y * q + (y - S u) = S y * q' + (y - u') /\ u' <= yx:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q'0, u'0) := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q, u:natH:S u <= yH':u <= yq', u':natEQ:x + S y * q + (y - u) = S y * q' + (y - u')LE:u' <= yS x + S y * q + (y - S u) = S y * q' + (y - u')x:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q'0, u'0) := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q, u:natH:S u <= yH':u <= yq', u':natEQ:x + S y * q + (y - u) = S y * q' + (y - u')LE:u' <= yS x + S y * q + (y - S u) = x + S y * q + (y - u)x:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q'0, u'0) := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q, u:natH:S u <= yH':u <= yq', u':natEQ:x + S y * q + (y - u) = S y * q' + (y - u')LE:u' <= yx + S y * q + S (y - S u) = x + S y * q + (y - u)now rewrite <- sub_succ_l. Qed.x:natIHx:forall y0 q0 u0 : nat, u0 <= y0 -> let (q'0, u'0) := divmod x y0 q0 u0 in x + S y0 * q0 + (y0 - u0) = S y0 * q'0 + (y0 - u'0) /\ u'0 <= y0y, q, u:natH:S u <= yH':u <= yq', u':natEQ:x + S y * q + (y - u) = S y * q' + (y - u')LE:u' <= yS (y - S u) = y - ux, y:naty <> 0 -> x = y * (x / y) + x mod yx, y:naty <> 0 -> x = y * (x / y) + x mod yx, y:natHy:y <> 0x = y * (x / y) + x mod yx, y:natx = S y * (x / S y) + x mod S yx, y:natx = S y * fst (divmod x y 0 y) + (y - snd (divmod x y 0 y))x, y:nat(let (q', u') := divmod x y 0 y in x + S y * 0 + (y - y) = S y * q' + (y - u') /\ u' <= y) -> x = S y * fst (divmod x y 0 y) + (y - snd (divmod x y 0 y))x, y, q, u:natx + S y * 0 + (y - y) = S y * q + (y - u) /\ u <= y -> x = S y * fst (q, u) + (y - snd (q, u))x, y, q, u:natU:x + S y * 0 + (y - y) = S y * q + (y - u)V:u <= yx = S y * fst (q, u) + (y - snd (q, u))now rewrite mul_0_r, sub_diag, !add_0_r in U. Qed.x, y, q, u:natU:x + y * 0 + (y - y) = q + y * q + (y - u)V:u <= yx = q + y * q + (y - u)x, y:nat0 <= x -> 0 < y -> 0 <= x mod y < yx, y:nat0 <= x -> 0 < y -> 0 <= x mod y < yx, y:natHx:0 <= xHy:0 < y0 <= x mod y < yx, y:natHx:0 <= xHy:0 < y0 <= x mod yx, y:natHx:0 <= xHy:0 < yx mod y < yx, y:natHx:0 <= xHy:0 < yx mod y < yx, y:natHx:0 <= xx mod S y < S yapply lt_succ_r, le_sub_l. Qed.x, y:natHx:0 <= xy - snd (divmod x y 0 y) < S y
forall k p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter k p q r in s * s <= k + p * p + (q - r) < S s * S sforall k p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter k p q r in s * s <= k + p * p + (q - r) < S s * S sforall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter 0 p q r in s * s <= 0 + p * p + (q - r) < S s * S sk:natIHk:forall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter k p q r in s * s <= k + p * p + (q - r) < S s * S sforall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter (S k) p q r in s * s <= S k + p * p + (q - r) < S s * S sforall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter 0 p q r in s * s <= 0 + p * p + (q - r) < S s * S sp, q, r:natHq:q = p + pHr:r <= qp * p <= p * p + (q - r) < S (p + p * S p)p, q, r:natHq:q = p + pHr:r <= qp * p <= p * p + (q - r)p, q, r:natHq:q = p + pHr:r <= qp * p + (q - r) < S (p + p * S p)apply le_add_r.p, q, r:natHq:q = p + pHr:r <= qp * p <= p * p + (q - r)p, q, r:natHq:q = p + pHr:r <= qp * p + (q - r) < S (p + p * S p)p, q, r:natHq:q = p + pHr:r <= qp * p + (q - r) <= p + p * S pp, q, r:natHq:q = p + pHr:r <= qp * p + (q - r) <= p + (p * p + p)p, q, r:natHq:q = p + pHr:r <= qp * p + (q - r) <= p * p + (p + p)p, q, r:natHq:q = p + pHr:r <= qq - r <= p + papply le_sub_l.p, q, r:natHq:q = p + pHr:r <= qq - r <= qk:natIHk:forall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter k p q r in s * s <= k + p * p + (q - r) < S s * S sforall p q r : nat, q = p + p -> r <= q -> let s := sqrt_iter (S k) p q r in s * s <= S k + p * p + (q - r) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natq = p + p -> 0 <= q -> let s := sqrt_iter (S k) p q 0 in s * s <= S k + p * p + (q - 0) < S s * S sk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natq = p + p -> S r <= q -> let s := sqrt_iter (S k) p q (S r) in s * s <= S k + p * p + (q - S r) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natq = p + p -> 0 <= q -> let s := sqrt_iter (S k) p q 0 in s * s <= S k + p * p + (q - 0) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + plet s := sqrt_iter (S k) p q 0 in s * s <= S k + p * p + (q - 0) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + plet s := sqrt_iter (S k) p q 0 in s * s <= k + S p * S p + (S (S q) - S (S q)) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pk + S p * S p + (S (S q) - S (S q)) = S k + p * p + (q - 0)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + plet s := sqrt_iter (S k) p q 0 in s * s <= k + S p * S p + (S (S q) - S (S q)) < S s * S sk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pS (S q) = S p + S pk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pS (S q) <= S (S q)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pS (S q) = S (p + S p)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pS (S q) <= S (S q)apply le_n.k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pS (S q) <= S (S q)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pk + S p * S p + (S (S q) - S (S q)) = S k + p * p + (q - 0)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pk + S p * S p = S k + p * p + qk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pk + S (p + p * S p) = S (k + p * p + q)k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pk + (p + p * S p) = k + p * p + qk:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pp + p * S p = p * p + qnow f_equal.k:natIHk:forall p0 q0 r : nat, q0 = p0 + p0 -> r <= q0 -> let s := sqrt_iter k p0 q0 r in s * s <= k + p0 * p0 + (q0 - r) < S s * S sp, q:natHq:q = p + pp * p + (p + p) = p * p + qk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natq = p + p -> S r <= q -> let s := sqrt_iter (S k) p q (S r) in s * s <= S k + p * p + (q - S r) < S s * S sk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qlet s := sqrt_iter (S k) p q (S r) in s * s <= S k + p * p + (q - S r) < S s * S sk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qlet s := sqrt_iter (S k) p q (S r) in s * s <= k + p * p + (q - r) < S s * S sk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qk + p * p + (q - r) = S k + p * p + (q - S r)k:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qlet s := sqrt_iter (S k) p q (S r) in s * s <= k + p * p + (q - r) < S s * S sk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qr <= qdo 2 constructor.k:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qr <= S rk:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qk + p * p + (q - r) = S k + p * p + (q - S r)k:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qk + p * p + (q - r) = S (k + p * p + (q - S r))k:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qk + p * p + (q - r) = k + p * p + S (q - S r)rewrite <- sub_succ_l; trivial. Qed.k:natIHk:forall p0 q0 r0 : nat, q0 = p0 + p0 -> r0 <= q0 -> let s := sqrt_iter k p0 q0 r0 in s * s <= k + p0 * p0 + (q0 - r0) < S s * S sp, q, r:natHq:q = p + pHr:S r <= qq - r = S (q - S r)n:natsqrt n * sqrt n <= n < S (sqrt n) * S (sqrt n)n:natsqrt n * sqrt n <= n < S (sqrt n) * S (sqrt n)n:nats:=sqrt n:nats * s <= n < S s * S sn:nats:=sqrt n:nats * s <= n + 0 * 0 + (0 - 0) < S s * S sn:nats:=sqrt n:natn + 0 * 0 + (0 - 0) = nn:nats:=sqrt n:natn + 0 * 0 + (0 - 0) = nnow rewrite !add_0_r. Qed. Definition sqrt_spec a (Ha:0<=a) := sqrt_specif a.n:nats:=sqrt n:natn + 0 + 0 = na:nata < 0 -> sqrt a = 0inversion 1. Qed.a:nata < 0 -> sqrt a = 0
forall k p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter k p q r in 2 ^ s <= k + q < 2 ^ S sforall k p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter k p q r in 2 ^ s <= k + q < 2 ^ S sforall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter 0 p q r in 2 ^ s <= 0 + q < 2 ^ S sk:natIHk:forall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter k p q r in 2 ^ s <= k + q < 2 ^ S sforall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter (S k) p q r in 2 ^ s <= S k + q < 2 ^ S sforall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter 0 p q r in 2 ^ s <= 0 + q < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ plet s := log2_iter 0 p q r in 2 ^ s <= 0 + q < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ plet s := p in 2 ^ s <= 0 + q < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p2 ^ p <= 0 + q < 2 ^ S pp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p2 ^ p <= 0 + qp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p0 + q < 2 ^ S pp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p2 ^ p <= 0 + qp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p2 ^ p <= qp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p2 ^ p + 2 ^ p <= 2 ^ p + qp, q, r:natEQ:2 ^ p + (2 ^ p + 0) = q + S rLT:r < 2 ^ p2 ^ p + 2 ^ p <= 2 ^ p + qp, q, r:natEQ:2 ^ p + 2 ^ p = q + S rLT:r < 2 ^ p2 ^ p + 2 ^ p <= 2 ^ p + qp, q, r:natEQ:2 ^ p + 2 ^ p = q + S rLT:r < 2 ^ pq + S r <= 2 ^ p + qp, q, r:natEQ:2 ^ p + 2 ^ p = q + S rLT:r < 2 ^ pS r + q <= 2 ^ p + qapply LT.p, q, r:natEQ:2 ^ p + 2 ^ p = q + S rLT:r < 2 ^ pS r <= 2 ^ pp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p0 + q < 2 ^ S pp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ pq + 0 < q + S rapply lt_succ_r, le_0_l.p, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ p0 < S rk:natIHk:forall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter k p q r in 2 ^ s <= k + q < 2 ^ S sforall p q r : nat, 2 ^ S p = q + S r -> r < 2 ^ p -> let s := log2_iter (S k) p q r in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S rLT:r < 2 ^ plet s := log2_iter (S k) p q r in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = q + 1LT:0 < 2 ^ plet s := log2_iter (S k) p q 0 in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ plet s := log2_iter (S k) p q (S r) in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = q + 1LT:0 < 2 ^ plet s := log2_iter (S k) p q 0 in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ plet s := log2_iter (S k) p q 0 in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ plet s := log2_iter (S k) p q 0 in 2 ^ s <= k + S q < 2 ^ S sk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ p2 ^ S (S p) = S q + S qk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ pq < 2 ^ S pk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ p2 ^ S (S p) = S q + S qk:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ p2 ^ S (S p) = 2 ^ S p + 2 ^ S pnow rewrite add_0_r.k:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q, p':natHeqp':p' = S pEQ:2 ^ p' = S qLT:0 < 2 ^ p2 ^ p' + (2 ^ p' + 0) = 2 ^ p' + 2 ^ p'k:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ pq < 2 ^ S pconstructor.k:natIHk:forall p0 q0 r : nat, 2 ^ S p0 = q0 + S r -> r < 2 ^ p0 -> let s := log2_iter k p0 q0 r in 2 ^ s <= k + q0 < 2 ^ S sp, q:natEQ:2 ^ S p = S qLT:0 < 2 ^ pq < S qk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ plet s := log2_iter (S k) p q (S r) in 2 ^ s <= S k + q < 2 ^ S sk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ plet s := log2_iter (S k) p q (S r) in 2 ^ s <= k + S q < 2 ^ S sk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ p2 ^ S p = S q + S rk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ pr < 2 ^ pnow rewrite add_succ_l, <- add_succ_r.k:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ p2 ^ S p = S q + S rk:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ pr < 2 ^ pdo 2 constructor. Qed.k:natIHk:forall p0 q0 r0 : nat, 2 ^ S p0 = q0 + S r0 -> r0 < 2 ^ p0 -> let s := log2_iter k p0 q0 r0 in 2 ^ s <= k + q0 < 2 ^ S sp, q, r:natEQ:2 ^ S p = q + S (S r)LT:S r < 2 ^ pr <= S rn:nat0 < n -> 2 ^ log2 n <= n < 2 ^ S (log2 n)n:nat0 < n -> 2 ^ log2 n <= n < 2 ^ S (log2 n)n:natH:0 < n2 ^ log2 n <= n < 2 ^ S (log2 n)n:natH:0 < ns:=log2 n:nat2 ^ s <= n < 2 ^ S sn:natH:0 < ns:=log2 n:nat2 ^ s <= pred n + 1 < 2 ^ S sn:natH:0 < ns:=log2 n:natpred n + 1 = nn:natH:0 < ns:=log2 n:natpred n + 1 = nn:natH:0 < ns:=log2 n:natS (pred n) = nnow apply neq_sym, lt_neq. Qed.n:natH:0 < ns:=log2 n:natn <> 0n:natn <= 0 -> log2 n = 0inversion 1; now subst. Qed.n:natn <= 0 -> log2 n = 0
Definition divide x y := exists z, y=z*x. Notation "( x | y )" := (divide x y) (at level 0) : nat_scope.forall a b : nat, (gcd a b | a) /\ (gcd a b | b)forall a b : nat, (gcd a b | a) /\ (gcd a b | b)gcd_divide:forall a b : nat, (gcd a b | a) /\ (gcd a b | b)forall a b : nat, (gcd a b | a) /\ (gcd a b | b)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:nat(b | 0) /\ (b | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:nat(b | 0)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:nat(b | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:nat(b | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:natb = 1 * bgcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a b0 : nat, (gcd a b0 | a) /\ (gcd a b0 | b0)b:natb = b + 0gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (a - snd (divmod b a 0 a)) (S a) | S a) /\ (gcd (a - snd (divmod b a 0 a)) (S a) | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nat(gcd (b mod S a) (S a) | S a) /\ (gcd (b mod S a) (S a) | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:natH:(gcd (b mod S a) (S a) | b mod S a)H':(gcd (b mod S a) (S a) | S a)(gcd (b mod S a) (S a) | S a) /\ (gcd (b mod S a) (S a) | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natH:(gcd (b mod a') a' | b mod a')H':(gcd (b mod a') a' | a')(gcd (b mod a') a' | a') /\ (gcd (b mod a') a' | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natH:(gcd (b mod a') a' | b mod a')H':(gcd (b mod a') a' | a')(gcd (b mod a') a' | b)gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natH:(gcd (b mod a') a' | b mod a')H':(gcd (b mod a') a' | a')(gcd (b mod a') a' | a' * (b / a') + b mod a')gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natu:natHu:b mod a' = u * gcd (b mod a') a'v:natHv:a' = v * gcd (b mod a') a'(gcd (b mod a') a' | a' * (b / a') + b mod a')gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natu:natHu:b mod a' = u * gcd (b mod a') a'v:natHv:a' = v * gcd (b mod a') a'(gcd (b mod a') a' | b / a' * a' + b mod a')gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natu:natHu:b mod a' = u * gcd (b mod a') a'v:natHv:a' = v * gcd (b mod a') a'b / a' * a' + b mod a' = (b / a' * v + u) * gcd (b mod a') a'now rewrite <- mul_assoc, <- Hv, <- Hu. Qed.gcd_divide:forall a0 b0 : nat, (gcd a0 b0 | a0) /\ (gcd a0 b0 | b0)a, b:nata':=S a:natu:natHu:b mod a' = u * gcd (b mod a') a'v:natHv:a' = v * gcd (b mod a') a'b / a' * a' + b mod a' = b / a' * v * gcd (b mod a') a' + u * gcd (b mod a') a'forall a b : nat, (gcd a b | a)forall a b : nat, (gcd a b | a)apply gcd_divide. Qed.a, b:nat(gcd a b | a)forall a b : nat, (gcd a b | b)forall a b : nat, (gcd a b | b)apply gcd_divide. Qed.a, b:nat(gcd a b | b)forall a b c : nat, (c | a) -> (c | b) -> (c | gcd a b)forall a b c : nat, (c | a) -> (c | b) -> (c | gcd a b)gcd_greatest:forall a b c : nat, (c | a) -> (c | b) -> (c | gcd a b)forall a b c : nat, (c | a) -> (c | b) -> (c | gcd a b)gcd_greatest:forall a0 b0 c : nat, (c | a0) -> (c | b0) -> (c | gcd a0 b0)a, b:natforall c : nat, (c | S a) -> (c | b) -> (c | gcd (a - snd (divmod b a 0 a)) (S a))gcd_greatest:forall a0 b0 c : nat, (c | a0) -> (c | b0) -> (c | gcd a0 b0)a, b:natforall c : nat, (c | S a) -> (c | b) -> (c | gcd (b mod S a) (S a))gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:natH:(c | S a)H':(c | b)(c | gcd (b mod S a) (S a))gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:natH:(c | S a)H':(c | b)(c | b mod S a)gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natH:(c | a')H':(c | b)(c | b mod a')gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natH:(c | a')H':(c | a' * (b / a') + b mod a')(c | b mod a')gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natu:natHu:a' = u * cv:natHv:a' * (b / a') + b mod a' = v * c(c | b mod a')gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natu:natHu:a' = u * cv:natHv:a' * (b / a') + b mod a' = v * cb mod a' = (v - b / a' * u) * cgcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natu:natHu:a' = u * cv:natHv:b / a' * a' + b mod a' = v * cb mod a' = (v - b / a' * u) * cnow rewrite add_comm, add_sub. Qed.gcd_greatest:forall a0 b0 c0 : nat, (c0 | a0) -> (c0 | b0) -> (c0 | gcd a0 b0)a, b, c:nata':=S a:natu:natHu:a' = u * cv:natHv:b / a' * a' + b mod a' = v * cb mod a' = b / a' * a' + b mod a' - b / a' * a'a, b:nat0 <= gcd a bapply le_0_l. Qed.a, b:nat0 <= gcd a b
n:natdiv2 (2 * n) = nn:natdiv2 (2 * n) = nn:natIHn:div2 (2 * n) = ndiv2 (2 * S n) = S nn:natIHn:div2 (2 * n) = ndiv2 (S (n + S (n + 0))) = S nn:natIHn:div2 (2 * n) = ndiv2 (S (S (n + (n + 0)))) = S nnow f_equal. Qed.n:natIHn:div2 (2 * n) = nS (div2 (n + (n + 0))) = S nn:natdiv2 (S (2 * n)) = nn:natdiv2 (S (2 * n)) = nn:natIHn:div2 (S (2 * n)) = ndiv2 (S (2 * S n)) = S nn:natIHn:div2 (S (2 * n)) = nS (div2 (n + S (n + 0))) = S nnow rewrite add_succ_r. Qed.n:natIHn:div2 (S (2 * n)) = ndiv2 (n + S (n + 0)) = nn:natdiv2 (S n) <= nn:natdiv2 (S n) <= nforall n : nat, div2 (S n) <= nle_div2:forall n : nat, div2 (S n) <= nforall n : nat, div2 (S n) <= nle_div2:forall n0 : nat, div2 (S n0) <= n0n:natS (div2 n) <= S nle_div2:forall n0 : nat, div2 (S n0) <= n0n:natdiv2 n <= nnow constructor. Qed.le_div2:forall n0 : nat, div2 (S n0) <= n0n:natdiv2 (S n) <= S nn:nat0 < n -> div2 n < nn:nat0 < n -> div2 n < n0 < 0 -> div2 0 < 0n:nat0 < S n -> div2 (S n) < S ninversion 1.0 < 0 -> div2 0 < 0n:nat0 < S n -> div2 (S n) < S napply lt_succ_r, le_div2. Qed.n:natdiv2 (S n) < S na, n:nata <= S n -> div2 a <= na, n:nata <= S n -> div2 a <= nn:natH:0 <= S ndiv2 0 <= na, n:natH:S a <= S ndiv2 (S a) <= nn:natH:0 <= S ndiv2 0 <= napply le_0_l.n:natH:0 <= S n0 <= na, n:natH:S a <= S ndiv2 (S a) <= napply le_trans with a; [ apply le_div2 | trivial ]. Qed.a, n:natH:a <= ndiv2 (S a) <= nforall n : nat, double n = 2 * nforall n : nat, double n = 2 * nnow rewrite add_0_r. Qed.n:natdouble n = n + (n + 0)forall n : nat, testbit 0 n = falsenow induction n. Qed.forall n : nat, testbit 0 n = falsea:nattestbit (2 * a + 1) 0 = truea:nattestbit (2 * a + 1) 0 = truea:natodd (2 * a + 1) = truenow exists a. Qed.a:natOdd (2 * a + 1)a:nattestbit (2 * a) 0 = falsea:nattestbit (2 * a) 0 = falsea:natnegb (even (2 * a)) = falsenow exists a. Qed.a:natEven (2 * a)a, n:nattestbit (2 * a + 1) (S n) = testbit a na, n:nattestbit (2 * a + 1) (S n) = testbit a na, n:nattestbit (div2 (2 * a + 1)) n = testbit a na, n:nattestbit (div2 (S (2 * a))) n = testbit a napply div2_succ_double. Qed.a, n:natdiv2 (S (2 * a)) = aa, n:nattestbit (2 * a) (S n) = testbit a na, n:nattestbit (2 * a) (S n) = testbit a na, n:nattestbit (div2 (2 * a)) n = testbit a napply div2_double. Qed.a, n:natdiv2 (2 * a) = aforall a n m : nat, testbit (shiftr a n) m = testbit a (m + n)forall a n m : nat, testbit (shiftr a n) m = testbit a (m + n)a, m:nattestbit (shiftr a 0) m = testbit a (m + 0)a, n:natIHn:forall m0 : nat, testbit (shiftr a n) m0 = testbit a (m0 + n)m:nattestbit (shiftr a (S n)) m = testbit a (m + S n)a, m:nattestbit (shiftr a 0) m = testbit a (m + 0)a, n:natIHn:forall m0 : nat, testbit (shiftr a n) m0 = testbit a (m0 + n)m:nattestbit (shiftr a (S n)) m = testbit a (m + S n)now rewrite add_succ_r, <- add_succ_l, <- IHn. Qed.a, n:natIHn:forall m0 : nat, testbit (shiftr a n) m0 = testbit a (m0 + n)m:nattestbit (shiftr a (S n)) m = testbit a (m + S n)forall a n m : nat, n <= m -> testbit (shiftl a n) m = testbit a (m - n)forall a n m : nat, n <= m -> testbit (shiftl a n) m = testbit a (m - n)a, m:natH:0 <= mtestbit (shiftl a 0) m = testbit a (m - 0)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= mtestbit (shiftl a (S n)) m = testbit a (m - S n)a, m:natH:0 <= mtestbit (shiftl a 0) m = testbit a (m - 0)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= mtestbit (shiftl a (S n)) m = testbit a (m - S n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= mtestbit (shiftl a (S n)) m = testbit a (m - S n)a, n:natIHn:forall m : nat, n <= m -> testbit (shiftl a n) m = testbit a (m - n)H:S n <= 0testbit (shiftl a (S n)) 0 = testbit a (0 - S n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= S mtestbit (shiftl a (S n)) (S m) = testbit a (S m - S n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= S mtestbit (shiftl a (S n)) (S m) = testbit a (S m - S n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:S n <= S mtestbit (div2 (double (shiftl a n))) m = testbit a (m - n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:n <= mtestbit (div2 (double (shiftl a n))) m = testbit a (m - n)a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:n <= mtestbit (div2 (double (shiftl a n))) m = testbit a (m - n)now apply IHn. Qed.a, n:natIHn:forall m0 : nat, n <= m0 -> testbit (shiftl a n) m0 = testbit a (m0 - n)m:natH:n <= mtestbit (shiftl a n) m = testbit a (m - n)forall a n m : nat, m < n -> testbit (shiftl a n) m = falseforall a n m : nat, m < n -> testbit (shiftl a n) m = falsea, m:natH:m < 0testbit (shiftl a 0) m = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:m < S ntestbit (shiftl a (S n)) m = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:m < S ntestbit (shiftl a (S n)) m = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:m < S ntestbit (double (shiftl a n)) m = falsea, n:natIHn:forall m : nat, m < n -> testbit (shiftl a n) m = falseH:0 < S nodd (double (shiftl a n)) = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m : nat, m < n -> testbit (shiftl a n) m = falseH:0 < S nnegb (even (double (shiftl a n))) = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m : nat, m < n -> testbit (shiftl a n) m = falseH:0 < S neven (double (shiftl a n)) = truea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m : nat, m < n -> testbit (shiftl a n) m = falseH:0 < S nEven (double (shiftl a n))a, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m : nat, m < n -> testbit (shiftl a n) m = falseH:0 < S ndouble (shiftl a n) = 2 * shiftl a na, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (div2 (double (shiftl a n))) m = falsea, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S ntestbit (shiftl a n) m = falsenow apply succ_le_mono. Qed.a, n:natIHn:forall m0 : nat, m0 < n -> testbit (shiftl a n) m0 = falsem:natH:S m < S nm < nforall (op : bool -> bool -> bool) (n a b : nat), div2 (bitwise op (S n) a b) = bitwise op n (div2 a) (div2 b)forall (op : bool -> bool -> bool) (n a b : nat), div2 (bitwise op (S n) a b) = bitwise op n (div2 a) (div2 b)op:bool -> bool -> booln, a, b:natdiv2 (bitwise op (S n) a b) = bitwise op n (div2 a) (div2 b)op:bool -> bool -> booln, a, b:natdiv2 ((if op (odd a) (odd b) then 1 else 0) + 2 * bitwise op n (div2 a) (div2 b)) = bitwise op n (div2 a) (div2 b)op:bool -> bool -> booln, a, b:natdiv2 (1 + 2 * bitwise op n (div2 a) (div2 b)) = bitwise op n (div2 a) (div2 b)op:bool -> bool -> booln, a, b:natdiv2 (0 + 2 * bitwise op n (div2 a) (div2 b)) = bitwise op n (div2 a) (div2 b)now rewrite add_0_l, div2_double. Qed.op:bool -> bool -> booln, a, b:natdiv2 (0 + 2 * bitwise op n (div2 a) (div2 b)) = bitwise op n (div2 a) (div2 b)forall (op : bool -> bool -> bool) (n a b : nat), odd (bitwise op (S n) a b) = op (odd a) (odd b)forall (op : bool -> bool -> bool) (n a b : nat), odd (bitwise op (S n) a b) = op (odd a) (odd b)op:bool -> bool -> booln, a, b:natodd (bitwise op (S n) a b) = op (odd a) (odd b)op:bool -> bool -> booln, a, b:natodd ((if op (odd a) (odd b) then 1 else 0) + 2 * bitwise op n (div2 a) (div2 b)) = op (odd a) (odd b)op:bool -> bool -> booln, a, b:natodd (1 + 2 * bitwise op n (div2 a) (div2 b)) = trueop:bool -> bool -> booln, a, b:natodd (0 + 2 * bitwise op n (div2 a) (div2 b)) = falseop:bool -> bool -> booln, a, b:natOdd (1 + 2 * bitwise op n (div2 a) (div2 b))op:bool -> bool -> booln, a, b:natodd (0 + 2 * bitwise op n (div2 a) (div2 b)) = falseop:bool -> bool -> booln, a, b:natOdd (2 * bitwise op n (div2 a) (div2 b) + 1)op:bool -> bool -> booln, a, b:natodd (0 + 2 * bitwise op n (div2 a) (div2 b)) = falseop:bool -> bool -> booln, a, b:natodd (0 + 2 * bitwise op n (div2 a) (div2 b)) = falseop:bool -> bool -> booln, a, b:natnegb (even (0 + 2 * bitwise op n (div2 a) (div2 b))) = falseop:bool -> bool -> booln, a, b:nateven (0 + 2 * bitwise op n (div2 a) (div2 b)) = truerewrite add_0_l; eexists; eauto. Qed.op:bool -> bool -> booln, a, b:natEven (0 + 2 * bitwise op n (div2 a) (div2 b))forall op : bool -> bool -> bool, (forall b : bool, op false b = false) -> forall n m a b : nat, a <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)forall op : bool -> bool -> bool, (forall b : bool, op false b = false) -> forall n m a b : nat, a <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b : bool, op false b = falseforall n m a b : nat, a <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsem, a, b:natHa:a <= 0testbit (bitwise op 0 a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsem, a, b:natHa:a <= 0testbit 0 m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsem, b:natHa:0 <= 0testbit 0 m = op (testbit 0 m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m = op (testbit a0 m) (testbit b0 m)a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) 0 = op (testbit a 0) (testbit b 0)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) (S m) = op (testbit a (S m)) (testbit b (S m))op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op (S n) a b) (S m) = op (testbit a (S m)) (testbit b (S m))op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (div2 (bitwise op (S n) a b)) m = op (testbit (div2 a) m) (testbit (div2 b) m)op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ntestbit (bitwise op n (div2 a) (div2 b)) m = op (testbit (div2 a) m) (testbit (div2 b) m)now apply div2_decr. Qed.op:bool -> bool -> boolHop:forall b0 : bool, op false b0 = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S ndiv2 a <= nforall op : bool -> bool -> bool, op false false = false -> forall n m a b : nat, a <= n -> b <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)forall op : bool -> bool -> bool, op false false = false -> forall n m a b : nat, a <= n -> b <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falseforall n m a b : nat, a <= n -> b <= n -> testbit (bitwise op n a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsem, a, b:natHa:a <= 0Hb:b <= 0testbit (bitwise op 0 a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsem, a, b:natHa:a <= 0Hb:b <= 0testbit 0 m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsem:natHa, Hb:0 <= 0testbit 0 m = op (testbit 0 m) (testbit 0 m)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) m = op (testbit a m) (testbit b m)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m = op (testbit a0 m) (testbit b0 m)a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) 0 = op (testbit a 0) (testbit b 0)op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) (S m) = op (testbit a (S m)) (testbit b (S m))op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op (S n) a b) (S m) = op (testbit a (S m)) (testbit b (S m))op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (div2 (bitwise op (S n) a b)) m = op (testbit (div2 a) m) (testbit (div2 b) m)apply IHn; now apply div2_decr. Qed.op:bool -> bool -> boolHop:op false false = falsen:natIHn:forall m0 a0 b0 : nat, a0 <= n -> b0 <= n -> testbit (bitwise op n a0 b0) m0 = op (testbit a0 m0) (testbit b0 m0)m, a, b:natHa:a <= S nHb:b <= S ntestbit (bitwise op n (div2 a) (div2 b)) m = op (testbit (div2 a) m) (testbit (div2 b) m)a, b, n:nattestbit (land a b) n = testbit a n && testbit b na, b, n:nattestbit (land a b) n = testbit a n && testbit b napply testbit_bitwise_1; trivial. Qed.a, b, n:nattestbit (bitwise andb a a b) n = testbit a n && testbit b na, b, n:nattestbit (ldiff a b) n = testbit a n && negb (testbit b n)a, b, n:nattestbit (ldiff a b) n = testbit a n && negb (testbit b n)apply testbit_bitwise_1; trivial. Qed.a, b, n:nattestbit (bitwise (fun b0 b' : bool => b0 && negb b') a a b) n = testbit a n && negb (testbit b n)a, b, n:nattestbit (lor a b) n = testbit a n || testbit b na, b, n:nattestbit (lor a b) n = testbit a n || testbit b na, b, n:nattestbit (bitwise orb (max a b) a b) n = testbit a n || testbit b na, b, n:natfalse || false = falsea, b, n:nata <= max a ba, b, n:natb <= max a btrivial.a, b, n:natfalse || false = falsea, b, n:nata <= max a ba, b, n:natH:a = ba <= max a ba, b, n:natH:a < ba <= max a ba, b, n:natH:b < aa <= max a brewrite max_l; subst; trivial.a, b, n:natH:a = ba <= max a ba, b, n:natH:a < ba <= max a bnow rewrite max_r.a, b, n:natH:a <= ba <= max a ba, b, n:natH:b < aa <= max a bnow rewrite max_l.a, b, n:natH:b <= aa <= max a ba, b, n:natb <= max a ba, b, n:natH:a = bb <= max a ba, b, n:natH:a < bb <= max a ba, b, n:natH:b < ab <= max a brewrite max_r; subst; trivial.a, b, n:natH:a = bb <= max a ba, b, n:natH:a < bb <= max a bnow rewrite max_r.a, b, n:natH:a <= bb <= max a ba, b, n:natH:b < ab <= max a bnow rewrite max_l. Qed.a, b, n:natH:b <= ab <= max a ba, b, n:nattestbit (lxor a b) n = xorb (testbit a n) (testbit b n)a, b, n:nattestbit (lxor a b) n = xorb (testbit a n) (testbit b n)a, b, n:nattestbit (bitwise xorb (max a b) a b) n = xorb (testbit a n) (testbit b n)a, b, n:natxorb false false = falsea, b, n:nata <= max a ba, b, n:natb <= max a btrivial.a, b, n:natxorb false false = falsea, b, n:nata <= max a ba, b, n:natH:a = ba <= max a ba, b, n:natH:a < ba <= max a ba, b, n:natH:b < aa <= max a brewrite max_l; subst; trivial.a, b, n:natH:a = ba <= max a ba, b, n:natH:a < ba <= max a bnow rewrite max_r.a, b, n:natH:a <= ba <= max a ba, b, n:natH:b < aa <= max a bnow rewrite max_l.a, b, n:natH:b <= aa <= max a ba, b, n:natb <= max a ba, b, n:natH:a = bb <= max a ba, b, n:natH:a < bb <= max a ba, b, n:natH:b < ab <= max a brewrite max_r; subst; trivial.a, b, n:natH:a = bb <= max a ba, b, n:natH:a < bb <= max a bnow rewrite max_r.a, b, n:natH:a <= bb <= max a ba, b, n:natH:b < ab <= max a bnow rewrite max_l. Qed.a, b, n:natH:b <= ab <= max a ba:natdiv2 a = shiftr a 1reflexivity. Qed.a:natdiv2 a = shiftr a 1
Aliases with extra dummy hypothesis, to fulfil the interface
Definition testbit_odd_succ a n (_:0<=n) := testbit_odd_succ' a n. Definition testbit_even_succ a n (_:0<=n) := testbit_even_succ' a n.a, n:natH:n < 0testbit a n = falseinversion H. Qed. Definition shiftl_spec_high a n m (_:0<=m) := shiftl_specif_high a n m. Definition shiftr_spec a n m (_:0<=m) := shiftr_specif a n m.a, n:natH:n < 0testbit a n = false
Properties of advanced functions (pow, sqrt, log2, ...)
Include NExtraProp.
Properties of tail-recursive addition and multiplication
n, m:nattail_add n m = n + mn, m:nattail_add n m = n + mn:natforall m : nat, tail_add n m = n + mn:natIH:forall m : nat, tail_add n m = n + mforall m : nat, tail_add n (S m) = S (n + m)now rewrite IH, add_succ_r. Qed.n:natIH:forall m0 : nat, tail_add n m0 = n + m0m:nattail_add n (S m) = S (n + m)r, n, m:nattail_addmul r n m = r + n * mr, n, m:nattail_addmul r n m = r + n * mn:natforall m r : nat, tail_addmul r n m = r + n * mn:natIH:forall m r : nat, tail_addmul r n m = r + n * mforall m r : nat, tail_addmul (tail_add m r) n m = r + (m + n * m)n:natIH:forall m0 r0 : nat, tail_addmul r0 n m0 = r0 + n * m0m, r:nattail_addmul (tail_add m r) n m = r + (m + n * m)n:natIH:forall m0 r0 : nat, tail_addmul r0 n m0 = r0 + n * m0m, r:natm + r + n * m = r + (m + n * m)n:natIH:forall m0 r0 : nat, tail_addmul r0 n m0 = r0 + n * m0m, r:natm + r + n * m = r + m + n * mapply add_comm. Qed.n:natIH:forall m0 r0 : nat, tail_addmul r0 n m0 = r0 + n * m0m, r:natm + r = r + mn, m:nattail_mul n m = n * mn, m:nattail_mul n m = n * mnow rewrite tail_addmul_spec. Qed. End Nat.n, m:nattail_addmul 0 n m = n * m
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. Hint Unfold Nat.le : core. Hint Unfold Nat.lt : core.
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.
Section TestOrder.forall x y : nat, x <= y -> y <= x -> x = yNat.order. Qed. End TestOrder.forall x y : nat, x <= y -> y <= x -> x = y