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) *)
(************************************************************************)
Base-2 Logarithm
Require Import NZAxioms NZMulOrder NZPow.
Interface of a log2 function, then its specification on naturals
Module Type Log2 (Import A : Typ). Parameter Inline log2 : t -> t. End Log2. Module Type NZLog2Spec (A : NZOrdAxiomsSig')(B : Pow' A)(C : Log2 A). Import A B C. Axiom log2_spec : forall a, 0<a -> 2^(log2 a) <= a < 2^(S (log2 a)). Axiom log2_nonpos : forall a, a<=0 -> log2 a == 0. End NZLog2Spec. Module Type NZLog2 (A : NZOrdAxiomsSig)(B : Pow A) := Log2 A <+ NZLog2Spec A B.
Derived properties of logarithm
Module Type NZLog2Prop
(Import A : NZOrdAxiomsSig')
(Import B : NZPow' A)
(Import C : NZLog2 A B)
(Import D : NZMulOrderProp A)
(Import E : NZPowProp A B D).
log2 is always non-negative
forall a : t, 0 <= log2 aforall a : t, 0 <= log2 aa:t0 <= log2 aa:tHa:a <= 00 <= log2 aa:tHa:0 < a0 <= log2 anow rewrite log2_nonpos.a:tHa:a <= 00 <= log2 aa:tHa:0 < a0 <= log2 aa:tHa:0 < aLT:a < 2 ^ S (log2 a)0 <= log2 aa:tHa:0 < aLT:a < 2 ^ S (log2 a)1 < 2a:tHa:0 < aLT:a < 2 ^ S (log2 a)1 < 2 ^ S (log2 a)order'.a:tHa:0 < aLT:a < 2 ^ S (log2 a)1 < 2a:tHa:0 < aLT:a < 2 ^ S (log2 a)1 < 2 ^ S (log2 a)order. Qed.a:tHa:1 <= aLT:a < 2 ^ S (log2 a)1 < 2 ^ S (log2 a)
A tactic for proving positivity and non-negativity
Ltac order_pos :=
((apply add_pos_pos || apply add_nonneg_nonneg ||
apply mul_pos_pos || apply mul_nonneg_nonneg ||
apply pow_nonneg || apply pow_pos_nonneg ||
apply log2_nonneg || apply (le_le_succ_r 0));
order_pos) (* in case of success of an apply, we recurse *)
|| order'. (* otherwise *)
The spec of log2 indeed determines it
forall a b : t, 0 <= b -> 2 ^ b <= a < 2 ^ S b -> log2 a == bforall a b : t, 0 <= b -> 2 ^ b <= a < 2 ^ S b -> log2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S blog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S b0 < aa, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < alog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S b0 < aapply pow_pos_nonneg; order'.a, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S b0 < 2 ^ ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < alog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 alog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)log2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)log2 a <= ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= blog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)log2 a <= bnow apply le_le_succ_r.a, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)0 <= S ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= blog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= bb <= log2 aa, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= bH0:b <= log2 alog2 a == ba, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= bb <= log2 anow apply le_le_succ_r.a, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= b0 <= S (log2 a)order. Qed.a, b:tHb:0 <= bLEb:2 ^ b <= aLTb:a < 2 ^ S bHa:0 < aHc:0 <= log2 aLEc:2 ^ log2 a <= aLTc:a < 2 ^ S (log2 a)H:log2 a <= bH0:b <= log2 alog2 a == b
Hence log2 is a morphism.
Proper (eq ==> eq) log2Proper (eq ==> eq) log2x, x':tHx:x == x'log2 x == log2 x'x, x':tHx:x == x'H:x <= 0log2 x == log2 x'x, x':tHx:x == x'H:0 < xlog2 x == log2 x'x, x':tHx:x == x'H:x <= 0log2 x == log2 x'x, x':tHx:x == x'H:x <= 00 == 0x, x':tHx:x == x'H:x <= 0x' <= 0reflexivity.x, x':tHx:x == x'H:x <= 00 == 0now rewrite <- Hx.x, x':tHx:x == x'H:x <= 0x' <= 0x, x':tHx:x == x'H:0 < xlog2 x == log2 x'x, x':tHx:x == x'H:0 < x0 <= log2 x'x, x':tHx:x == x'H:0 < x2 ^ log2 x' <= x < 2 ^ S (log2 x')apply log2_nonneg.x, x':tHx:x == x'H:0 < x0 <= log2 x'x, x':tHx:x == x'H:0 < x2 ^ log2 x' <= x < 2 ^ S (log2 x')now apply log2_spec. Qed.x, x':tHx:x == x'H:0 < x'2 ^ log2 x' <= x' < 2 ^ S (log2 x')
An alternate specification
forall a : t, 0 < a -> exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 aforall a : t, 0 < a -> exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 aa:tHa:0 < aexists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= rexists r0 : t, a == 2 ^ log2 a + r0 /\ 0 <= r0 < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra == 2 ^ log2 a + ra:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= r0 <= r < 2 ^ log2 anow rewrite add_comm.a:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra == 2 ^ log2 a + ra:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= r0 <= r < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= r0 <= ra:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= rr < 2 ^ log2 atrivial.a:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= r0 <= ra:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= rr < 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= rr + 2 ^ log2 a < 2 ^ log2 a + 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra < 2 ^ log2 a + 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra < 2 ^ S (log2 a) -> a < 2 ^ log2 a + 2 ^ log2 aa:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra < 2 * 2 ^ log2 a -> a < 2 ^ log2 a + 2 ^ log2 anow nzsimpl. Qed.a:tHa:0 < aLE:2 ^ log2 a <= aLT:a < 2 ^ S (log2 a)r:tHr:a == r + 2 ^ log2 aHr':0 <= ra < S 1 * 2 ^ log2 a -> a < 2 ^ log2 a + 2 ^ log2 aforall a b c : t, 0 <= b -> 0 <= c < 2 ^ b -> a == 2 ^ b + c -> log2 a == bforall a b c : t, 0 <= b -> 0 <= c < 2 ^ b -> a == 2 ^ b + c -> log2 a == ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + clog2 a == ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c0 <= ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b <= a < 2 ^ S btrivial.a, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c0 <= ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b <= a < 2 ^ S ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b <= 2 ^ b + c < 2 ^ S ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b <= 2 ^ b + ca, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + c < 2 ^ S ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b <= 2 ^ b + cnow apply add_le_mono_l.a, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + 0 <= 2 ^ b + ca, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + c < 2 ^ S ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + c < 2 * 2 ^ ba, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + c < S 1 * 2 ^ bnow apply add_lt_mono_l. Qed.a, b, c:tHb:0 <= bHc:0 <= cH:c < 2 ^ bEQ:a == 2 ^ b + c2 ^ b + c < 2 ^ b + 2 ^ b
log2 is exact on powers of 2
forall a : t, 0 <= a -> log2 (2 ^ a) == aforall a : t, 0 <= a -> log2 (2 ^ a) == aa:tHa:0 <= alog2 (2 ^ a) == aa:tHa:0 <= a0 <= 0 < 2 ^ aa:tHa:0 <= a2 ^ a == 2 ^ a + 0split; order_pos.a:tHa:0 <= a0 <= 0 < 2 ^ anow nzsimpl. Qed.a:tHa:0 <= a2 ^ a == 2 ^ a + 0
log2 and predecessors of powers of 2
forall a : t, 0 < a -> log2 (P (2 ^ a)) == P aforall a : t, 0 < a -> log2 (P (2 ^ a)) == P aa:tHa:0 < alog2 (P (2 ^ a)) == P aa:tHa:0 < aHa':S (P a) == alog2 (P (2 ^ a)) == P aa:tHa:0 < aHa':S (P a) == a0 <= P aa:tHa:0 < aHa':S (P a) == a2 ^ P a <= P (2 ^ a) < 2 ^ S (P a)apply lt_succ_r; order.a:tHa:0 < aHa':S (P a) == a0 <= P aa:tHa:0 < aHa':S (P a) == a2 ^ P a <= P (2 ^ a) < 2 ^ S (P a)a:tHa:0 < aHa':S (P a) == a2 ^ P a < S (P (2 ^ a)) <= 2 ^ aa:tHa:0 < aHa':S (P a) == a2 ^ P a < 2 ^ a <= 2 ^ aa:tHa:0 < aHa':S (P a) == a0 < 2 ^ aa:tHa:0 < aHa':S (P a) == a2 ^ P a < 2 ^ a <= 2 ^ aa:tHa:0 < aHa':S (P a) == a2 ^ P a < 2 ^ aa:tHa:0 < aHa':S (P a) == aP a < aapply lt_succ_diag_r.a:tHa:0 < aHa':S (P a) == aa < S aapply pow_pos_nonneg; order'. Qed.a:tHa:0 < aHa':S (P a) == a0 < 2 ^ a
log2 and basic constants
log2 1 == 0log2 1 == 0now apply log2_pow2. Qed.log2 (2 ^ 0) == 0log2 2 == 1log2 2 == 1apply log2_pow2; order'. Qed.log2 (2 ^ 1) == 1
log2 n is strictly positive for 1<n
forall a : t, 1 < a -> 0 < log2 aforall a : t, 1 < a -> 0 < log2 aa:tHa:1 < a0 < log2 aa:tHa:1 < aHa':0 < a0 < log2 aa:tHa:1 < aHa':0 < aH:0 <= log2 a0 < log2 aa:tHa:1 < aHa':0 < aH:0 == log2 a0 < log2 aa:tHa:1 < aHa':0 < aH:0 == log2 a2 ^ log2 a <= a < 2 ^ S (log2 a) -> 0 < log2 aa:tHa:1 < aHa':0 < aH:0 == log2 a2 ^ 0 <= a < 2 ^ S 0 -> 0 < 0a:tHa:1 < aHa':0 < aH:0 == log2 a1 <= a < 2 -> 0 < 0a:tHa:1 < aHa':0 < aH:0 == log2 aH':a < 20 < 0apply lt_succ_r in H'; order. Qed.a:tHa:1 < aHa':0 < aH:0 == log2 aH':a < S 10 < 0
Said otherwise, log2 is null only below 1
forall a : t, log2 a == 0 <-> a <= 1forall a : t, log2 a == 0 <-> a <= 1a:tlog2 a == 0 <-> a <= 1a:tH:log2 a == 0a <= 1a:tH:a <= 1log2 a == 0a:tH:log2 a == 0a <= 1generalize (log2_pos a Ha); order.a:tH:log2 a == 0Ha:1 < aa <= 1a:tH:a <= 1log2 a == 0a:tH:a < 1log2 a == 0a:tH:a == 1log2 a == 0a:tH:a < 1log2 a == 0a:tH:a < 1a <= 0now rewrite <- one_succ.a:tH:a < 1a < S 0a:tH:a == 1log2 a == 0apply log2_1. Qed.a:tH:a == 1log2 1 == 0
log2 is a monotone function (but not a strict one)
forall a b : t, a <= b -> log2 a <= log2 bforall a b : t, a <= b -> log2 a <= log2 ba, b:tH:a <= blog2 a <= log2 ba, b:tH:a <= bHa:a <= 0log2 a <= log2 ba, b:tH:a <= bHa:0 < alog2 a <= log2 brewrite log2_nonpos; order_pos.a, b:tH:a <= bHa:a <= 0log2 a <= log2 ba, b:tH:a <= bHa:0 < alog2 a <= log2 ba, b:tH:a <= bHa:0 < aHb:0 < blog2 a <= log2 ba, b:tH:a <= bHa:0 < aHb:0 < bLEa:2 ^ log2 a <= alog2 a <= log2 bapply lt_succ_r, (pow_lt_mono_r_iff 2); order_pos. Qed.a, b:tH:a <= bHa:0 < aHb:0 < bLEa:2 ^ log2 a <= aLTb:b < 2 ^ S (log2 b)log2 a <= log2 b
No reverse result for <=, consider for instance log2 3 <= log2 2
forall a b : t, log2 a < log2 b -> a < bforall a b : t, log2 a < log2 b -> a < ba, b:tH:log2 a < log2 ba < ba, b:tH:log2 a < log2 bHb:b <= 0a < ba, b:tH:log2 a < log2 bHb:0 < ba < ba, b:tH:log2 a < log2 bHb:b <= 0a < bgeneralize (log2_nonneg a); order.a, b:tH:log2 a < 0Hb:b <= 0a < ba, b:tH:log2 a < log2 bHb:0 < ba < ba, b:tH:log2 a < log2 bHb:0 < bHa:a <= 0a < ba, b:tH:log2 a < log2 bHb:0 < bHa:0 < aa < border.a, b:tH:log2 a < log2 bHb:0 < bHa:a <= 0a < ba, b:tH:log2 a < log2 bHb:0 < bHa:0 < aa < ba, b:tH:log2 a < log2 bHb:0 < bHa:0 < aLTa:a < 2 ^ S (log2 a)a < ba, b:tH:log2 a < log2 bHb:0 < bHa:0 < aLTa:a < 2 ^ S (log2 a)LEb:2 ^ log2 b <= ba < bapply (pow_le_mono_r_iff 2) in H; order_pos. Qed.a, b:tH:S (log2 a) <= log2 bHb:0 < bHa:0 < aLTa:a < 2 ^ S (log2 a)LEb:2 ^ log2 b <= ba < b
When left side is a power of 2, we have an equivalence for <=
forall a b : t, 0 < a -> 2 ^ b <= a <-> b <= log2 aforall a b : t, 0 < a -> 2 ^ b <= a <-> b <= log2 aa, b:tHa:0 < a2 ^ b <= a <-> b <= log2 aa, b:tHa:0 < aH:2 ^ b <= ab <= log2 aa, b:tHa:0 < aH:b <= log2 a2 ^ b <= aa, b:tHa:0 < aH:2 ^ b <= ab <= log2 aa, b:tHa:0 < aH:2 ^ b <= aHb:b < 0b <= log2 aa, b:tHa:0 < aH:2 ^ b <= aHb:0 <= bb <= log2 ageneralize (log2_nonneg a); order.a, b:tHa:0 < aH:2 ^ b <= aHb:b < 0b <= log2 aa, b:tHa:0 < aH:2 ^ b <= aHb:0 <= bb <= log2 anow apply log2_le_mono.a, b:tHa:0 < aH:2 ^ b <= aHb:0 <= blog2 (2 ^ b) <= log2 aa, b:tHa:0 < aH:b <= log2 a2 ^ b <= aa, b:tHa:0 < aH:b <= log2 a2 ^ b <= 2 ^ log2 aa, b:tHa:0 < aH:b <= log2 a2 ^ log2 a <= aapply pow_le_mono_r; order'.a, b:tHa:0 < aH:b <= log2 a2 ^ b <= 2 ^ log2 anow destruct (log2_spec a Ha). Qed.a, b:tHa:0 < aH:b <= log2 a2 ^ log2 a <= a
When right side is a square, we have an equivalence for <
forall a b : t, 0 < a -> a < 2 ^ b <-> log2 a < bforall a b : t, 0 < a -> a < 2 ^ b <-> log2 a < ba, b:tHa:0 < aa < 2 ^ b <-> log2 a < ba, b:tHa:0 < aH:a < 2 ^ blog2 a < ba, b:tHa:0 < aH:log2 a < ba < 2 ^ ba, b:tHa:0 < aH:a < 2 ^ blog2 a < ba, b:tHa:0 < aH:a < 2 ^ bHb:b < 0log2 a < ba, b:tHa:0 < aH:a < 2 ^ bHb:0 <= blog2 a < brewrite pow_neg_r in H; order.a, b:tHa:0 < aH:a < 2 ^ bHb:b < 0log2 a < ba, b:tHa:0 < aH:a < 2 ^ bHb:0 <= blog2 a < ba, b:tHa:0 < aH:a < 2 ^ bHb:0 <= b2 ^ log2 a < 2 ^ bnow destruct (log2_spec a Ha).a, b:tHa:0 < aH:a < 2 ^ bHb:0 <= b2 ^ log2 a <= aa, b:tHa:0 < aH:log2 a < ba < 2 ^ ba, b:tHa:0 < aH:log2 a < bHb:b < 0a < 2 ^ ba, b:tHa:0 < aH:log2 a < bHb:0 <= ba < 2 ^ bgeneralize (log2_nonneg a); order.a, b:tHa:0 < aH:log2 a < bHb:b < 0a < 2 ^ ba, b:tHa:0 < aH:log2 a < bHb:0 <= ba < 2 ^ bnow rewrite log2_pow2. Qed.a, b:tHa:0 < aH:log2 a < bHb:0 <= blog2 a < log2 (2 ^ b)
Comparing log2 and identity
forall a : t, 0 < a -> log2 a < aforall a : t, 0 < a -> log2 a < aa:tHa:0 < alog2 a < aa:tHa:0 < a2 ^ log2 a < 2 ^ aa:tHa:0 < a2 ^ log2 a <= aa:tHa:0 < aa < 2 ^ anow destruct (log2_spec a Ha).a:tHa:0 < a2 ^ log2 a <= aapply pow_gt_lin_r; order'. Qed.a:tHa:0 < aa < 2 ^ aforall a : t, 0 <= a -> log2 a <= aforall a : t, 0 <= a -> log2 a <= aa:tHa:0 <= alog2 a <= aa:tHa:0 < alog2 a <= aa:tHa:0 == alog2 a <= anow apply lt_le_incl, log2_lt_lin.a:tHa:0 < alog2 a <= arewrite <- Ha, log2_nonpos; order. Qed.a:tHa:0 == alog2 a <= a
Log2 and multiplication.
Due to rounding error, we don't have the usual
log2 (a×b) = log2 a + log2 b but we may be off by 1 at most
forall a b : t, 0 < a -> 0 < b -> log2 a + log2 b <= log2 (a * b)forall a b : t, 0 < a -> 0 < b -> log2 a + log2 b <= log2 (a * b)a, b:tHa:0 < aHb:0 < blog2 a + log2 b <= log2 (a * b)a, b:tHa:0 < aHb:0 < b2 ^ (log2 a + log2 b) <= a * bapply mul_le_mono_nonneg; try apply log2_spec; order_pos. Qed.a, b:tHa:0 < aHb:0 < b2 ^ log2 a * 2 ^ log2 b <= a * bforall a b : t, 0 <= a -> 0 <= b -> log2 (a * b) <= log2 a + log2 b + 1forall a b : t, 0 <= a -> 0 <= b -> log2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 <= aHb:0 <= blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 <= blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 == aHb:0 <= blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 <= blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 < blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 == blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 < blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 < blog2 (a * b) < S (log2 a + log2 b + 1)a, b:tHa:0 < aHb:0 < blog2 (a * b) < S (log2 a) + S (log2 b)a, b:tHa:0 < aHb:0 < ba * b < 2 ^ (S (log2 a) + S (log2 b))apply mul_lt_mono_nonneg; try order; now apply log2_spec.a, b:tHa:0 < aHb:0 < ba * b < 2 ^ S (log2 a) * 2 ^ S (log2 b)a, b:tHa:0 < aHb:0 == blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 < aHb:0 == blog2 (a * 0) <= log2 a + log2 0 + 1rewrite log2_nonpos; order_pos.a, b:tHa:0 < aHb:0 == blog2 0 <= S (log2 a + log2 0)a, b:tHa:0 == aHb:0 <= blog2 (a * b) <= log2 a + log2 b + 1a, b:tHa:0 == aHb:0 <= blog2 (0 * b) <= log2 0 + log2 b + 1rewrite log2_nonpos; order_pos. Qed.a, b:tHa:0 == aHb:0 <= blog2 0 <= S (log2 0 + log2 b)
And we can't find better approximations in general.
- The lower bound is exact for powers of 2.
- Concerning the upper bound, for any c>1, take a=b=2^c-1, then log2 (a*b) = c+c -1 while (log2 a) = (log2 b) = c-1
At least, we get back the usual equation when we multiply by 2 (or 2^k)
forall a b : t, 0 < a -> 0 <= b -> log2 (a * 2 ^ b) == b + log2 aforall a b : t, 0 < a -> 0 <= b -> log2 (a * 2 ^ b) == b + log2 aa, b:tHa:0 < aHb:0 <= blog2 (a * 2 ^ b) == b + log2 aa, b:tHa:0 < aHb:0 <= b2 ^ (b + log2 a) <= a * 2 ^ b < 2 ^ S (b + log2 a)a, b:tHa:0 < aHb:0 <= b2 ^ (b + log2 a) <= a * 2 ^ ba, b:tHa:0 < aHb:0 <= ba * 2 ^ b < 2 ^ S (b + log2 a)a, b:tHa:0 < aHb:0 <= b2 ^ (b + log2 a) <= a * 2 ^ ba, b:tHa:0 < aHb:0 <= b2 ^ log2 a * 2 ^ b <= a * 2 ^ ba, b:tHa:0 < aHb:0 <= b0 <= 2 ^ ba, b:tHa:0 < aHb:0 <= b2 ^ log2 a <= aorder_pos.a, b:tHa:0 < aHb:0 <= b0 <= 2 ^ bnow apply log2_spec.a, b:tHa:0 < aHb:0 <= b2 ^ log2 a <= aa, b:tHa:0 < aHb:0 <= ba * 2 ^ b < 2 ^ S (b + log2 a)a, b:tHa:0 < aHb:0 <= b2 ^ b * a < 2 ^ b * 2 ^ S (log2 a)a, b:tHa:0 < aHb:0 <= b0 < 2 ^ ba, b:tHa:0 < aHb:0 <= ba < 2 ^ S (log2 a)order_pos.a, b:tHa:0 < aHb:0 <= b0 < 2 ^ bnow apply log2_spec. Qed.a, b:tHa:0 < aHb:0 <= ba < 2 ^ S (log2 a)forall a : t, 0 < a -> log2 (2 * a) == S (log2 a)forall a : t, 0 < a -> log2 (2 * a) == S (log2 a)a:tHa:0 < alog2 (2 * a) == S (log2 a)now nzsimpl'. Qed.a:tHa:0 < alog2 (a * 2 ^ 1) == 1 + log2 a -> log2 (2 * a) == S (log2 a)
Two numbers with same log2 cannot be far away.
forall a b : t, 0 < a -> 0 < b -> log2 a == log2 b -> a < 2 * bforall a b : t, 0 < a -> 0 < b -> log2 a == log2 b -> a < 2 * ba, b:tHa:0 < aHb:0 < bH:log2 a == log2 ba < 2 * ba, b:tHa:0 < aHb:0 < bH:log2 a == log2 blog2 a < log2 (2 * b)apply lt_succ_diag_r. Qed.a, b:tHa:0 < aHb:0 < bH:log2 a == log2 blog2 b < S (log2 b)
Log2 and successor :
- the log2 function climbs by at most 1 at a time
- otherwise it stays at the same value
- the +1 steps occur for powers of two
forall a : t, log2 (S a) <= S (log2 a)forall a : t, log2 (S a) <= S (log2 a)a:tlog2 (S a) <= S (log2 a)a:tLT:0 < alog2 (S a) <= S (log2 a)a:tEQ:0 == alog2 (S a) <= S (log2 a)a:tLT:a < 0log2 (S a) <= S (log2 a)a:tLT:0 < alog2 (S a) <= S (log2 a)a:tLT:0 < a2 ^ log2 (S a) <= 2 ^ S (log2 a)a:tLT:0 < a2 ^ log2 (S a) <= S aa:tLT:0 < aS a <= 2 ^ S (log2 a)a:tLT:0 < a2 ^ log2 (S a) <= S aapply lt_succ_r; order.a:tLT:0 < a0 < S anow apply le_succ_l, log2_spec.a:tLT:0 < aS a <= 2 ^ S (log2 a)rewrite <- EQ, <- one_succ, log2_1; order_pos.a:tEQ:0 == alog2 (S a) <= S (log2 a)a:tLT:a < 0log2 (S a) <= S (log2 a)a:tLT:a < 00 <= S 0a:tLT:a < 0a <= 0a:tLT:a < 0S a <= 0order_pos.a:tLT:a < 00 <= S 0order'.a:tLT:a < 0a <= 0now rewrite le_succ_l. Qed.a:tLT:a < 0S a <= 0forall a : t, log2 (S a) == S (log2 a) \/ log2 (S a) == log2 aforall a : t, log2 (S a) == S (log2 a) \/ log2 (S a) == log2 aa:tlog2 (S a) == S (log2 a) \/ log2 (S a) == log2 aa:tH:log2 (S a) <= log2 alog2 (S a) == S (log2 a) \/ log2 (S a) == log2 aa:tH:log2 a < log2 (S a)log2 (S a) == S (log2 a) \/ log2 (S a) == log2 aa:tH:log2 (S a) <= log2 alog2 (S a) == S (log2 a) \/ log2 (S a) == log2 ageneralize (log2_le_mono _ _ (le_succ_diag_r a)); order.a:tH:log2 (S a) <= log2 alog2 (S a) == log2 aa:tH:log2 a < log2 (S a)log2 (S a) == S (log2 a) \/ log2 (S a) == log2 aa:tH:log2 a < log2 (S a)log2 (S a) == S (log2 a)generalize (log2_succ_le a); order. Qed.a:tH:S (log2 a) <= log2 (S a)log2 (S a) == S (log2 a)forall a : t, log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ bforall a : t, log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)exists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)Ha:a <= 0exists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)Ha:0 < aexists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)Ha:a <= 0exists b : t, S a == 2 ^ ba:tH:0 == S 0Ha:a <= 0exists b : t, S a == 2 ^ ba:tH:0 == S (log2 a)Ha:a <= 0a <= 1a:tH:log2 (S a) == S (log2 a)Ha:a <= 0S a <= 1generalize (lt_succ_diag_r 0); order.a:tH:0 == S 0Ha:a <= 0exists b : t, S a == 2 ^ border'.a:tH:0 == S (log2 a)Ha:a <= 0a <= 1a:tH:log2 (S a) == S (log2 a)Ha:a <= 0S a <= 1order'.a:tH:log2 (S a) == S (log2 a)Ha:a <= 0a < 1a:tH:log2 (S a) == S (log2 a)Ha:0 < aexists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)Ha:0 < aHa':0 < S aexists b : t, S a == 2 ^ ba:tH:log2 (S a) == S (log2 a)Ha:0 < aHa':0 < S aS a == 2 ^ log2 (S a)a:tH:log2 (S a) == S (log2 a)Ha:0 < aHa':0 < S a2 ^ log2 (S a) <= S a -> a < 2 ^ S (log2 a) -> S a == 2 ^ log2 (S a)order. Qed.a:tH:log2 (S a) == S (log2 a)Ha:0 < aHa':0 < S a2 ^ log2 (S a) <= S a -> S a <= 2 ^ log2 (S a) -> S a == 2 ^ log2 (S a)forall a : t, 0 < a -> log2 (S a) == S (log2 a) <-> (exists b : t, S a == 2 ^ b)forall a : t, 0 < a -> log2 (S a) == S (log2 a) <-> (exists b : t, S a == 2 ^ b)a:tHa:0 < alog2 (S a) == S (log2 a) <-> (exists b : t, S a == 2 ^ b)a:tHa:0 < alog2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ ba:tHa:0 < a(exists b : t, S a == 2 ^ b) -> log2 (S a) == S (log2 a)apply log2_eq_succ_is_pow2.a:tHa:0 < alog2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ ba:tHa:0 < a(exists b : t, S a == 2 ^ b) -> log2 (S a) == S (log2 a)a:tHa:0 < ab:tHb:S a == 2 ^ blog2 (S a) == S (log2 a)a:tHa:0 < ab:tHb:S a == 2 ^ b0 < ba:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < blog2 (S a) == S (log2 a)apply (pow_gt_1 2); try order'; now rewrite <- Hb, one_succ, <- succ_lt_mono.a:tHa:0 < ab:tHb:S a == 2 ^ b0 < ba:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < blog2 (S a) == S (log2 a)a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bb == S (log2 a)a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bb == S (log2 (P (2 ^ b)))a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < ba == P (2 ^ b)a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bb == S (log2 (P (2 ^ b)))symmetry; now apply lt_succ_pred with 0.a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bb == S (P b)a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < ba == P (2 ^ b)a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bS a == S (P (2 ^ b))a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < b2 ^ b == S (P (2 ^ b))a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < bS (P (2 ^ b)) == 2 ^ brewrite <- Hb, lt_succ_r; order. Qed.a:tHa:0 < ab:tHb:S a == 2 ^ bHb':0 < b0 < 2 ^ bforall a : t, 0 < a -> log2 (2 * a + 1) == S (log2 a)forall a : t, 0 < a -> log2 (2 * a + 1) == S (log2 a)a:tHa:0 < alog2 (2 * a + 1) == S (log2 a)a:tHa:0 < alog2 (S (2 * a)) == S (log2 a)a:tHa:0 < aH:log2 (S (2 * a)) == S (log2 (2 * a))Falsea:tHa:0 < aH:exists b : t, S (2 * a) == 2 ^ bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bLT:b < 0Falsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bEQ:b == 0Falsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bLT:0 < bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bLT:b < 0Falsea:tHa:0 < ab:tH:S (2 * a) == 0LT:b < 0Falsea:tHa:S 0 < S (2 * a)b:tH:S (2 * a) == 0LT:b < 0Falseorder'.a:tHa:1 < S (2 * a)b:tH:S (2 * a) == 0LT:b < 0Falsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bEQ:b == 0Falsea:tHa:0 < ab:tH:S (2 * a) == 1EQ:b == 0Falsea:tHa:S 0 < S (2 * a)b:tH:S (2 * a) == 1EQ:b == 0Falseorder'.a:tHa:1 < S (2 * a)b:tH:S (2 * a) == 1EQ:b == 0Falsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bLT:0 < bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 ^ bLT:0 < bEQ:S (P b) == bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLT':a < 2 ^ P bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLE':2 ^ P b <= aFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLT':a < 2 ^ P bFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLT':a < 2 ^ P b1 + 2 * a < 2 * 2 ^ P b -> Falseorder.a:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLT':a < 2 ^ P bS (2 * a) < 2 * 2 ^ P b -> Falsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLE':2 ^ P b <= aFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLE':2 * 2 ^ P b <= 2 * aFalsea:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLE':S (2 * a) <= 2 * aFalseorder. Qed.a:tHa:0 < ab:tH:S (2 * a) == 2 * 2 ^ P bLT:0 < bEQ:S (P b) == bLE':2 * a < 2 * aFalse
Log2 and addition
forall a b : t, a ~= 1 -> b ~= 1 -> log2 (a + b) <= log2 a + log2 bforall a b : t, a ~= 1 -> b ~= 1 -> log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < alog2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0log2 (a + b) <= 0 + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0log2 (a + b) <= log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0a + b <= bnow apply add_le_mono.a, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0a + b <= 0 + ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < alog2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':1 < blog2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0log2 (a + b) <= log2 a + log2 ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0log2 (a + b) <= log2 a + 0a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0log2 (a + b) <= log2 aa, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0a + b <= anow apply add_le_mono.a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0a + b <= a + 0a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':1 < blog2 (a + b) <= log2 a + log2 ba, b:tHa':1 < aHb':1 < blog2 (a + b) <= log2 a + log2 ba, b:tHa':1 < aHb':1 < blog2 (a + b) < S (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba + b < 2 ^ S (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba + b < 2 * 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba + b < S (S 0) * 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba + b < 2 ^ (log2 a + log2 b) + 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba < 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < bb < 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba < 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < ba < 2 ^ S (log2 a)a, b:tHa':1 < aHb':1 < b2 ^ S (log2 a) <= 2 ^ (log2 a + log2 b)apply log2_spec; order'.a, b:tHa':1 < aHb':1 < ba < 2 ^ S (log2 a)a, b:tHa':1 < aHb':1 < b2 ^ S (log2 a) <= 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < b0 < 2a, b:tHa':1 < aHb':1 < bS (log2 a) <= log2 a + log2 border'.a, b:tHa':1 < aHb':1 < b0 < 2a, b:tHa':1 < aHb':1 < bS (log2 a) <= log2 a + log2 ba, b:tHa':1 < aHb':1 < blog2 a + 1 <= log2 a + log2 brewrite one_succ; now apply le_succ_l, log2_pos.a, b:tHa':1 < aHb':1 < b1 <= log2 ba, b:tHa':1 < aHb':1 < bb < 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < bb < 2 ^ S (log2 b)a, b:tHa':1 < aHb':1 < b2 ^ S (log2 b) <= 2 ^ (log2 a + log2 b)apply log2_spec; order'.a, b:tHa':1 < aHb':1 < bb < 2 ^ S (log2 b)a, b:tHa':1 < aHb':1 < b2 ^ S (log2 b) <= 2 ^ (log2 a + log2 b)a, b:tHa':1 < aHb':1 < b0 < 2a, b:tHa':1 < aHb':1 < bS (log2 b) <= log2 a + log2 border'.a, b:tHa':1 < aHb':1 < b0 < 2a, b:tHa':1 < aHb':1 < bS (log2 b) <= log2 a + log2 ba, b:tHa':1 < aHb':1 < b1 + log2 b <= log2 a + log2 brewrite one_succ; now apply le_succ_l, log2_pos. Qed.a, b:tHa':1 < aHb':1 < b1 <= log2 a
The sum of two log2 is less than twice the log2 of the sum.
The large inequality is obvious thanks to monotonicity.
The strict one requires some more work. This is almost
a convexity inequality for points 2a, 2b and their middle a+b :
ideally, we would have 2*log(a+b) ≥ log(2a)+log(2b) = 2+log a+log b.
Here, we cannot do better: consider for instance a=2 b=4, then 1+2<2*2
forall a b : t, 0 < a -> 0 < b -> log2 a + log2 b < 2 * log2 (a + b)forall a b : t, 0 < a -> 0 < b -> log2 a + log2 b < 2 * log2 (a + b)a, b:tHa:0 < aHb:0 < blog2 a + log2 b < 2 * log2 (a + b)a, b:tHa:0 < aHb:0 < blog2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < blog2 a <= log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < blog2 a <= log2 (a + b)a, b:tHa:0 < aHb:0 < ba <= a + bapply add_le_mono; order.a, b:tHa:0 < aHb:0 < ba + 0 <= a + ba, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)log2 b <= log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)log2 b <= log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)b <= a + bapply add_le_mono; order.a, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)0 + b <= a + ba, b:tHa:0 < aHb:0 < bH:log2 a <= log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a == log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 ba, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 (a + b) + log2 b <= log2 (a + b) + log2 (a + b)now apply add_lt_mono_r.a, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 bnow apply add_le_mono_l.a, b:tHa:0 < aHb:0 < bH:log2 a < log2 (a + b)H':log2 b <= log2 (a + b)log2 (a + b) + log2 b <= log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a == log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 (a + b) + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a == log2 (a + b)H':log2 b <= log2 (a + b)log2 a + log2 b < log2 a + log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a == log2 (a + b)H':log2 b <= log2 (a + b)log2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 a == log2 (a + b)H':log2 b == log2 (a + b)log2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < bH:log2 (a + b) == log2 aH':log2 b == log2 (a + b)log2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':log2 b == log2 (a + b)log2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':log2 (a + b) == log2 blog2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':a + b < 2 * blog2 b < log2 (a + b)a, b:tHa:0 < aHb:0 < ba + b < 2 * a -> a + b < 2 * b -> log2 b < log2 (a + b)rewrite <- add_lt_mono_l, <- add_lt_mono_r; order. Qed. End NZLog2Prop. Module NZLog2UpProp (Import A : NZDecOrdAxiomsSig') (Import B : NZPow' A) (Import C : NZLog2 A B) (Import D : NZMulOrderProp A) (Import E : NZPowProp A B D) (Import F : NZLog2Prop A B C D E).a, b:tHa:0 < aHb:0 < ba + b < a + a -> a + b < b + b -> log2 b < log2 (a + b)
For once, we define instead of axiomatizing, thanks to log2
Definition log2_up a := match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end.forall a : t, a <= 1 -> log2_up a == 0forall a : t, a <= 1 -> log2_up a == 0a:tHa:a <= 1log2_up a == 0case compare_spec; try order. Qed.a:tHa:a <= 1match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end == 0forall a : t, 1 < a -> log2_up a == S (log2 (P a))forall a : t, 1 < a -> log2_up a == S (log2 (P a))a:tHa:1 < alog2_up a == S (log2 (P a))case compare_spec; try order. Qed.a:tHa:1 < amatch compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end == S (log2 (P a))forall a : t, 1 < a -> 2 ^ P (log2_up a) < a <= 2 ^ log2_up aforall a : t, 1 < a -> 2 ^ P (log2_up a) < a <= 2 ^ log2_up aa:tHa:1 < a2 ^ P (log2_up a) < a <= 2 ^ log2_up aa:tHa:1 < a2 ^ P (S (log2 (P a))) < a <= 2 ^ S (log2 (P a))a:tHa:1 < a2 ^ log2 (P a) < a <= 2 ^ S (log2 (P a))a:tHa:1 < a2 ^ log2 (P a) < S (P a) <= 2 ^ S (log2 (P a))a:tHa:1 < a2 ^ log2 (P a) <= P a < 2 ^ S (log2 (P a))a:tHa:1 < a0 < P anow rewrite (lt_succ_pred 1 a Ha), <- one_succ. Qed.a:tHa:1 < aS 0 < S (P a)forall a : t, a <= 0 -> log2_up a == 0forall a : t, a <= 0 -> log2_up a == 0a:tH:a <= 0log2_up a == 0order'. Qed.a:tH:a <= 0a <= 1Proper (eq ==> eq) log2_upProper (eq ==> eq) log2_upProper (eq ==> eq ==> Logic.eq) compareH:Proper (eq ==> eq ==> Logic.eq) compareProper (eq ==> eq) log2_uprepeat red; intros; do 2 case compare_spec; trivial; order.Proper (eq ==> eq ==> Logic.eq) compareH:Proper (eq ==> eq ==> Logic.eq) compareProper (eq ==> eq) log2_upH:Proper (eq ==> eq ==> Logic.eq) comparea, a':tHa:a == a'log2_up a == log2_up a'H:Proper (eq ==> eq ==> Logic.eq) comparea, a':tHa:a == a'match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end == match compare 1 a' with | Lt => S (log2 (P a')) | _ => 0 endcase compare; now rewrite ?Ha. Qed.H:Proper (eq ==> eq ==> Logic.eq) comparea, a':tHa:a == a'match compare 1 a' with | Lt => S (log2 (P a)) | _ => 0 end == match compare 1 a' with | Lt => S (log2 (P a')) | _ => 0 end
log2_up is always non-negative
forall a : t, 0 <= log2_up aforall a : t, 0 <= log2_up aa:t0 <= log2_up aa:t0 <= match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 enda:t1 < a -> 0 <= S (log2 (P a))apply le_le_succ_r, log2_nonneg. Qed.a:tH:1 < a0 <= S (log2 (P a))
The spec of log2_up indeed determines it
forall a b : t, 0 < b -> 2 ^ P b < a <= 2 ^ b -> log2_up a == bforall a b : t, 0 < b -> 2 ^ P b < a <= 2 ^ b -> log2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ blog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b1 < aa, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b1 < aa, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b1 <= 2 ^ P ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bS 0 <= 2 ^ P ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 < 2 ^ P ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 < 2a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 <= P border'.a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 < 2a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 <= P bnow rewrite (lt_succ_pred 0 b Hb).a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ b0 < S (P b)a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up ab <= log2_up aa, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up ab <= log2_up aa, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up ab < S (log2_up a)a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aS (P b) < S (log2_up a)apply (pow_lt_mono_r_iff 2); try order'.a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aP b < log2_up aa, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up alog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up alog2_up a <= ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up aH0:log2_up a <= blog2_up a == ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up alog2_up a <= ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up alog2_up a < S ba, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up aS (P (log2_up a)) < S bapply (pow_lt_mono_r_iff 2); try order'.a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up aP (log2_up a) < border. Qed.a, b:tHb:0 < bLEb:2 ^ P b < aLTb:a <= 2 ^ bHa:1 < aHc:0 <= log2_up aLTc:2 ^ P (log2_up a) < aLEc:a <= 2 ^ log2_up aH:b <= log2_up aHc':0 < log2_up aH0:log2_up a <= blog2_up a == b
log2_up is exact on powers of 2
forall a : t, 0 <= a -> log2_up (2 ^ a) == aforall a : t, 0 <= a -> log2_up (2 ^ a) == aa:tHa:0 <= alog2_up (2 ^ a) == aa:tHa:0 < alog2_up (2 ^ a) == aa:tHa:0 == alog2_up (2 ^ a) == aa:tHa:0 < alog2_up (2 ^ a) == aa:tHa:0 < a2 ^ P a < 2 ^ a <= 2 ^ aa:tHa:0 < a2 ^ P a < 2 ^ aa:tHa:0 < aP a < anow apply lt_succ_r.a:tHa:0 < aP a < S (P a)now rewrite <- Ha, pow_0_r, log2_up_eqn0. Qed.a:tHa:0 == alog2_up (2 ^ a) == a
log2_up and successors of powers of 2
forall a : t, 0 <= a -> log2_up (S (2 ^ a)) == S aforall a : t, 0 <= a -> log2_up (S (2 ^ a)) == S aa:tHa:0 <= alog2_up (S (2 ^ a)) == S aa:tHa:0 <= a1 < S (2 ^ a)apply pow_pos_nonneg; order'. Qed.a:tHa:0 <= a0 < 2 ^ a
Basic constants
log2_up 1 == 0now apply log2_up_eqn0. Qed.log2_up 1 == 0log2_up 2 == 1log2_up 2 == 1apply log2_up_pow2; order'. Qed.log2_up (2 ^ 1) == 1
Links between log2 and log2_up
forall a : t, log2 a <= log2_up aforall a : t, log2 a <= log2_up aa:tlog2 a <= log2_up aa:tlog2 a <= match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 enda:tH:1 == alog2 a <= 0a:tH:1 < alog2 a <= S (log2 (P a))a:tH:a < 1log2 a <= 0a:tH:1 == alog2 a <= 0order.a:tH:1 == a0 <= 0a:tH:1 < alog2 a <= S (log2 (P a))apply log2_succ_le.a:tH:1 < alog2 (S (P a)) <= S (log2 (P a))a:tH:a < 1log2 a <= 0a:tH:a < 10 <= 0a:tH:a < 1a <= 0order.a:tH:a < 10 <= 0now rewrite <-lt_succ_r, <-one_succ. Qed.a:tH:a < 1a <= 0forall a : t, log2_up a <= S (log2 a)forall a : t, log2_up a <= S (log2 a)a:tlog2_up a <= S (log2 a)a:tmatch compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end <= S (log2 a)a:tH:1 < aS (log2 (P a)) <= S (log2 a)a:tH:1 < alog2 (P a) <= log2 aa:tH:1 < aP a <= aapply le_succ_diag_r. Qed.a:tH:1 < aP a <= S (P a)forall a : t, 0 < a -> 2 ^ log2 a <= a <= 2 ^ log2_up aforall a : t, 0 < a -> 2 ^ log2 a <= a <= 2 ^ log2_up aa:tH:0 < a2 ^ log2 a <= a <= 2 ^ log2_up aa:tH:0 < a2 ^ log2 a <= aa:tH:0 < aa <= 2 ^ log2_up anow apply log2_spec.a:tH:0 < a2 ^ log2 a <= aa:tH:0 < aa <= 2 ^ log2_up aa:tH:1 <= aa <= 2 ^ log2_up aa:tH:1 < aa <= 2 ^ log2_up aa:tH:1 == aa <= 2 ^ log2_up anow apply log2_up_spec.a:tH:1 < aa <= 2 ^ log2_up anow rewrite <-H, log2_up_1, pow_0_r. Qed.a:tH:1 == aa <= 2 ^ log2_up aforall a : t, 0 < a -> log2 a == log2_up a <-> (exists b : t, a == 2 ^ b)forall a : t, 0 < a -> log2 a == log2_up a <-> (exists b : t, a == 2 ^ b)a:tHa:0 < alog2 a == log2_up a <-> (exists b : t, a == 2 ^ b)a:tHa:0 < alog2 a == log2_up a -> exists b : t, a == 2 ^ ba:tHa:0 < a(exists b : t, a == 2 ^ b) -> log2 a == log2_up aa:tHa:0 < alog2 a == log2_up a -> exists b : t, a == 2 ^ ba:tHa:0 < aH:log2 a == log2_up aexists b : t, a == 2 ^ ba:tHa:0 < aH:log2 a == log2_up aa == 2 ^ log2 aa:tHa:0 < aH:log2 a == log2_up a2 ^ log2 a <= a <= 2 ^ log2_up a -> a == 2 ^ log2 adestruct 1; order.a:tHa:0 < aH:log2 a == log2_up a2 ^ log2 a <= a <= 2 ^ log2 a -> a == 2 ^ log2 aa:tHa:0 < a(exists b : t, a == 2 ^ b) -> log2 a == log2_up aa:tHa:0 < ab:tHb:a == 2 ^ blog2 a == log2_up aa:tHa:0 < ab:tHb:a == 2 ^ blog2 (2 ^ b) == log2_up (2 ^ b)a:tHa:0 < ab:tHb:a == 2 ^ bH:0 <= blog2 (2 ^ b) == log2_up (2 ^ b)a:tHa:0 < ab:tHb:a == 2 ^ bH:b < 0log2 (2 ^ b) == log2_up (2 ^ b)now rewrite log2_pow2, log2_up_pow2.a:tHa:0 < ab:tHb:a == 2 ^ bH:0 <= blog2 (2 ^ b) == log2_up (2 ^ b)a:tHa:0 < ab:tHb:a == 2 ^ bH:b < 0log2 (2 ^ b) == log2_up (2 ^ b)now rewrite log2_nonpos, log2_up_nonpos. Qed.a:tHa:0 < ab:tHb:a == 2 ^ bH:b < 0log2 0 == log2_up 0
log2_up n is strictly positive for 1<n
forall a : t, 1 < a -> 0 < log2_up aforall a : t, 1 < a -> 0 < log2_up aa:tH:1 < a0 < log2_up aapply lt_succ_r; order_pos. Qed.a:tH:1 < a0 < S (log2 (P a))
Said otherwise, log2_up is null only below 1
forall a : t, log2_up a == 0 <-> a <= 1forall a : t, log2_up a == 0 <-> a <= 1a:tlog2_up a == 0 <-> a <= 1a:tH:log2_up a == 0a <= 1a:tH:a <= 1log2_up a == 0a:tH:log2_up a == 0a <= 1generalize (log2_up_pos a Ha); order.a:tH:log2_up a == 0Ha:1 < aa <= 1now apply log2_up_eqn0. Qed.a:tH:a <= 1log2_up a == 0
log2_up is a monotone function (but not a strict one)
forall a b : t, a <= b -> log2_up a <= log2_up bforall a b : t, a <= b -> log2_up a <= log2_up ba, b:tH:a <= blog2_up a <= log2_up ba, b:tH:a <= bHa:a <= 1log2_up a <= log2_up ba, b:tH:a <= bHa:1 < alog2_up a <= log2_up ba, b:tH:a <= bHa:a <= 1log2_up a <= log2_up bapply log2_up_nonneg.a, b:tH:a <= bHa:a <= 10 <= log2_up ba, b:tH:a <= bHa:1 < alog2_up a <= log2_up ba, b:tH:a <= bHa:1 < aS (log2 (P a)) <= S (log2 (P b))a, b:tH:a <= bHa:1 < alog2 (P a) <= log2 (P b)rewrite 2 lt_succ_pred with 1; order. Qed.a, b:tH:a <= bHa:1 < aS (P a) <= S (P b)
No reverse result for <=, consider for instance log2_up 4 <= log2_up 3
forall a b : t, log2_up a < log2_up b -> a < bforall a b : t, log2_up a < log2_up b -> a < ba, b:tH:log2_up a < log2_up ba < ba, b:tH:log2_up a < log2_up bHb:b <= 1a < ba, b:tH:log2_up a < log2_up bHb:1 < ba < ba, b:tH:log2_up a < log2_up bHb:b <= 1a < bgeneralize (log2_up_nonneg a); order.a, b:tH:log2_up a < 0Hb:b <= 1a < ba, b:tH:log2_up a < log2_up bHb:1 < ba < ba, b:tH:log2_up a < log2_up bHb:1 < bHa:a <= 1a < ba, b:tH:log2_up a < log2_up bHb:1 < bHa:1 < aa < border.a, b:tH:log2_up a < log2_up bHb:1 < bHa:a <= 1a < ba, b:tH:log2_up a < log2_up bHb:1 < bHa:1 < aa < ba, b:tH:S (log2 (P a)) < S (log2 (P b))Hb:1 < bHa:1 < aa < ba, b:tH:log2 (P a) < log2 (P b)Hb:1 < bHa:1 < aa < brewrite 2 lt_succ_pred with 1 in H; order. Qed.a, b:tH:S (P a) < S (P b)Hb:1 < bHa:1 < aa < b
When left side is a power of 2, we have an equivalence for <
forall a b : t, 0 < a -> 2 ^ b < a <-> b < log2_up aforall a b : t, 0 < a -> 2 ^ b < a <-> b < log2_up aa, b:tHa:0 < a2 ^ b < a <-> b < log2_up aa, b:tHa:0 < aH:2 ^ b < ab < log2_up aa, b:tHa:0 < aH:b < log2_up a2 ^ b < aa, b:tHa:0 < aH:2 ^ b < ab < log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:b < 0b < log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= bb < log2_up ageneralize (log2_up_nonneg a); order.a, b:tHa:0 < aH:2 ^ b < aHb:b < 0b < log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= bb < log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= b1 < 2a, b:tHa:0 < aH:2 ^ b < aHb:0 <= b0 <= log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= b2 ^ b < 2 ^ log2_up aorder'.a, b:tHa:0 < aH:2 ^ b < aHb:0 <= b1 < 2apply log2_up_nonneg.a, b:tHa:0 < aH:2 ^ b < aHb:0 <= b0 <= log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= b2 ^ b < 2 ^ log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= ba <= 2 ^ log2_up aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= b1 < aa, b:tHa:0 < aH:2 ^ b < aHb:0 <= b1 <= 2 ^ bapply pow_pos_nonneg; order'.a, b:tHa:0 < aH:2 ^ b < aHb:0 <= b0 < 2 ^ ba, b:tHa:0 < aH:b < log2_up a2 ^ b < aa, b:tHa:0 < aH:b < log2_up aHb:b < 02 ^ b < aa, b:tHa:0 < aH:b < log2_up aHb:0 <= b2 ^ b < anow rewrite pow_neg_r.a, b:tHa:0 < aH:b < log2_up aHb:b < 02 ^ b < aa, b:tHa:0 < aH:b < log2_up aHb:0 <= b2 ^ b < anow apply log2_up_lt_cancel. Qed.a, b:tHa:0 < aH:log2_up (2 ^ b) < log2_up aHb:0 <= b2 ^ b < a
When right side is a square, we have an equivalence for <=
forall a b : t, 0 < a -> a <= 2 ^ b <-> log2_up a <= bforall a b : t, 0 < a -> a <= 2 ^ b <-> log2_up a <= ba, b:tHa:0 < aa <= 2 ^ b <-> log2_up a <= ba, b:tHa:0 < aH:a <= 2 ^ blog2_up a <= ba, b:tHa:0 < aH:log2_up a <= ba <= 2 ^ ba, b:tHa:0 < aH:a <= 2 ^ blog2_up a <= ba, b:tHa:0 < aH:a <= 2 ^ bHb:b < 0log2_up a <= ba, b:tHa:0 < aH:a <= 2 ^ bHb:0 <= blog2_up a <= brewrite pow_neg_r in H; order.a, b:tHa:0 < aH:a <= 2 ^ bHb:b < 0log2_up a <= ba, b:tHa:0 < aH:a <= 2 ^ bHb:0 <= blog2_up a <= bnow apply log2_up_le_mono.a, b:tHa:0 < aH:a <= 2 ^ bHb:0 <= blog2_up a <= log2_up (2 ^ b)a, b:tHa:0 < aH:log2_up a <= ba <= 2 ^ ba, b:tHa:0 < aH:log2_up a <= ba <= 2 ^ log2_up aa, b:tHa:0 < aH:log2_up a <= b2 ^ log2_up a <= 2 ^ bnow apply log2_log2_up_spec.a, b:tHa:0 < aH:log2_up a <= ba <= 2 ^ log2_up aapply pow_le_mono_r; order'. Qed.a, b:tHa:0 < aH:log2_up a <= b2 ^ log2_up a <= 2 ^ b
Comparing log2_up and identity
forall a : t, 0 < a -> log2_up a < aforall a : t, 0 < a -> log2_up a < aa:tHa:0 < alog2_up a < aa:tHa:0 < aH:S (P a) == alog2_up a < aa:tHa:0 < aH:S (P a) == alog2_up a < S (P a)a:tHa:0 < aH:S (P a) == alog2_up a <= P aa:tHa:0 < aH:S (P a) == aa <= 2 ^ P aa:tHa:0 < aH:S (P a) == aS (P a) <= 2 ^ P aa:tHa:0 < aH:S (P a) == aP a < 2 ^ P aa:tHa:0 < aH:S (P a) == a1 < 2a:tHa:0 < aH:S (P a) == a0 <= P aorder'.a:tHa:0 < aH:S (P a) == a1 < 2apply lt_succ_r; order. Qed.a:tHa:0 < aH:S (P a) == a0 <= P aforall a : t, 0 <= a -> log2_up a <= aforall a : t, 0 <= a -> log2_up a <= aa:tHa:0 <= alog2_up a <= aa:tHa:0 < alog2_up a <= aa:tHa:0 == alog2_up a <= anow apply lt_le_incl, log2_up_lt_lin.a:tHa:0 < alog2_up a <= arewrite <- Ha, log2_up_nonpos; order. Qed.a:tHa:0 == alog2_up a <= a
log2_up and multiplication.
Due to rounding error, we don't have the usual
log2_up (a×b) = log2_up a + log2_up b but we may be off by 1 at most
forall a b : t, 0 <= a -> 0 <= b -> log2_up (a * b) <= log2_up a + log2_up bforall a b : t, 0 <= a -> 0 <= b -> log2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 <= aHb:0 <= blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 <= aHb:0 <= bHa':0 <= log2_up alog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 <= aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 == aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 < bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 == bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 < bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 < bHa':0 <= log2_up aHb':0 <= log2_up ba * b <= 2 ^ (log2_up a + log2_up b)apply mul_le_mono_nonneg; try apply log2_log2_up_spec; order'.a, b:tHa:0 < aHb:0 < bHa':0 <= log2_up aHb':0 <= log2_up ba * b <= 2 ^ log2_up a * 2 ^ log2_up ba, b:tHa:0 < aHb:0 == bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 < aHb:0 == bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * 0) <= log2_up a + log2_up 0rewrite log2_up_nonpos; order_pos.a, b:tHa:0 < aHb:0 == bHa':0 <= log2_up aHb':0 <= log2_up blog2_up 0 <= log2_up a + log2_up 0a, b:tHa:0 == aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (a * b) <= log2_up a + log2_up ba, b:tHa:0 == aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up (0 * b) <= log2_up 0 + log2_up brewrite log2_up_nonpos; order_pos. Qed.a, b:tHa:0 == aHb:0 <= bHa':0 <= log2_up aHb':0 <= log2_up blog2_up 0 <= log2_up 0 + log2_up bforall a b : t, 0 < a -> 0 < b -> log2_up a + log2_up b <= S (log2_up (a * b))forall a b : t, 0 < a -> 0 < b -> log2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:0 < aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 <= aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 == aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 <= blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 == blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up alog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up blog2_up a + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up bS (P (log2_up a)) + log2_up b <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up bS (P (log2_up a)) + S (P (log2_up b)) <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up bS (S (P (log2_up a) + P (log2_up b))) <= S (log2_up (a * b))a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up bP (log2_up a) + P (log2_up b) < log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b1 < 2a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b0 <= log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b2 ^ (P (log2_up a) + P (log2_up b)) < 2 ^ log2_up (a * b)order'.a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b1 < 2apply log2_up_nonneg.a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b0 <= log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b2 ^ (P (log2_up a) + P (log2_up b)) < 2 ^ log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b2 ^ P (log2_up a) * 2 ^ P (log2_up b) < 2 ^ log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b2 ^ P (log2_up a) * 2 ^ P (log2_up b) < a * ba, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up ba * b <= 2 ^ log2_up (a * b)apply mul_lt_mono_nonneg; try order_pos; try now apply log2_up_spec.a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b2 ^ P (log2_up a) * 2 ^ P (log2_up b) < a * ba, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up ba * b <= 2 ^ log2_up (a * b)a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b1 < a * bapply mul_lt_mono_nonneg; order'.a, b:tHa:1 < aHb:1 < bHa':0 < log2_up aHb':0 < log2_up b1 * 1 < a * ba, b:tHa:1 < aHb:1 == blog2_up a + log2_up b <= S (log2_up (a * b))apply le_succ_diag_r.a, b:tHa:1 < aHb:1 == blog2_up a <= S (log2_up a)a, b:tHa:1 == aHb:0 < blog2_up a + log2_up b <= S (log2_up (a * b))apply le_succ_diag_r. Qed.a, b:tHa:1 == aHb:0 < blog2_up b <= S (log2_up b)
And we can't find better approximations in general.
- The upper bound is exact for powers of 2.
- Concerning the lower bound, for any c>1, take a=b=2^c+1, then log2_up (a×b) = c+c +1 while (log2_up a) = (log2_up b) = c+1
At least, we get back the usual equation when we multiply by 2 (or 2^k)
forall a b : t, 0 < a -> 0 <= b -> log2_up (a * 2 ^ b) == b + log2_up aforall a b : t, 0 < a -> 0 <= b -> log2_up (a * 2 ^ b) == b + log2_up aa, b:tHa:0 < aHb:0 <= blog2_up (a * 2 ^ b) == b + log2_up aa, b:tHa:1 < aHb:0 <= blog2_up (a * 2 ^ b) == b + log2_up aa, b:tHa:1 == aHb:0 <= blog2_up (a * 2 ^ b) == b + log2_up aa, b:tHa:1 < aHb:0 <= blog2_up (a * 2 ^ b) == b + log2_up aa, b:tHa:1 < aHb:0 <= b0 < b + log2_up aa, b:tHa:1 < aHb:0 <= b2 ^ P (b + log2_up a) < a * 2 ^ b <= 2 ^ (b + log2_up a)a, b:tHa:1 < aHb:0 <= b0 < b + log2_up anow apply log2_up_pos.a, b:tHa:1 < aHb:0 <= b0 < log2_up aa, b:tHa:1 < aHb:0 <= b2 ^ P (b + log2_up a) < a * 2 ^ b <= 2 ^ (b + log2_up a)a, b:tHa:1 < aHb:0 <= b2 ^ P (b + log2_up a) < a * 2 ^ ba, b:tHa:1 < aHb:0 <= ba * 2 ^ b <= 2 ^ (b + log2_up a)a, b:tHa:1 < aHb:0 <= b2 ^ P (b + log2_up a) < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (b + log2_up a) < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (b + S (P (log2_up a))) < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ (b + P (log2_up a)) < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (log2_up a) * 2 ^ b < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a0 <= P (log2_up a)a, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (log2_up a) * 2 ^ b < a * 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a0 < 2 ^ ba, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (log2_up a) < aorder_pos.a, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a0 < 2 ^ bnow apply log2_up_spec.a, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a2 ^ P (log2_up a) < aa, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a0 <= P (log2_up a)now apply log2_up_pos.a, b:tHa:1 < aHb:0 <= bEQ:S (P (log2_up a)) == log2_up a0 < log2_up aa, b:tHa:1 < aHb:0 <= ba * 2 ^ b <= 2 ^ (b + log2_up a)a, b:tHa:1 < aHb:0 <= b2 ^ b * a <= 2 ^ b * 2 ^ log2_up aa, b:tHa:1 < aHb:0 <= b0 <= log2_up aa, b:tHa:1 < aHb:0 <= b2 ^ b * a <= 2 ^ b * 2 ^ log2_up aa, b:tHa:1 < aHb:0 <= b0 <= 2 ^ ba, b:tHa:1 < aHb:0 <= ba <= 2 ^ log2_up aorder_pos.a, b:tHa:1 < aHb:0 <= b0 <= 2 ^ bnow apply log2_up_spec.a, b:tHa:1 < aHb:0 <= ba <= 2 ^ log2_up aapply log2_up_nonneg.a, b:tHa:1 < aHb:0 <= b0 <= log2_up anow rewrite <- Ha, mul_1_l, log2_up_1, add_0_r, log2_up_pow2. Qed.a, b:tHa:1 == aHb:0 <= blog2_up (a * 2 ^ b) == b + log2_up aforall a : t, 0 < a -> log2_up (2 * a) == S (log2_up a)forall a : t, 0 < a -> log2_up (2 * a) == S (log2_up a)a:tHa:0 < alog2_up (2 * a) == S (log2_up a)now nzsimpl'. Qed.a:tHa:0 < alog2_up (a * 2 ^ 1) == 1 + log2_up a -> log2_up (2 * a) == S (log2_up a)
Two numbers with same log2_up cannot be far away.
forall a b : t, 0 < a -> 0 < b -> log2_up a == log2_up b -> a < 2 * bforall a b : t, 0 < a -> 0 < b -> log2_up a == log2_up b -> a < 2 * ba, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up ba < 2 * ba, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up blog2_up a < log2_up (2 * b)apply lt_succ_diag_r. Qed.a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up blog2_up b < S (log2_up b)
log2_up and successor :
- the log2_up function climbs by at most 1 at a time
- otherwise it stays at the same value
- the +1 steps occur after powers of two
forall a : t, log2_up (S a) <= S (log2_up a)forall a : t, log2_up (S a) <= S (log2_up a)a:tlog2_up (S a) <= S (log2_up a)a:tLT:1 < alog2_up (S a) <= S (log2_up a)a:tEQ:1 == alog2_up (S a) <= S (log2_up a)a:tLT:a < 1log2_up (S a) <= S (log2_up a)a:tLT:1 < alog2_up (S a) <= S (log2_up a)a:tLT:1 < aS (log2 (P (S a))) <= S (S (log2 (P a)))a:tLT:1 < a1 < S aa:tLT:1 < aS (log2 (P (S a))) <= S (S (log2 (P a)))a:tLT:1 < alog2 a <= S (log2 (P a))apply log2_succ_le.a:tLT:1 < alog2 (S (P a)) <= S (log2 (P a))apply lt_succ_r; order.a:tLT:1 < a1 < S aa:tEQ:1 == alog2_up (S a) <= S (log2_up a)now nzsimpl'.a:tEQ:1 == a1 <= S 0a:tLT:a < 1log2_up (S a) <= S (log2_up a)a:tLT:a < 10 <= S 0a:tLT:a < 1a <= 1a:tLT:a < 1S a <= 1order_pos.a:tLT:a < 10 <= S 0order'.a:tLT:a < 1a <= 1now rewrite le_succ_l. Qed.a:tLT:a < 1S a <= 1forall a : t, log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aforall a : t, log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aa:tlog2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aa:tH:log2_up (S a) <= log2_up alog2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aa:tH:log2_up a < log2_up (S a)log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aa:tH:log2_up (S a) <= log2_up alog2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up ageneralize (log2_up_le_mono _ _ (le_succ_diag_r a)); order.a:tH:log2_up (S a) <= log2_up alog2_up (S a) == log2_up aa:tH:log2_up a < log2_up (S a)log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up aa:tH:log2_up a < log2_up (S a)log2_up (S a) == S (log2_up a)generalize (log2_up_succ_le a); order. Qed.a:tH:S (log2_up a) <= log2_up (S a)log2_up (S a) == S (log2_up a)forall a : t, log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ bforall a : t, log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)exists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)Ha:a <= 0exists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)Ha:0 < aexists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)Ha:a <= 0exists b : t, a == 2 ^ ba:tH:0 == S 0Ha:a <= 0exists b : t, a == 2 ^ ba:tH:0 == S (log2_up a)Ha:a <= 0a <= 1a:tH:log2_up (S a) == S (log2_up a)Ha:a <= 0S a <= 1generalize (lt_succ_diag_r 0); order.a:tH:0 == S 0Ha:a <= 0exists b : t, a == 2 ^ border'.a:tH:0 == S (log2_up a)Ha:a <= 0a <= 1a:tH:log2_up (S a) == S (log2_up a)Ha:a <= 0S a <= 1order'.a:tH:log2_up (S a) == S (log2_up a)Ha:a <= 0a < 1a:tH:log2_up (S a) == S (log2_up a)Ha:0 < aexists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)Ha:0 < aHa':1 < S aexists b : t, a == 2 ^ ba:tH:log2_up (S a) == S (log2_up a)Ha:0 < aHa':1 < S aa == 2 ^ log2_up aa:tH:log2_up (S a) == S (log2_up a)Ha:0 < aHa':1 < S a2 ^ P (log2_up (S a)) < S a -> a <= 2 ^ log2_up a -> a == 2 ^ log2_up aorder. Qed.a:tH:log2_up (S a) == S (log2_up a)Ha:0 < aHa':1 < S a2 ^ log2_up a <= a -> a <= 2 ^ log2_up a -> a == 2 ^ log2_up aforall a : t, 0 < a -> log2_up (S a) == S (log2_up a) <-> (exists b : t, a == 2 ^ b)forall a : t, 0 < a -> log2_up (S a) == S (log2_up a) <-> (exists b : t, a == 2 ^ b)a:tHa:0 < alog2_up (S a) == S (log2_up a) <-> (exists b : t, a == 2 ^ b)a:tHa:0 < alog2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ ba:tHa:0 < a(exists b : t, a == 2 ^ b) -> log2_up (S a) == S (log2_up a)apply log2_up_eq_succ_is_pow2.a:tHa:0 < alog2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ ba:tHa:0 < a(exists b : t, a == 2 ^ b) -> log2_up (S a) == S (log2_up a)a:tHa:0 < ab:tHb:a == 2 ^ blog2_up (S a) == S (log2_up a)a:tHa:0 < ab:tHb:a == 2 ^ bHb':b < 0log2_up (S a) == S (log2_up a)a:tHa:0 < ab:tHb:a == 2 ^ bHb':0 <= blog2_up (S a) == S (log2_up a)rewrite pow_neg_r in Hb; order.a:tHa:0 < ab:tHb:a == 2 ^ bHb':b < 0log2_up (S a) == S (log2_up a)a:tHa:0 < ab:tHb:a == 2 ^ bHb':0 <= blog2_up (S a) == S (log2_up a)now rewrite log2_up_succ_pow2. Qed.a:tHa:0 < ab:tHb:a == 2 ^ bHb':0 <= blog2_up (S (2 ^ b)) == S bforall a : t, 0 < a -> log2_up (2 * a + 1) == 2 + log2 aforall a : t, 0 < a -> log2_up (2 * a + 1) == 2 + log2 aa:tHa:0 < alog2_up (2 * a + 1) == 2 + log2 aa:tHa:0 < aS (log2 (P (2 * a + 1))) == 2 + log2 aa:tHa:0 < a1 < 2 * a + 1rewrite add_1_r, pred_succ, log2_double; now nzsimpl'.a:tHa:0 < aS (log2 (P (2 * a + 1))) == 2 + log2 aa:tHa:0 < a1 < 2 * a + 1a:tHa:0 < a1 <= 0 + 1a:tHa:0 < a0 + 1 < 2 * a + 1now nzsimpl'.a:tHa:0 < a1 <= 0 + 1a:tHa:0 < a0 + 1 < 2 * a + 1order_pos. Qed.a:tHa:0 < a0 < 2 * a
log2_up and addition
forall a b : t, a ~= 1 -> b ~= 1 -> log2_up (a + b) <= log2_up a + log2_up bforall a b : t, a ~= 1 -> b ~= 1 -> log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < alog2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2_up (a + b) <= 0 + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1log2_up (a + b) <= log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a < 1a + b <= ba, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0a + b <= bnow apply add_le_mono.a, b:tHa:a ~= 1Hb:b ~= 1Ha':a <= 0a + b <= 0 + ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < alog2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':1 < blog2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2_up (a + b) <= log2_up a + log2_up ba, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2_up (a + b) <= log2_up a + 0a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1log2_up (a + b) <= log2_up aa, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b < 1a + b <= aa, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0a + b <= anow apply add_le_mono.a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':b <= 0a + b <= a + 0a, b:tHa:a ~= 1Hb:b ~= 1Ha':1 < aHb':1 < blog2_up (a + b) <= log2_up a + log2_up ba, b:tHa':1 < aHb':1 < blog2_up (a + b) <= log2_up a + log2_up ba, b:tHa':1 < aHb':1 < blog2_up (a + b) <= log2_up (a * b)a, b:tHa':1 < aHb':1 < blog2_up (a * b) <= log2_up a + log2_up bnow apply log2_up_le_mono, add_le_mul.a, b:tHa':1 < aHb':1 < blog2_up (a + b) <= log2_up (a * b)apply log2_up_mul_above; order'. Qed.a, b:tHa':1 < aHb':1 < blog2_up (a * b) <= log2_up a + log2_up b
The sum of two log2_up is less than twice the log2_up of the sum.
The large inequality is obvious thanks to monotonicity.
The strict one requires some more work. This is almost
a convexity inequality for points 2a, 2b and their middle a+b :
ideally, we would have 2*log(a+b) ≥ log(2a)+log(2b) = 2+log a+log b.
Here, we cannot do better: consider for instance a=3 b=5, then 2+3<2*3
forall a b : t, 0 < a -> 0 < b -> log2_up a + log2_up b < 2 * log2_up (a + b)forall a b : t, 0 < a -> 0 < b -> log2_up a + log2_up b < 2 * log2_up (a + b)a, b:tHa:0 < aHb:0 < blog2_up a + log2_up b < 2 * log2_up (a + b)a, b:tHa:0 < aHb:0 < blog2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < blog2_up a <= log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < blog2_up a <= log2_up (a + b)a, b:tHa:0 < aHb:0 < ba <= a + bapply add_le_mono; order.a, b:tHa:0 < aHb:0 < ba + 0 <= a + ba, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)log2_up b <= log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)log2_up b <= log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)b <= a + bapply add_le_mono; order.a, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)0 + b <= a + ba, b:tHa:0 < aHb:0 < bH:log2_up a <= log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up ba, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up (a + b) + log2_up b <= log2_up (a + b) + log2_up (a + b)now apply add_lt_mono_r.a, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up bnow apply add_le_mono_l.a, b:tHa:0 < aHb:0 < bH:log2_up a < log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up (a + b) + log2_up b <= log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up a + log2_up b < log2_up a + log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b <= log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b < log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b == log2_up (a + b)log2_up b < log2_up (a + b)trivial.a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b < log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up a == log2_up (a + b)H':log2_up b == log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:log2_up (a + b) == log2_up aH':log2_up b == log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':log2_up b == log2_up (a + b)log2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':log2_up (a + b) == log2_up blog2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < bH:a + b < 2 * aH':a + b < 2 * blog2_up b < log2_up (a + b)a, b:tHa:0 < aHb:0 < ba + b < 2 * a -> a + b < 2 * b -> log2_up b < log2_up (a + b)rewrite <- add_lt_mono_l, <- add_lt_mono_r; order. Qed. End NZLog2UpProp.a, b:tHa:0 < aHb:0 < ba + b < a + a -> a + b < b + b -> log2_up b < log2_up (a + b)