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 Bool. (* To get the orb and negb function *) Require Import RelationPairs. Require Export NStrongRec.
In this module, we derive generic implementations of usual operators
just via the use of a recursion function.
Module NdefOpsProp (Import N : NAxiomsRecSig'). Include NStrongRecProp N.
Nullity Test
Definition if_zero (A : Type) (a b : A) (n : N.t) : A := recursion a (fun _ _ => b) n. Arguments if_zero [A] a b n.A:TypeProper (Logic.eq ==> Logic.eq ==> eq ==> Logic.eq) (if_zero (A:=A))A:TypeProper (Logic.eq ==> Logic.eq ==> eq ==> Logic.eq) (if_zero (A:=A))f_equiv'. Qed.A:TypeProper (Logic.eq ==> Logic.eq ==> eq ==> Logic.eq) (fun (a b : A) (n : t) => recursion a (fun (_ : t) (_ : A) => b) n)forall (A : Type) (a b : A), if_zero a b 0 = aunfold if_zero; intros; now rewrite recursion_0. Qed.forall (A : Type) (a b : A), if_zero a b 0 = aforall (A : Type) (a b : A) (n : t), if_zero a b (S n) = bforall (A : Type) (a b : A) (n : t), if_zero a b (S n) = bnow rewrite recursion_succ. Qed. (*****************************************************)A:Typea, b:An:trecursion a (fun (_ : t) (_ : A) => b) (S n) = b
Addition
Definition def_add (x y : N.t) := recursion y (fun _ => S) x. Local Infix "+++" := def_add (at level 50, left associativity).Proper (eq ==> eq ==> eq) def_addProper (eq ==> eq ==> eq) def_addf_equiv'. Qed.Proper (eq ==> eq ==> eq) (fun x y : t => recursion y (fun _ : t => S) x)forall y : t, 0 +++ y == yforall y : t, 0 +++ y == yy:t0 +++ y == ynow rewrite recursion_0. Qed.y:trecursion y (fun _ : t => S) 0 == yforall x y : t, S x +++ y == S (x +++ y)forall x y : t, S x +++ y == S (x +++ y)rewrite recursion_succ; f_equiv'. Qed.x, y:trecursion y (fun _ : t => S) (S x) == S (recursion y (fun _ : t => S) x)forall n m : t, n +++ m == n + mforall n m : t, n +++ m == n + mm:t0 +++ m == 0 + mm:tforall n : t, n +++ m == n + m -> S n +++ m == S n + mm:tforall n : t, n +++ m == n + m -> S n +++ m == S n + mnow rewrite def_add_succ_l, add_succ_l, H. Qed. (*****************************************************)m, n:tH:n +++ m == n + mS n +++ m == S n + m
Multiplication
Definition def_mul (x y : N.t) := recursion 0 (fun _ p => p +++ x) y. Local Infix "**" := def_mul (at level 40, left associativity).Proper (eq ==> eq ==> eq) def_mulProper (eq ==> eq ==> eq) def_mulf_equiv'. Qed.Proper (eq ==> eq ==> eq) (fun x y : t => recursion 0 (fun _ p : t => p +++ x) y)forall x : t, x ** 0 == 0forall x : t, x ** 0 == 0x:tx ** 0 == 0now rewrite recursion_0. Qed.x:trecursion 0 (fun _ p : t => p +++ x) 0 == 0forall x y : t, x ** S y == x ** y +++ xforall x y : t, x ** S y == x ** y +++ xx, y:trecursion 0 (fun _ p : t => p +++ x) (S y) == recursion 0 (fun _ p : t => p +++ x) y +++ xf_equiv'. Qed.x, y:tProper (eq ==> eq ==> eq) (fun _ p : t => p +++ x)forall n m : t, n ** m == n * mforall n m : t, n ** m == n * mn:tn ** 0 == n * 0n:tforall n0 : t, n ** n0 == n * n0 -> n ** S n0 == n * S n0intros m IH; now rewrite def_mul_succ_r, mul_succ_r, def_add_add, IH. Qed. (*****************************************************)n:tforall n0 : t, n ** n0 == n * n0 -> n ** S n0 == n * S n0
Order
Definition ltb (m : N.t) : N.t -> bool := recursion (if_zero false true) (fun _ f n => recursion false (fun n' _ => f n') n) m. Local Infix "<<" := ltb (at level 70, no associativity).Proper (eq ==> eq ==> Logic.eq) ltbProper (eq ==> eq ==> Logic.eq) ltbf_equiv'. Qed.Proper (eq ==> eq ==> Logic.eq) (fun m : t => recursion (if_zero false true) (fun (_ : t) (f : t -> bool) (n : t) => recursion false (fun (n' : t) (_ : bool) => f n') n) m)forall n : t, (0 << n) = if_zero false true nintro n; unfold ltb; now rewrite recursion_0. Qed.forall n : t, (0 << n) = if_zero false true nforall m n : t, (S m << n) = recursion false (fun (n' : t) (_ : bool) => m << n') nforall m n : t, (S m << n) = recursion false (fun (n' : t) (_ : bool) => m << n') nm, n:trecursion (if_zero false true) (fun (_ : t) (f : t -> bool) (n0 : t) => recursion false (fun (n' : t) (_ : bool) => f n') n0) (S m) n = recursion false (fun (n' : t) (_ : bool) => m << n') nrewrite recursion_succ; f_equiv'. Qed. (* Above, we rewrite applications of function. Is it possible to rewrite functions themselves, i.e., rewrite (recursion lt_base lt_step (S n)) to lt_step n (recursion lt_base lt_step n)? *)m, n:t(Logic.eq ==> Logic.eq)%signature (recursion (if_zero false true) (fun (_ : t) (f : t -> bool) (n0 : t) => recursion false (fun (n' : t) (_ : bool) => f n') n0) (S m)) (recursion false (fun (n' : t) (_ : bool) => m << n'))forall n : t, (n << 0) = falseforall n : t, (n << 0) = false(0 << 0) = falseforall n : t, (S n << 0) = falseforall n : t, (S n << 0) = falsenow rewrite recursion_0. Qed.n:trecursion false (fun (n' : t) (_ : bool) => n << n') 0 = falseforall n : t, (0 << S n) = trueintro n; rewrite ltb_base; now rewrite if_zero_succ. Qed.forall n : t, (0 << S n) = trueforall n m : t, (S n << S m) = (n << m)forall n m : t, (S n << S m) = (n << m)n, m:t(S n << S m) = (n << m)rewrite recursion_succ; f_equiv'. Qed.n, m:trecursion false (fun (n' : t) (_ : bool) => n << n') (S m) = (n << m)forall n m : t, (n << m) = true <-> n < mforall n m : t, (n << m) = true <-> n < mforall m : t, (0 << m) = true <-> 0 < mforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S m(0 << 0) = true <-> 0 < 0forall n : t, (0 << S n) = true <-> 0 < S nforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mfalse = true <-> 0 < 0forall n : t, (0 << S n) = true <-> 0 < S nforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mforall n : t, (0 << S n) = true <-> 0 < S nforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mn:t(0 << S n) = true <-> 0 < S nforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mn:ttrue = true <-> 0 < S nforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mforall n : t, (S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mn:t(S n << 0) = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mn:tfalse = true <-> S n < 0forall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mforall n m : t, (n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mn, m:t(n << m) = true <-> n < m -> (S n << S m) = true <-> S n < S mnow rewrite <- succ_lt_mono. Qed.n, m:t(n << m) = true <-> n < m -> (n << m) = true <-> S n < S mforall n m : t, (n << m) = false <-> m <= nforall n m : t, (n << m) = false <-> m <= nn, m:t(n << m) = false <-> m <= napply nlt_ge. Qed. (*****************************************************)n, m:t~ n < m <-> m <= n
Even
Definition even (x : N.t) := recursion true (fun _ p => negb p) x.Proper (eq ==> Logic.eq) evenProper (eq ==> Logic.eq) evenf_equiv'. Qed.Proper (eq ==> Logic.eq) (fun x : t => recursion true (fun (_ : t) (p : bool) => negb p) x)even 0 = trueeven 0 = truenow rewrite recursion_0. Qed.recursion true (fun (_ : t) (p : bool) => negb p) 0 = trueforall x : t, even (S x) = negb (even x)forall x : t, even (S x) = negb (even x)intro x; rewrite recursion_succ; f_equiv'. Qed. (*****************************************************)forall x : t, recursion true (fun (_ : t) (p : bool) => negb p) (S x) = negb (recursion true (fun (_ : t) (p : bool) => negb p) x)
Division by 2
Definition half_aux (x : N.t) : N.t * N.t := recursion (0, 0) (fun _ p => let (x1, x2) := p in (S x2, x1)) x. Definition half (x : N.t) := snd (half_aux x).Proper (eq ==> eq * eq) half_auxProper (eq ==> eq * eq) half_auxx, x':tHx:x == x'(eq * eq)%signature (half_aux x) (half_aux x')x, x':tHx:x == x'(eq * eq)%signature (recursion (0, 0) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) x) (recursion (0, 0) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) x')x, x':tHx:x == x'(eq ==> eq * eq ==> eq * eq)%signature (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1))x, x':tHx:x == x'y, y':tHy:y == y'u, v, u', v':tHu:(eq @@1)%signature (u, v) (u', v')Hv:(eq @@2)%signature (u, v) (u', v')(eq * eq)%signature (S v, u) (S v', u')rewrite Hu, Hv; auto with *. Qed.x, x':tHx:x == x'y, y':tHy:y == y'u, v, u', v':tHu:u == u'Hv:v == v'S v == S v' /\ u == u'Proper (eq ==> eq) halfProper (eq ==> eq) halff_equiv'. Qed.Proper (eq ==> eq) (fun x : t => snd (half_aux x))half_aux 0 = (0, 0)half_aux 0 = (0, 0)rewrite recursion_0; auto. Qed.recursion (0, 0) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) 0 = (0, 0)forall x : t, half_aux (S x) = (S (snd (half_aux x)), fst (half_aux x))forall x : t, half_aux (S x) = (S (snd (half_aux x)), fst (half_aux x))x:thalf_aux (S x) = (S (snd (half_aux x)), fst (half_aux x))x:th:(t * t)%typeHeqh:h = half_aux xhalf_aux (S x) = (S (snd h), fst h)x, f, s:tHeqh:(f, s) = half_aux xhalf_aux (S x) = (S s, f)rewrite recursion_succ, <- Heqh; simpl; f_equiv'. Qed.x, f, s:tHeqh:(f, s) = recursion (0, 0) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) xrecursion (0, 0) (fun (_ : t) (p : t * t) => let (x1, x2) := p in (S x2, x1)) (S x) = (S s, f)forall n : t, n == fst (half_aux n) + snd (half_aux n)forall n : t, n == fst (half_aux n) + snd (half_aux n)Proper (eq ==> iff) (fun n : t => n == fst (half_aux n) + snd (half_aux n))0 == fst (half_aux 0) + snd (half_aux 0)forall n : t, n == fst (half_aux n) + snd (half_aux n) -> S n == fst (half_aux (S n)) + snd (half_aux (S n))x, x':tHx:x == x'x == fst (half_aux x) + snd (half_aux x) <-> x' == fst (half_aux x') + snd (half_aux x')0 == fst (half_aux 0) + snd (half_aux 0)forall n : t, n == fst (half_aux n) + snd (half_aux n) -> S n == fst (half_aux (S n)) + snd (half_aux (S n))0 == fst (half_aux 0) + snd (half_aux 0)forall n : t, n == fst (half_aux n) + snd (half_aux n) -> S n == fst (half_aux (S n)) + snd (half_aux (S n))forall n : t, n == fst (half_aux n) + snd (half_aux n) -> S n == fst (half_aux (S n)) + snd (half_aux (S n))n:tH:n == fst (half_aux n) + snd (half_aux n)S n == fst (half_aux (S n)) + snd (half_aux (S n))n:tH:n == fst (half_aux n) + snd (half_aux n)S n == fst (S (snd (half_aux n)), fst (half_aux n)) + snd (S (snd (half_aux n)), fst (half_aux n))n:tH:n == fst (half_aux n) + snd (half_aux n)S n == S (snd (half_aux n)) + fst (half_aux n)now f_equiv. Qed.n:tH:n == fst (half_aux n) + snd (half_aux n)S n == S (fst (half_aux n) + snd (half_aux n))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n))Proper (eq ==> iff) (fun n : t => fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)))fst (half_aux 0) == snd (half_aux 0) \/ fst (half_aux 0) == S (snd (half_aux 0))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)) -> fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))x, x':tHx:x == x'fst (half_aux x) == snd (half_aux x) \/ fst (half_aux x) == S (snd (half_aux x)) <-> fst (half_aux x') == snd (half_aux x') \/ fst (half_aux x') == S (snd (half_aux x'))fst (half_aux 0) == snd (half_aux 0) \/ fst (half_aux 0) == S (snd (half_aux 0))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)) -> fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))fst (half_aux 0) == snd (half_aux 0) \/ fst (half_aux 0) == S (snd (half_aux 0))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)) -> fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))0 == 0 \/ 0 == S 0forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)) -> fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))forall n : t, fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n)) -> fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))n:tH:fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n))fst (half_aux (S n)) == snd (half_aux (S n)) \/ fst (half_aux (S n)) == S (snd (half_aux (S n)))n:tH:fst (half_aux n) == snd (half_aux n) \/ fst (half_aux n) == S (snd (half_aux n))S (snd (half_aux n)) == fst (half_aux n) \/ S (snd (half_aux n)) == S (fst (half_aux n))right; now f_equiv. Qed.n:tH:fst (half_aux n) == snd (half_aux n)S (snd (half_aux n)) == fst (half_aux n) \/ S (snd (half_aux n)) == S (fst (half_aux n))half 0 == 0half 0 == 0rewrite half_aux_0; simpl; auto with *. Qed.snd (half_aux 0) == 0half 1 == 0half 1 == 0rewrite one_succ, half_aux_succ, half_aux_0; simpl; auto with *. Qed.snd (half_aux 1) == 0forall n : t, n == 2 * half n \/ n == 1 + 2 * half nforall n : t, n == 2 * half n \/ n == 1 + 2 * half nn:tn == 2 * half n \/ n == 1 + 2 * half nn:tn == 2 * snd (half_aux n) \/ n == 1 + 2 * snd (half_aux n)n:tn == snd (half_aux n) + snd (half_aux n) \/ n == S (snd (half_aux n) + snd (half_aux n))n:tH:fst (half_aux n) == snd (half_aux n)n == snd (half_aux n) + snd (half_aux n)n:tH:fst (half_aux n) == S (snd (half_aux n))n == S (snd (half_aux n) + snd (half_aux n))n:tH:fst (half_aux n) == snd (half_aux n)n == fst (half_aux n) + snd (half_aux n)n:tH:fst (half_aux n) == S (snd (half_aux n))n == S (snd (half_aux n) + snd (half_aux n))n:tH:fst (half_aux n) == S (snd (half_aux n))n == S (snd (half_aux n) + snd (half_aux n))n:tH:fst (half_aux n) == S (snd (half_aux n))n == S (snd (half_aux n)) + snd (half_aux n)apply half_aux_spec. Qed.n:tH:fst (half_aux n) == S (snd (half_aux n))n == fst (half_aux n) + snd (half_aux n)forall n : t, 2 * half n <= nforall n : t, 2 * half n <= nn:t2 * half n <= nn:tE:n == 2 * half n2 * half n <= 2 * half nn:tE:n == 1 + 2 * half n2 * half n <= 1 + 2 * half nn:tE:n == 1 + 2 * half n2 * half n <= 1 + 2 * half napply le_le_succ_r, le_refl. Qed.n:tE:n == 1 + 2 * half n2 * half n <= S (2 * half n)forall n : t, n <= 1 + 2 * half nforall n : t, n <= 1 + 2 * half nn:tn <= 1 + 2 * half nn:tE:n == 2 * half n2 * half n <= 1 + 2 * half nn:tE:n == 1 + 2 * half n1 + 2 * half n <= 1 + 2 * half nn:tE:n == 2 * half n2 * half n <= S (2 * half n)n:tE:n == 1 + 2 * half n1 + 2 * half n <= 1 + 2 * half napply le_refl. Qed.n:tE:n == 1 + 2 * half n1 + 2 * half n <= 1 + 2 * half nforall n : t, 1 < n -> 0 < half nforall n : t, 1 < n -> 0 < half nn:tLT:1 < n0 < half nn:tLT:1 < nLE:0 <= half n0 < half nn:tLT:1 < nLE:0 == half n0 < half nn:tLT:1 < 0LE:0 == half nE:n == 00 < half nn:tLT:1 < 1LE:0 == half nE:n == 10 < half norder. Qed.n:tLT:1 < 1LE:0 == half nE:n == 10 < half nforall n : t, 0 < n -> half n < nforall n : t, 0 < n -> half n < nn:tLT:0 < nhalf n < nn:tLT:0 < nE:n == 2 * half nhalf n < half n + half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 2 * half n0 + half n < half n + half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 2 * half n0 < half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 2 * half nLE:0 <= half n0 < half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 2 * half nLE:0 == half n0 < half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 0LE:0 == half n0 < half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < 0E:n == 0LE:0 == half n0 < half nn:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n + half n)n:tLT:0 < nE:n == 1 + 2 * half nhalf n < S (half n) + half nn:tLT:0 < nE:n == 1 + 2 * half n0 + half n < S (half n) + half napply lt_0_succ. Qed. (*****************************************************)n:tLT:0 < nE:n == 1 + 2 * half n0 < S (half n)
Power
Definition pow (n m : N.t) := recursion 1 (fun _ r => n*r) m. Local Infix "^^" := pow (at level 30, right associativity).Proper (eq ==> eq ==> eq) powProper (eq ==> eq ==> eq) powf_equiv'. Qed.Proper (eq ==> eq ==> eq) (fun n m : t => recursion 1 (fun _ r : t => n * r) m)forall n : t, n ^^ 0 == 1forall n : t, n ^^ 0 == 1n:tn ^^ 0 == 1n:trecursion 1 (fun _ r : t => n * r) 0 == 1auto with *. Qed.n:t1 == 1forall n m : t, n ^^ S m == n * n ^^ mforall n m : t, n ^^ S m == n * n ^^ mn, m:tn ^^ S m == n * n ^^ mrewrite recursion_succ; f_equiv'. Qed. (*****************************************************)n, m:trecursion 1 (fun _ r : t => n * r) (S m) == n * recursion 1 (fun _ r : t => n * r) m
Logarithm for the base 2
Definition log (x : N.t) : N.t := strong_rec 0 (fun g x => if x << 2 then 0 else S (g (half x))) x.Proper ((eq ==> eq) ==> eq ==> eq) (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x)))Proper ((eq ==> eq) ==> eq ==> eq) (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x)))g, g':t -> tHg:(eq ==> eq)%signature g g'n, n':tHn:n == n'(if n << 2 then 0 else S (g (half n))) == (if n' << 2 then 0 else S (g' (half n')))g, g':t -> tHg:(eq ==> eq)%signature g g'n, n':tHn:n == n'(if n' << 2 then 0 else S (g (half n))) == (if n' << 2 then 0 else S (g' (half n')))g, g':t -> tHg:(eq ==> eq)%signature g g'n, n':tHn:n == n'S (g (half n)) == S (g' (half n'))g, g':t -> tHg:(eq ==> eq)%signature g g'n, n':tHn:n == n'g (half n) == g' (half n')now f_equiv. Qed.g, g':t -> tHg:(eq ==> eq)%signature g g'n, n':tHn:n == n'half n == half n'Proper (eq ==> eq) logProper (eq ==> eq) logx, x':tExx':x == x'log x == log x'apply strong_rec_wd; f_equiv'. Qed.x, x':tExx':x == x'strong_rec 0 (fun (g : t -> t) (x0 : t) => if x0 << 2 then 0 else S (g (half x0))) x == strong_rec 0 (fun (g : t -> t) (x0 : t) => if x0 << 2 then 0 else S (g (half x0))) x'forall (n : t) (h1 h2 : t -> t), (forall m : t, m < n -> h1 m == h2 m) -> (if n << 2 then 0 else S (h1 (half n))) == (if n << 2 then 0 else S (h2 (half n)))forall (n : t) (h1 h2 : t -> t), (forall m : t, m < n -> h1 m == h2 m) -> (if n << 2 then 0 else S (h1 (half n))) == (if n << 2 then 0 else S (h2 (half n)))n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 m(if n << 2 then 0 else S (h1 (half n))) == (if n << 2 then 0 else S (h2 (half n)))n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:(n << 2) = true0 == 0n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:(n << 2) = falseS (h1 (half n)) == S (h2 (half n))n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:(n << 2) = falseS (h1 (half n)) == S (h2 (half n))n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:(n << 2) = falseh1 (half n) == h2 (half n)n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:(n << 2) = false0 < norder'. Qed. Hint Resolve log_good_step : core.n:th1, h2:t -> tE:forall m : t, m < n -> h1 m == h2 mH:1 < n0 < nforall n : t, n < 2 -> log n == 0forall n : t, n < 2 -> log n == 0n:tHn:n < 2log n == 0n:tHn:n < 2strong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) n == 0n:tHn:n < 2(if n << 2 then 0 else S (strong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) (half n))) == 0n:tHn:n < 2true = (n << 2)now rewrite ltb_lt. Qed.n:tHn:n < 2(n << 2) = trueforall n : t, 2 <= n -> log n == S (log (half n))forall n : t, 2 <= n -> log n == S (log (half n))n:tHn:2 <= nlog n == S (log (half n))n:tHn:2 <= nstrong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) n == S (strong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) (half n))n:tHn:2 <= n(if n << 2 then 0 else S (strong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) (half n))) == S (strong_rec 0 (fun (g : t -> t) (x : t) => if x << 2 then 0 else S (g (half x))) (half n))n:tHn:2 <= nfalse = (n << 2)rewrite <- not_true_iff_false, ltb_lt, nlt_ge; auto. Qed.n:tHn:2 <= n(n << 2) = falseforall n : t, 0 < n -> half n < 2 ^^ log n <= nforall n : t, 0 < n -> half n < 2 ^^ log n <= nn:tn <= n -> 0 < n -> half n < 2 ^^ log n <= nn:tk:=n:tk <= n -> 0 < k -> half k < 2 ^^ log k <= kn, k:tk <= n -> 0 < k -> half k < 2 ^^ log k <= kn:tforall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= kn:t(fun t0 : t => forall k : t, k <= t0 -> 0 < k -> half k < 2 ^^ log k <= k) nProper (eq ==> iff) (fun t0 : t => forall k : t, k <= t0 -> 0 < k -> half k < 2 ^^ log k <= k)forall k : t, k <= 0 -> 0 < k -> half k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kforall k : t, k <= 0 -> 0 < k -> half k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kk:tHk1:k <= 0Hk2:0 < khalf k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kk:tHk1:k < 0Hk2:0 < khalf k < 2 ^^ log k <= kk:tHk1:k == 0Hk2:0 < khalf k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kk:tHk1:k == 0Hk2:0 < khalf k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kk:tHk1:k == 0Hk2:0 < 0half k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kforall n : t, (forall k : t, k <= n -> 0 < k -> half k < 2 ^^ log k <= k) -> forall k : t, k <= S n -> 0 < k -> half k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < khalf k < 2 ^^ log k <= k(* base *)n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLT:k < 2half k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 <= kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 < kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 == kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 < kLT:~ 1 < khalf k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 == kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 == kLT:k < 2half k < 1 <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:1 == kLT:k < 2half 1 < 1 <= 1n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= k(* step *)n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 ^^ log k <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:2 <= khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < khalf k <= nn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < k0 < half kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kIH1:half (half k) < 2 ^^ log (half k)IH2:2 ^^ log (half k) <= half khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < khalf k < S nn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < k0 < half kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kIH1:half (half k) < 2 ^^ log (half k)IH2:2 ^^ log (half k) <= half khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < khalf k < kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < k0 < half kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kIH1:half (half k) < 2 ^^ log (half k)IH2:2 ^^ log (half k) <= half khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < k0 < half kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kIH1:half (half k) < 2 ^^ log (half k)IH2:2 ^^ log (half k) <= half khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kIH1:half (half k) < 2 ^^ log (half k)IH2:2 ^^ log (half k) <= half khalf k < 2 * 2 ^^ log (half k) <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half khalf k < 2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half khalf k < 2 * Kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:S (half (half k)) <= KIH2:K <= half khalf k < 2 * Kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:2 * S (half (half k)) <= 2 * KIH2:K <= half khalf k < 2 * Kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:2 * S (half (half k)) <= 2 * KIH2:K <= half khalf k < 2 * S (half (half k))n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:2 * S (half (half k)) <= 2 * KIH2:K <= half khalf k < S (S (half (half k) + half (half k)))n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:2 * S (half (half k)) <= 2 * KIH2:K <= half khalf k <= S (half (half k) + half (half k))n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:2 * S (half (half k)) <= 2 * KIH2:K <= half k1 + 2 * half (half k) <= S (half (half k) + half (half k))n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kn:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= kapply mul_le_mono_l; auto. Qed. End NdefOpsProp.n:tIH:forall k0 : t, k0 <= n -> 0 < k0 -> half k0 < 2 ^^ log k0 <= k0k:tHk1:k <= S nHk2:0 < kLE:1 < kK:tIH1:half (half k) < KIH2:K <= half k2 * K <= 2 * half k