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 a

forall a : t, 0 <= log2 a
a:t

0 <= log2 a
a:t
Ha:a <= 0

0 <= log2 a
a:t
Ha:0 < a
0 <= log2 a
a:t
Ha:a <= 0

0 <= log2 a
now rewrite log2_nonpos.
a:t
Ha:0 < a

0 <= log2 a
a:t
Ha:0 < a
LT:a < 2 ^ S (log2 a)

0 <= log2 a
a:t
Ha:0 < a
LT:a < 2 ^ S (log2 a)

1 < 2
a:t
Ha:0 < a
LT:a < 2 ^ S (log2 a)
1 < 2 ^ S (log2 a)
a:t
Ha:0 < a
LT:a < 2 ^ S (log2 a)

1 < 2
order'.
a:t
Ha:0 < a
LT:a < 2 ^ S (log2 a)

1 < 2 ^ S (log2 a)
a:t
Ha:1 <= a
LT:a < 2 ^ S (log2 a)

1 < 2 ^ S (log2 a)
order. Qed.
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 == b

forall a b : t, 0 <= b -> 2 ^ b <= a < 2 ^ S b -> log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b

log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b

0 < a
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b

0 < a
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b

0 < 2 ^ b
apply pow_pos_nonneg; order'.
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a

log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a

log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)

log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)

log2 a <= b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b
log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)

log2 a <= b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)

0 <= S b
now apply le_le_succ_r.
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b

log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b

b <= log2 a
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b
H0:b <= log2 a
log2 a == b
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b

b <= log2 a
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b

0 <= S (log2 a)
now apply le_le_succ_r.
a, b:t
Hb:0 <= b
LEb:2 ^ b <= a
LTb:a < 2 ^ S b
Ha:0 < a
Hc:0 <= log2 a
LEc:2 ^ log2 a <= a
LTc:a < 2 ^ S (log2 a)
H:log2 a <= b
H0:b <= log2 a

log2 a == b
order. Qed.
Hence log2 is a morphism.

Proper (eq ==> eq) log2

Proper (eq ==> eq) log2
x, x':t
Hx:x == x'

log2 x == log2 x'
x, x':t
Hx:x == x'
H:x <= 0

log2 x == log2 x'
x, x':t
Hx:x == x'
H:0 < x
log2 x == log2 x'
x, x':t
Hx:x == x'
H:x <= 0

log2 x == log2 x'
x, x':t
Hx:x == x'
H:x <= 0

0 == 0
x, x':t
Hx:x == x'
H:x <= 0
x' <= 0
x, x':t
Hx:x == x'
H:x <= 0

0 == 0
reflexivity.
x, x':t
Hx:x == x'
H:x <= 0

x' <= 0
now rewrite <- Hx.
x, x':t
Hx:x == x'
H:0 < x

log2 x == log2 x'
x, x':t
Hx:x == x'
H:0 < x

0 <= log2 x'
x, x':t
Hx:x == x'
H:0 < x
2 ^ log2 x' <= x < 2 ^ S (log2 x')
x, x':t
Hx:x == x'
H:0 < x

0 <= log2 x'
apply log2_nonneg.
x, x':t
Hx:x == x'
H:0 < x

2 ^ log2 x' <= x < 2 ^ S (log2 x')
x, x':t
Hx:x == x'
H:0 < x'

2 ^ log2 x' <= x' < 2 ^ S (log2 x')
now apply log2_spec. Qed.
An alternate specification

forall a : t, 0 < a -> exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 a

forall a : t, 0 < a -> exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 a
a:t
Ha:0 < a

exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)

exists r : t, a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

exists r0 : t, a == 2 ^ log2 a + r0 /\ 0 <= r0 < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a == 2 ^ log2 a + r /\ 0 <= r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a == 2 ^ log2 a + r
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r
0 <= r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a == 2 ^ log2 a + r
now rewrite add_comm.
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

0 <= r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

0 <= r
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r
r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

0 <= r
trivial.
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

r < 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

r + 2 ^ log2 a < 2 ^ log2 a + 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a < 2 ^ log2 a + 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a < 2 ^ S (log2 a) -> a < 2 ^ log2 a + 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a < 2 * 2 ^ log2 a -> a < 2 ^ log2 a + 2 ^ log2 a
a:t
Ha:0 < a
LE:2 ^ log2 a <= a
LT:a < 2 ^ S (log2 a)
r:t
Hr:a == r + 2 ^ log2 a
Hr':0 <= r

a < S 1 * 2 ^ log2 a -> a < 2 ^ log2 a + 2 ^ log2 a
now nzsimpl. Qed.

forall a b c : t, 0 <= b -> 0 <= c < 2 ^ b -> a == 2 ^ b + c -> log2 a == b

forall a b c : t, 0 <= b -> 0 <= c < 2 ^ b -> a == 2 ^ b + c -> log2 a == b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

log2 a == b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

0 <= b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c
2 ^ b <= a < 2 ^ S b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

0 <= b
trivial.
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b <= a < 2 ^ S b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b <= 2 ^ b + c < 2 ^ S b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b <= 2 ^ b + c
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c
2 ^ b + c < 2 ^ S b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b <= 2 ^ b + c
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b + 0 <= 2 ^ b + c
now apply add_le_mono_l.
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b + c < 2 ^ S b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b + c < 2 * 2 ^ b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b + c < S 1 * 2 ^ b
a, b, c:t
Hb:0 <= b
Hc:0 <= c
H:c < 2 ^ b
EQ:a == 2 ^ b + c

2 ^ b + c < 2 ^ b + 2 ^ b
now apply add_lt_mono_l. Qed.
log2 is exact on powers of 2

forall a : t, 0 <= a -> log2 (2 ^ a) == a

forall a : t, 0 <= a -> log2 (2 ^ a) == a
a:t
Ha:0 <= a

log2 (2 ^ a) == a
a:t
Ha:0 <= a

0 <= 0 < 2 ^ a
a:t
Ha:0 <= a
2 ^ a == 2 ^ a + 0
a:t
Ha:0 <= a

0 <= 0 < 2 ^ a
split; order_pos.
a:t
Ha:0 <= a

2 ^ a == 2 ^ a + 0
now nzsimpl. Qed.
log2 and predecessors of powers of 2

forall a : t, 0 < a -> log2 (P (2 ^ a)) == P a

forall a : t, 0 < a -> log2 (P (2 ^ a)) == P a
a:t
Ha:0 < a

log2 (P (2 ^ a)) == P a
a:t
Ha:0 < a
Ha':S (P a) == a

log2 (P (2 ^ a)) == P a
a:t
Ha:0 < a
Ha':S (P a) == a

0 <= P a
a:t
Ha:0 < a
Ha':S (P a) == a
2 ^ P a <= P (2 ^ a) < 2 ^ S (P a)
a:t
Ha:0 < a
Ha':S (P a) == a

0 <= P a
apply lt_succ_r; order.
a:t
Ha:0 < a
Ha':S (P a) == a

2 ^ P a <= P (2 ^ a) < 2 ^ S (P a)
a:t
Ha:0 < a
Ha':S (P a) == a

2 ^ P a < S (P (2 ^ a)) <= 2 ^ a
a:t
Ha:0 < a
Ha':S (P a) == a

2 ^ P a < 2 ^ a <= 2 ^ a
a:t
Ha:0 < a
Ha':S (P a) == a
0 < 2 ^ a
a:t
Ha:0 < a
Ha':S (P a) == a

2 ^ P a < 2 ^ a <= 2 ^ a
a:t
Ha:0 < a
Ha':S (P a) == a

2 ^ P a < 2 ^ a
a:t
Ha:0 < a
Ha':S (P a) == a

P a < a
a:t
Ha:0 < a
Ha':S (P a) == a

a < S a
apply lt_succ_diag_r.
a:t
Ha:0 < a
Ha':S (P a) == a

0 < 2 ^ a
apply pow_pos_nonneg; order'. Qed.
log2 and basic constants

log2 1 == 0

log2 1 == 0

log2 (2 ^ 0) == 0
now apply log2_pow2. Qed.

log2 2 == 1

log2 2 == 1

log2 (2 ^ 1) == 1
apply log2_pow2; order'. Qed.
log2 n is strictly positive for 1<n

forall a : t, 1 < a -> 0 < log2 a

forall a : t, 1 < a -> 0 < log2 a
a:t
Ha:1 < a

0 < log2 a
a:t
Ha:1 < a
Ha':0 < a

0 < log2 a
a:t
Ha:1 < a
Ha':0 < a
H:0 <= log2 a

0 < log2 a
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a

0 < log2 a
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a

2 ^ log2 a <= a < 2 ^ S (log2 a) -> 0 < log2 a
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a

2 ^ 0 <= a < 2 ^ S 0 -> 0 < 0
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a

1 <= a < 2 -> 0 < 0
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a
H':a < 2

0 < 0
a:t
Ha:1 < a
Ha':0 < a
H:0 == log2 a
H':a < S 1

0 < 0
apply lt_succ_r in H'; order. Qed.
Said otherwise, log2 is null only below 1

forall a : t, log2 a == 0 <-> a <= 1

forall a : t, log2 a == 0 <-> a <= 1
a:t

log2 a == 0 <-> a <= 1
a:t
H:log2 a == 0

a <= 1
a:t
H:a <= 1
log2 a == 0
a:t
H:log2 a == 0

a <= 1
a:t
H:log2 a == 0
Ha:1 < a

a <= 1
generalize (log2_pos a Ha); order.
a:t
H:a <= 1

log2 a == 0
a:t
H:a < 1

log2 a == 0
a:t
H:a == 1
log2 a == 0
a:t
H:a < 1

log2 a == 0
a:t
H:a < 1

a <= 0
a:t
H:a < 1

a < S 0
now rewrite <- one_succ.
a:t
H:a == 1

log2 a == 0
a:t
H:a == 1

log2 1 == 0
apply log2_1. Qed.
log2 is a monotone function (but not a strict one)

forall a b : t, a <= b -> log2 a <= log2 b

forall a b : t, a <= b -> log2 a <= log2 b
a, b:t
H:a <= b

log2 a <= log2 b
a, b:t
H:a <= b
Ha:a <= 0

log2 a <= log2 b
a, b:t
H:a <= b
Ha:0 < a
log2 a <= log2 b
a, b:t
H:a <= b
Ha:a <= 0

log2 a <= log2 b
rewrite log2_nonpos; order_pos.
a, b:t
H:a <= b
Ha:0 < a

log2 a <= log2 b
a, b:t
H:a <= b
Ha:0 < a
Hb:0 < b

log2 a <= log2 b
a, b:t
H:a <= b
Ha:0 < a
Hb:0 < b
LEa:2 ^ log2 a <= a

log2 a <= log2 b
a, b:t
H:a <= b
Ha:0 < a
Hb:0 < b
LEa:2 ^ log2 a <= a
LTb:b < 2 ^ S (log2 b)

log2 a <= log2 b
apply lt_succ_r, (pow_lt_mono_r_iff 2); order_pos. Qed.
No reverse result for <=, consider for instance log2 3 <= log2 2

forall a b : t, log2 a < log2 b -> a < b

forall a b : t, log2 a < log2 b -> a < b
a, b:t
H:log2 a < log2 b

a < b
a, b:t
H:log2 a < log2 b
Hb:b <= 0

a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
a < b
a, b:t
H:log2 a < log2 b
Hb:b <= 0

a < b
a, b:t
H:log2 a < 0
Hb:b <= 0

a < b
generalize (log2_nonneg a); order.
a, b:t
H:log2 a < log2 b
Hb:0 < b

a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:a <= 0

a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:0 < a
a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:a <= 0

a < b
order.
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:0 < a

a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:0 < a
LTa:a < 2 ^ S (log2 a)

a < b
a, b:t
H:log2 a < log2 b
Hb:0 < b
Ha:0 < a
LTa:a < 2 ^ S (log2 a)
LEb:2 ^ log2 b <= b

a < b
a, b:t
H:S (log2 a) <= log2 b
Hb:0 < b
Ha:0 < a
LTa:a < 2 ^ S (log2 a)
LEb:2 ^ log2 b <= b

a < b
apply (pow_le_mono_r_iff 2) in H; order_pos. Qed.
When left side is a power of 2, we have an equivalence for <=

forall a b : t, 0 < a -> 2 ^ b <= a <-> b <= log2 a

forall a b : t, 0 < a -> 2 ^ b <= a <-> b <= log2 a
a, b:t
Ha:0 < a

2 ^ b <= a <-> b <= log2 a
a, b:t
Ha:0 < a
H:2 ^ b <= a

b <= log2 a
a, b:t
Ha:0 < a
H:b <= log2 a
2 ^ b <= a
a, b:t
Ha:0 < a
H:2 ^ b <= a

b <= log2 a
a, b:t
Ha:0 < a
H:2 ^ b <= a
Hb:b < 0

b <= log2 a
a, b:t
Ha:0 < a
H:2 ^ b <= a
Hb:0 <= b
b <= log2 a
a, b:t
Ha:0 < a
H:2 ^ b <= a
Hb:b < 0

b <= log2 a
generalize (log2_nonneg a); order.
a, b:t
Ha:0 < a
H:2 ^ b <= a
Hb:0 <= b

b <= log2 a
a, b:t
Ha:0 < a
H:2 ^ b <= a
Hb:0 <= b

log2 (2 ^ b) <= log2 a
now apply log2_le_mono.
a, b:t
Ha:0 < a
H:b <= log2 a

2 ^ b <= a
a, b:t
Ha:0 < a
H:b <= log2 a

2 ^ b <= 2 ^ log2 a
a, b:t
Ha:0 < a
H:b <= log2 a
2 ^ log2 a <= a
a, b:t
Ha:0 < a
H:b <= log2 a

2 ^ b <= 2 ^ log2 a
apply pow_le_mono_r; order'.
a, b:t
Ha:0 < a
H:b <= log2 a

2 ^ log2 a <= a
now destruct (log2_spec a Ha). Qed.
When right side is a square, we have an equivalence for <

forall a b : t, 0 < a -> a < 2 ^ b <-> log2 a < b

forall a b : t, 0 < a -> a < 2 ^ b <-> log2 a < b
a, b:t
Ha:0 < a

a < 2 ^ b <-> log2 a < b
a, b:t
Ha:0 < a
H:a < 2 ^ b

log2 a < b
a, b:t
Ha:0 < a
H:log2 a < b
a < 2 ^ b
a, b:t
Ha:0 < a
H:a < 2 ^ b

log2 a < b
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:b < 0

log2 a < b
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:0 <= b
log2 a < b
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:b < 0

log2 a < b
rewrite pow_neg_r in H; order.
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:0 <= b

log2 a < b
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:0 <= b

2 ^ log2 a < 2 ^ b
a, b:t
Ha:0 < a
H:a < 2 ^ b
Hb:0 <= b

2 ^ log2 a <= a
now destruct (log2_spec a Ha).
a, b:t
Ha:0 < a
H:log2 a < b

a < 2 ^ b
a, b:t
Ha:0 < a
H:log2 a < b
Hb:b < 0

a < 2 ^ b
a, b:t
Ha:0 < a
H:log2 a < b
Hb:0 <= b
a < 2 ^ b
a, b:t
Ha:0 < a
H:log2 a < b
Hb:b < 0

a < 2 ^ b
generalize (log2_nonneg a); order.
a, b:t
Ha:0 < a
H:log2 a < b
Hb:0 <= b

a < 2 ^ b
a, b:t
Ha:0 < a
H:log2 a < b
Hb:0 <= b

log2 a < log2 (2 ^ b)
now rewrite log2_pow2. Qed.
Comparing log2 and identity

forall a : t, 0 < a -> log2 a < a

forall a : t, 0 < a -> log2 a < a
a:t
Ha:0 < a

log2 a < a
a:t
Ha:0 < a

2 ^ log2 a < 2 ^ a
a:t
Ha:0 < a

2 ^ log2 a <= a
a:t
Ha:0 < a
a < 2 ^ a
a:t
Ha:0 < a

2 ^ log2 a <= a
now destruct (log2_spec a Ha).
a:t
Ha:0 < a

a < 2 ^ a
apply pow_gt_lin_r; order'. Qed.

forall a : t, 0 <= a -> log2 a <= a

forall a : t, 0 <= a -> log2 a <= a
a:t
Ha:0 <= a

log2 a <= a
a:t
Ha:0 < a

log2 a <= a
a:t
Ha:0 == a
log2 a <= a
a:t
Ha:0 < a

log2 a <= a
now apply lt_le_incl, log2_lt_lin.
a:t
Ha:0 == a

log2 a <= a
rewrite <- Ha, log2_nonpos; order. Qed.
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:t
Ha:0 < a
Hb:0 < b

log2 a + log2 b <= log2 (a * b)
a, b:t
Ha:0 < a
Hb:0 < b

2 ^ (log2 a + log2 b) <= a * b
a, b:t
Ha:0 < a
Hb:0 < b

2 ^ log2 a * 2 ^ log2 b <= a * b
apply mul_le_mono_nonneg; try apply log2_spec; order_pos. Qed.

forall a b : t, 0 <= a -> 0 <= b -> log2 (a * b) <= log2 a + log2 b + 1

forall a b : t, 0 <= a -> 0 <= b -> log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 <= a
Hb:0 <= b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 <= b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 == a
Hb:0 <= b
log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 <= b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 < b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 == b
log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 < b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 < b

log2 (a * b) < S (log2 a + log2 b + 1)
a, b:t
Ha:0 < a
Hb:0 < b

log2 (a * b) < S (log2 a) + S (log2 b)
a, b:t
Ha:0 < a
Hb:0 < b

a * b < 2 ^ (S (log2 a) + S (log2 b))
a, b:t
Ha:0 < a
Hb:0 < b

a * b < 2 ^ S (log2 a) * 2 ^ S (log2 b)
apply mul_lt_mono_nonneg; try order; now apply log2_spec.
a, b:t
Ha:0 < a
Hb:0 == b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 < a
Hb:0 == b

log2 (a * 0) <= log2 a + log2 0 + 1
a, b:t
Ha:0 < a
Hb:0 == b

log2 0 <= S (log2 a + log2 0)
rewrite log2_nonpos; order_pos.
a, b:t
Ha:0 == a
Hb:0 <= b

log2 (a * b) <= log2 a + log2 b + 1
a, b:t
Ha:0 == a
Hb:0 <= b

log2 (0 * b) <= log2 0 + log2 b + 1
a, b:t
Ha:0 == a
Hb:0 <= b

log2 0 <= S (log2 0 + log2 b)
rewrite log2_nonpos; order_pos. Qed.
And we can't find better approximations in general.
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 a

forall a b : t, 0 < a -> 0 <= b -> log2 (a * 2 ^ b) == b + log2 a
a, b:t
Ha:0 < a
Hb:0 <= b

log2 (a * 2 ^ b) == b + log2 a
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ (b + log2 a) <= a * 2 ^ b < 2 ^ S (b + log2 a)
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ (b + log2 a) <= a * 2 ^ b
a, b:t
Ha:0 < a
Hb:0 <= b
a * 2 ^ b < 2 ^ S (b + log2 a)
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ (b + log2 a) <= a * 2 ^ b
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ log2 a * 2 ^ b <= a * 2 ^ b
a, b:t
Ha:0 < a
Hb:0 <= b

0 <= 2 ^ b
a, b:t
Ha:0 < a
Hb:0 <= b
2 ^ log2 a <= a
a, b:t
Ha:0 < a
Hb:0 <= b

0 <= 2 ^ b
order_pos.
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ log2 a <= a
now apply log2_spec.
a, b:t
Ha:0 < a
Hb:0 <= b

a * 2 ^ b < 2 ^ S (b + log2 a)
a, b:t
Ha:0 < a
Hb:0 <= b

2 ^ b * a < 2 ^ b * 2 ^ S (log2 a)
a, b:t
Ha:0 < a
Hb:0 <= b

0 < 2 ^ b
a, b:t
Ha:0 < a
Hb:0 <= b
a < 2 ^ S (log2 a)
a, b:t
Ha:0 < a
Hb:0 <= b

0 < 2 ^ b
order_pos.
a, b:t
Ha:0 < a
Hb:0 <= b

a < 2 ^ S (log2 a)
now apply log2_spec. Qed.

forall a : t, 0 < a -> log2 (2 * a) == S (log2 a)

forall a : t, 0 < a -> log2 (2 * a) == S (log2 a)
a:t
Ha:0 < a

log2 (2 * a) == S (log2 a)
a:t
Ha:0 < a

log2 (a * 2 ^ 1) == 1 + log2 a -> log2 (2 * a) == S (log2 a)
now nzsimpl'. Qed.
Two numbers with same log2 cannot be far away.

forall a b : t, 0 < a -> 0 < b -> log2 a == log2 b -> a < 2 * b

forall a b : t, 0 < a -> 0 < b -> log2 a == log2 b -> a < 2 * b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 b

a < 2 * b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 b

log2 a < log2 (2 * b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 b

log2 b < S (log2 b)
apply lt_succ_diag_r. Qed.
Log2 and successor :

forall a : t, log2 (S a) <= S (log2 a)

forall a : t, log2 (S a) <= S (log2 a)
a:t

log2 (S a) <= S (log2 a)
a:t
LT:0 < a

log2 (S a) <= S (log2 a)
a:t
EQ:0 == a
log2 (S a) <= S (log2 a)
a:t
LT:a < 0
log2 (S a) <= S (log2 a)
a:t
LT:0 < a

log2 (S a) <= S (log2 a)
a:t
LT:0 < a

2 ^ log2 (S a) <= 2 ^ S (log2 a)
a:t
LT:0 < a

2 ^ log2 (S a) <= S a
a:t
LT:0 < a
S a <= 2 ^ S (log2 a)
a:t
LT:0 < a

2 ^ log2 (S a) <= S a
a:t
LT:0 < a

0 < S a
apply lt_succ_r; order.
a:t
LT:0 < a

S a <= 2 ^ S (log2 a)
now apply le_succ_l, log2_spec.
a:t
EQ:0 == a

log2 (S a) <= S (log2 a)
rewrite <- EQ, <- one_succ, log2_1; order_pos.
a:t
LT:a < 0

log2 (S a) <= S (log2 a)
a:t
LT:a < 0

0 <= S 0
a:t
LT:a < 0
a <= 0
a:t
LT:a < 0
S a <= 0
a:t
LT:a < 0

0 <= S 0
order_pos.
a:t
LT:a < 0

a <= 0
order'.
a:t
LT:a < 0

S a <= 0
now rewrite le_succ_l. Qed.

forall a : t, log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a

forall a : t, log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t

log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t
H:log2 (S a) <= log2 a

log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t
H:log2 a < log2 (S a)
log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t
H:log2 (S a) <= log2 a

log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t
H:log2 (S a) <= log2 a

log2 (S a) == log2 a
generalize (log2_le_mono _ _ (le_succ_diag_r a)); order.
a:t
H:log2 a < log2 (S a)

log2 (S a) == S (log2 a) \/ log2 (S a) == log2 a
a:t
H:log2 a < log2 (S a)

log2 (S a) == S (log2 a)
a:t
H:S (log2 a) <= log2 (S a)

log2 (S a) == S (log2 a)
generalize (log2_succ_le a); order. Qed.

forall a : t, log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ b

forall a : t, log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)

exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)
Ha:a <= 0

exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a
exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)
Ha:a <= 0

exists b : t, S a == 2 ^ b
a:t
H:0 == S 0
Ha:a <= 0

exists b : t, S a == 2 ^ b
a:t
H:0 == S (log2 a)
Ha:a <= 0
a <= 1
a:t
H:log2 (S a) == S (log2 a)
Ha:a <= 0
S a <= 1
a:t
H:0 == S 0
Ha:a <= 0

exists b : t, S a == 2 ^ b
generalize (lt_succ_diag_r 0); order.
a:t
H:0 == S (log2 a)
Ha:a <= 0

a <= 1
order'.
a:t
H:log2 (S a) == S (log2 a)
Ha:a <= 0

S a <= 1
a:t
H:log2 (S a) == S (log2 a)
Ha:a <= 0

a < 1
order'.
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a

exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a
Ha':0 < S a

exists b : t, S a == 2 ^ b
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a
Ha':0 < S a

S a == 2 ^ log2 (S a)
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a
Ha':0 < S a

2 ^ log2 (S a) <= S a -> a < 2 ^ S (log2 a) -> S a == 2 ^ log2 (S a)
a:t
H:log2 (S a) == S (log2 a)
Ha:0 < a
Ha':0 < S a

2 ^ log2 (S a) <= S a -> S a <= 2 ^ log2 (S a) -> S a == 2 ^ log2 (S a)
order. Qed.

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:t
Ha:0 < a

log2 (S a) == S (log2 a) <-> (exists b : t, S a == 2 ^ b)
a:t
Ha:0 < a

log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ b
a:t
Ha:0 < a
(exists b : t, S a == 2 ^ b) -> log2 (S a) == S (log2 a)
a:t
Ha:0 < a

log2 (S a) == S (log2 a) -> exists b : t, S a == 2 ^ b
apply log2_eq_succ_is_pow2.
a:t
Ha:0 < a

(exists b : t, S a == 2 ^ b) -> log2 (S a) == S (log2 a)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b

log2 (S a) == S (log2 a)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b

0 < b
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b
log2 (S a) == S (log2 a)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b

0 < b
apply (pow_gt_1 2); try order'; now rewrite <- Hb, one_succ, <- succ_lt_mono.
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

log2 (S a) == S (log2 a)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

b == S (log2 a)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

b == S (log2 (P (2 ^ b)))
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b
a == P (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

b == S (log2 (P (2 ^ b)))
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

b == S (P b)
symmetry; now apply lt_succ_pred with 0.
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

a == P (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

S a == S (P (2 ^ b))
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

2 ^ b == S (P (2 ^ b))
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

S (P (2 ^ b)) == 2 ^ b
a:t
Ha:0 < a
b:t
Hb:S a == 2 ^ b
Hb':0 < b

0 < 2 ^ b
rewrite <- Hb, lt_succ_r; order. Qed.

forall a : t, 0 < a -> log2 (2 * a + 1) == S (log2 a)

forall a : t, 0 < a -> log2 (2 * a + 1) == S (log2 a)
a:t
Ha:0 < a

log2 (2 * a + 1) == S (log2 a)
a:t
Ha:0 < a

log2 (S (2 * a)) == S (log2 a)
a:t
Ha:0 < a
H:log2 (S (2 * a)) == S (log2 (2 * a))

False
a:t
Ha:0 < a
H:exists b : t, S (2 * a) == 2 ^ b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
LT:b < 0

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
EQ:b == 0
False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
LT:0 < b
False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
LT:b < 0

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 0
LT:b < 0

False
a:t
Ha:S 0 < S (2 * a)
b:t
H:S (2 * a) == 0
LT:b < 0

False
a:t
Ha:1 < S (2 * a)
b:t
H:S (2 * a) == 0
LT:b < 0

False
order'.
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
EQ:b == 0

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 1
EQ:b == 0

False
a:t
Ha:S 0 < S (2 * a)
b:t
H:S (2 * a) == 1
EQ:b == 0

False
a:t
Ha:1 < S (2 * a)
b:t
H:S (2 * a) == 1
EQ:b == 0

False
order'.
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
LT:0 < b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 ^ b
LT:0 < b
EQ:S (P b) == b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LT':a < 2 ^ P b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LE':2 ^ P b <= a
False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LT':a < 2 ^ P b

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LT':a < 2 ^ P b

1 + 2 * a < 2 * 2 ^ P b -> False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LT':a < 2 ^ P b

S (2 * a) < 2 * 2 ^ P b -> False
order.
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LE':2 ^ P b <= a

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LE':2 * 2 ^ P b <= 2 * a

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LE':S (2 * a) <= 2 * a

False
a:t
Ha:0 < a
b:t
H:S (2 * a) == 2 * 2 ^ P b
LT:0 < b
EQ:S (P b) == b
LE':2 * a < 2 * a

False
order. Qed.
Log2 and addition

forall a b : t, a ~= 1 -> b ~= 1 -> log2 (a + b) <= log2 a + log2 b

forall a b : t, a ~= 1 -> b ~= 1 -> log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

log2 (a + b) <= 0 + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

log2 (a + b) <= log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

a + b <= b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

a + b <= 0 + b
now apply add_le_mono.
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':1 < b
log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

log2 (a + b) <= log2 a + 0
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

log2 (a + b) <= log2 a
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

a + b <= a
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

a + b <= a + 0
now apply add_le_mono.
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':1 < b

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

log2 (a + b) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

log2 (a + b) < S (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a + b < 2 ^ S (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a + b < 2 * 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a + b < S (S 0) * 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a + b < 2 ^ (log2 a + log2 b) + 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a < 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b
b < 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a < 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a < 2 ^ S (log2 a)
a, b:t
Ha':1 < a
Hb':1 < b
2 ^ S (log2 a) <= 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

a < 2 ^ S (log2 a)
apply log2_spec; order'.
a, b:t
Ha':1 < a
Hb':1 < b

2 ^ S (log2 a) <= 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

0 < 2
a, b:t
Ha':1 < a
Hb':1 < b
S (log2 a) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

0 < 2
order'.
a, b:t
Ha':1 < a
Hb':1 < b

S (log2 a) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

log2 a + 1 <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

1 <= log2 b
rewrite one_succ; now apply le_succ_l, log2_pos.
a, b:t
Ha':1 < a
Hb':1 < b

b < 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

b < 2 ^ S (log2 b)
a, b:t
Ha':1 < a
Hb':1 < b
2 ^ S (log2 b) <= 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

b < 2 ^ S (log2 b)
apply log2_spec; order'.
a, b:t
Ha':1 < a
Hb':1 < b

2 ^ S (log2 b) <= 2 ^ (log2 a + log2 b)
a, b:t
Ha':1 < a
Hb':1 < b

0 < 2
a, b:t
Ha':1 < a
Hb':1 < b
S (log2 b) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

0 < 2
order'.
a, b:t
Ha':1 < a
Hb':1 < b

S (log2 b) <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

1 + log2 b <= log2 a + log2 b
a, b:t
Ha':1 < a
Hb':1 < b

1 <= log2 a
rewrite one_succ; now apply le_succ_l, log2_pos. Qed.
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:t
Ha:0 < a
Hb:0 < b

log2 a + log2 b < 2 * log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2 a <= log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)
log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2 a <= log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a <= a + b
a, b:t
Ha:0 < a
Hb:0 < b

a + 0 <= a + b
apply add_le_mono; order.
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)

log2 b <= log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)
H':log2 b <= log2 (a + b)
log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)

log2 b <= log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)

b <= a + b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)

0 + b <= a + b
apply add_le_mono; order.
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a <= log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a < log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 (a + b)
H':log2 b <= log2 (a + b)
log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a < log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a < log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a < log2 (a + b)
H':log2 b <= log2 (a + b)
log2 (a + b) + log2 b <= log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a < log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 b
now apply add_lt_mono_r.
a, b:t
Ha:0 < a
Hb:0 < b
H: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_le_mono_l.
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 (a + b) + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 (a + b)
H':log2 b <= log2 (a + b)

log2 a + log2 b < log2 a + log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 (a + b)
H':log2 b <= log2 (a + b)

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 a == log2 (a + b)
H':log2 b == log2 (a + b)

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2 (a + b) == log2 a
H':log2 b == log2 (a + b)

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':log2 b == log2 (a + b)

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':log2 (a + b) == log2 b

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':a + b < 2 * b

log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a + b < 2 * a -> a + b < 2 * b -> log2 b < log2 (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a + b < a + a -> a + b < b + 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).

log2_up : a binary logarithm that rounds up instead of down

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 == 0

forall a : t, a <= 1 -> log2_up a == 0
a:t
Ha:a <= 1

log2_up a == 0
a:t
Ha:a <= 1

match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end == 0
case compare_spec; try order. Qed.

forall a : t, 1 < a -> log2_up a == S (log2 (P a))

forall a : t, 1 < a -> log2_up a == S (log2 (P a))
a:t
Ha:1 < a

log2_up a == S (log2 (P a))
a:t
Ha:1 < a

match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end == S (log2 (P a))
case compare_spec; try order. Qed.

forall a : t, 1 < a -> 2 ^ P (log2_up a) < a <= 2 ^ log2_up a

forall a : t, 1 < a -> 2 ^ P (log2_up a) < a <= 2 ^ log2_up a
a:t
Ha:1 < a

2 ^ P (log2_up a) < a <= 2 ^ log2_up a
a:t
Ha:1 < a

2 ^ P (S (log2 (P a))) < a <= 2 ^ S (log2 (P a))
a:t
Ha:1 < a

2 ^ log2 (P a) < a <= 2 ^ S (log2 (P a))
a:t
Ha:1 < a

2 ^ log2 (P a) < S (P a) <= 2 ^ S (log2 (P a))
a:t
Ha:1 < a

2 ^ log2 (P a) <= P a < 2 ^ S (log2 (P a))
a:t
Ha:1 < a

0 < P a
a:t
Ha:1 < a

S 0 < S (P a)
now rewrite (lt_succ_pred 1 a Ha), <- one_succ. Qed.

forall a : t, a <= 0 -> log2_up a == 0

forall a : t, a <= 0 -> log2_up a == 0
a:t
H:a <= 0

log2_up a == 0
a:t
H:a <= 0

a <= 1
order'. Qed.

Proper (eq ==> eq) log2_up

Proper (eq ==> eq) log2_up

Proper (eq ==> eq ==> Logic.eq) compare
H:Proper (eq ==> eq ==> Logic.eq) compare
Proper (eq ==> eq) log2_up

Proper (eq ==> eq ==> Logic.eq) compare
repeat red; intros; do 2 case compare_spec; trivial; order.
H:Proper (eq ==> eq ==> Logic.eq) compare

Proper (eq ==> eq) log2_up
H:Proper (eq ==> eq ==> Logic.eq) compare
a, a':t
Ha:a == a'

log2_up a == log2_up a'
H:Proper (eq ==> eq ==> Logic.eq) compare
a, a':t
Ha: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
H:Proper (eq ==> eq ==> Logic.eq) compare
a, a':t
Ha: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
case compare; now rewrite ?Ha. Qed.
log2_up is always non-negative

forall a : t, 0 <= log2_up a

forall a : t, 0 <= log2_up a
a:t

0 <= log2_up a
a:t

0 <= match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end
a:t

1 < a -> 0 <= S (log2 (P a))
a:t
H:1 < a

0 <= S (log2 (P a))
apply le_le_succ_r, log2_nonneg. Qed.
The spec of log2_up indeed determines it

forall a b : t, 0 < b -> 2 ^ P b < a <= 2 ^ b -> log2_up a == b

forall a b : t, 0 < b -> 2 ^ P b < a <= 2 ^ b -> log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

1 < a
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

1 < a
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

1 <= 2 ^ P b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

S 0 <= 2 ^ P b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

0 < 2 ^ P b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

0 < 2
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
0 <= P b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

0 < 2
order'.
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

0 <= P b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b

0 < S (P b)
now rewrite (lt_succ_pred 0 b Hb).
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

b <= log2_up a
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

b <= log2_up a
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

b < S (log2_up a)
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

S (P b) < S (log2_up a)
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a

P b < log2_up a
apply (pow_lt_mono_r_iff 2); try order'.
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

log2_up a <= b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a
H0:log2_up a <= b
log2_up a == b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

log2_up a <= b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

log2_up a < S b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

S (P (log2_up a)) < S b
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a

P (log2_up a) < b
apply (pow_lt_mono_r_iff 2); try order'.
a, b:t
Hb:0 < b
LEb:2 ^ P b < a
LTb:a <= 2 ^ b
Ha:1 < a
Hc:0 <= log2_up a
LTc:2 ^ P (log2_up a) < a
LEc:a <= 2 ^ log2_up a
H:b <= log2_up a
Hc':0 < log2_up a
H0:log2_up a <= b

log2_up a == b
order. Qed.
log2_up is exact on powers of 2

forall a : t, 0 <= a -> log2_up (2 ^ a) == a

forall a : t, 0 <= a -> log2_up (2 ^ a) == a
a:t
Ha:0 <= a

log2_up (2 ^ a) == a
a:t
Ha:0 < a

log2_up (2 ^ a) == a
a:t
Ha:0 == a
log2_up (2 ^ a) == a
a:t
Ha:0 < a

log2_up (2 ^ a) == a
a:t
Ha:0 < a

2 ^ P a < 2 ^ a <= 2 ^ a
a:t
Ha:0 < a

2 ^ P a < 2 ^ a
a:t
Ha:0 < a

P a < a
a:t
Ha:0 < a

P a < S (P a)
now apply lt_succ_r.
a:t
Ha:0 == a

log2_up (2 ^ a) == a
now rewrite <- Ha, pow_0_r, log2_up_eqn0. Qed.
log2_up and successors of powers of 2

forall a : t, 0 <= a -> log2_up (S (2 ^ a)) == S a

forall a : t, 0 <= a -> log2_up (S (2 ^ a)) == S a
a:t
Ha:0 <= a

log2_up (S (2 ^ a)) == S a
a:t
Ha:0 <= a

1 < S (2 ^ a)
a:t
Ha:0 <= a

0 < 2 ^ a
apply pow_pos_nonneg; order'. Qed.
Basic constants

log2_up 1 == 0

log2_up 1 == 0
now apply log2_up_eqn0. Qed.

log2_up 2 == 1

log2_up 2 == 1

log2_up (2 ^ 1) == 1
apply log2_up_pow2; order'. Qed.
Links between log2 and log2_up

forall a : t, log2 a <= log2_up a

forall a : t, log2 a <= log2_up a
a:t

log2 a <= log2_up a
a:t

log2 a <= match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end
a:t
H:1 == a

log2 a <= 0
a:t
H:1 < a
log2 a <= S (log2 (P a))
a:t
H:a < 1
log2 a <= 0
a:t
H:1 == a

log2 a <= 0
a:t
H:1 == a

0 <= 0
order.
a:t
H:1 < a

log2 a <= S (log2 (P a))
a:t
H:1 < a

log2 (S (P a)) <= S (log2 (P a))
apply log2_succ_le.
a:t
H:a < 1

log2 a <= 0
a:t
H:a < 1

0 <= 0
a:t
H:a < 1
a <= 0
a:t
H:a < 1

0 <= 0
order.
a:t
H:a < 1

a <= 0
now rewrite <-lt_succ_r, <-one_succ. Qed.

forall a : t, log2_up a <= S (log2 a)

forall a : t, log2_up a <= S (log2 a)
a:t

log2_up a <= S (log2 a)
a:t

match compare 1 a with | Lt => S (log2 (P a)) | _ => 0 end <= S (log2 a)
a:t
H:1 < a

S (log2 (P a)) <= S (log2 a)
a:t
H:1 < a

log2 (P a) <= log2 a
a:t
H:1 < a

P a <= a
a:t
H:1 < a

P a <= S (P a)
apply le_succ_diag_r. Qed.

forall a : t, 0 < a -> 2 ^ log2 a <= a <= 2 ^ log2_up a

forall a : t, 0 < a -> 2 ^ log2 a <= a <= 2 ^ log2_up a
a:t
H:0 < a

2 ^ log2 a <= a <= 2 ^ log2_up a
a:t
H:0 < a

2 ^ log2 a <= a
a:t
H:0 < a
a <= 2 ^ log2_up a
a:t
H:0 < a

2 ^ log2 a <= a
now apply log2_spec.
a:t
H:0 < a

a <= 2 ^ log2_up a
a:t
H:1 <= a

a <= 2 ^ log2_up a
a:t
H:1 < a

a <= 2 ^ log2_up a
a:t
H:1 == a
a <= 2 ^ log2_up a
a:t
H:1 < a

a <= 2 ^ log2_up a
now apply log2_up_spec.
a:t
H:1 == a

a <= 2 ^ log2_up a
now rewrite <-H, log2_up_1, pow_0_r. Qed.

forall 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:t
Ha:0 < a

log2 a == log2_up a <-> (exists b : t, a == 2 ^ b)
a:t
Ha:0 < a

log2 a == log2_up a -> exists b : t, a == 2 ^ b
a:t
Ha:0 < a
(exists b : t, a == 2 ^ b) -> log2 a == log2_up a
a:t
Ha:0 < a

log2 a == log2_up a -> exists b : t, a == 2 ^ b
a:t
Ha:0 < a
H:log2 a == log2_up a

exists b : t, a == 2 ^ b
a:t
Ha:0 < a
H:log2 a == log2_up a

a == 2 ^ log2 a
a:t
Ha:0 < a
H:log2 a == log2_up a

2 ^ log2 a <= a <= 2 ^ log2_up a -> a == 2 ^ log2 a
a:t
Ha:0 < a
H:log2 a == log2_up a

2 ^ log2 a <= a <= 2 ^ log2 a -> a == 2 ^ log2 a
destruct 1; order.
a:t
Ha:0 < a

(exists b : t, a == 2 ^ b) -> log2 a == log2_up a
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b

log2 a == log2_up a
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b

log2 (2 ^ b) == log2_up (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
H:0 <= b

log2 (2 ^ b) == log2_up (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
H:b < 0
log2 (2 ^ b) == log2_up (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
H:0 <= b

log2 (2 ^ b) == log2_up (2 ^ b)
now rewrite log2_pow2, log2_up_pow2.
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
H:b < 0

log2 (2 ^ b) == log2_up (2 ^ b)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
H:b < 0

log2 0 == log2_up 0
now rewrite log2_nonpos, log2_up_nonpos. Qed.
log2_up n is strictly positive for 1<n

forall a : t, 1 < a -> 0 < log2_up a

forall a : t, 1 < a -> 0 < log2_up a
a:t
H:1 < a

0 < log2_up a
a:t
H:1 < a

0 < S (log2 (P a))
apply lt_succ_r; order_pos. Qed.
Said otherwise, log2_up is null only below 1

forall a : t, log2_up a == 0 <-> a <= 1

forall a : t, log2_up a == 0 <-> a <= 1
a:t

log2_up a == 0 <-> a <= 1
a:t
H:log2_up a == 0

a <= 1
a:t
H:a <= 1
log2_up a == 0
a:t
H:log2_up a == 0

a <= 1
a:t
H:log2_up a == 0
Ha:1 < a

a <= 1
generalize (log2_up_pos a Ha); order.
a:t
H:a <= 1

log2_up a == 0
now apply log2_up_eqn0. Qed.
log2_up is a monotone function (but not a strict one)

forall a b : t, a <= b -> log2_up a <= log2_up b

forall a b : t, a <= b -> log2_up a <= log2_up b
a, b:t
H:a <= b

log2_up a <= log2_up b
a, b:t
H:a <= b
Ha:a <= 1

log2_up a <= log2_up b
a, b:t
H:a <= b
Ha:1 < a
log2_up a <= log2_up b
a, b:t
H:a <= b
Ha:a <= 1

log2_up a <= log2_up b
a, b:t
H:a <= b
Ha:a <= 1

0 <= log2_up b
apply log2_up_nonneg.
a, b:t
H:a <= b
Ha:1 < a

log2_up a <= log2_up b
a, b:t
H:a <= b
Ha:1 < a

S (log2 (P a)) <= S (log2 (P b))
a, b:t
H:a <= b
Ha:1 < a

log2 (P a) <= log2 (P b)
a, b:t
H:a <= b
Ha:1 < a

S (P a) <= S (P b)
rewrite 2 lt_succ_pred with 1; order. Qed.
No reverse result for <=, consider for instance log2_up 4 <= log2_up 3

forall a b : t, log2_up a < log2_up b -> a < b

forall a b : t, log2_up a < log2_up b -> a < b
a, b:t
H:log2_up a < log2_up b

a < b
a, b:t
H:log2_up a < log2_up b
Hb:b <= 1

a < b
a, b:t
H:log2_up a < log2_up b
Hb:1 < b
a < b
a, b:t
H:log2_up a < log2_up b
Hb:b <= 1

a < b
a, b:t
H:log2_up a < 0
Hb:b <= 1

a < b
generalize (log2_up_nonneg a); order.
a, b:t
H:log2_up a < log2_up b
Hb:1 < b

a < b
a, b:t
H:log2_up a < log2_up b
Hb:1 < b
Ha:a <= 1

a < b
a, b:t
H:log2_up a < log2_up b
Hb:1 < b
Ha:1 < a
a < b
a, b:t
H:log2_up a < log2_up b
Hb:1 < b
Ha:a <= 1

a < b
order.
a, b:t
H:log2_up a < log2_up b
Hb:1 < b
Ha:1 < a

a < b
a, b:t
H:S (log2 (P a)) < S (log2 (P b))
Hb:1 < b
Ha:1 < a

a < b
a, b:t
H:log2 (P a) < log2 (P b)
Hb:1 < b
Ha:1 < a

a < b
a, b:t
H:S (P a) < S (P b)
Hb:1 < b
Ha:1 < a

a < b
rewrite 2 lt_succ_pred with 1 in H; order. Qed.
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 a

forall a b : t, 0 < a -> 2 ^ b < a <-> b < log2_up a
a, b:t
Ha:0 < a

2 ^ b < a <-> b < log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a

b < log2_up a
a, b:t
Ha:0 < a
H:b < log2_up a
2 ^ b < a
a, b:t
Ha:0 < a
H:2 ^ b < a

b < log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:b < 0

b < log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b
b < log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:b < 0

b < log2_up a
generalize (log2_up_nonneg a); order.
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

b < log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

1 < 2
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b
0 <= log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b
2 ^ b < 2 ^ log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

1 < 2
order'.
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

0 <= log2_up a
apply log2_up_nonneg.
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

2 ^ b < 2 ^ log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

a <= 2 ^ log2_up a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

1 < a
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

1 <= 2 ^ b
a, b:t
Ha:0 < a
H:2 ^ b < a
Hb:0 <= b

0 < 2 ^ b
apply pow_pos_nonneg; order'.
a, b:t
Ha:0 < a
H:b < log2_up a

2 ^ b < a
a, b:t
Ha:0 < a
H:b < log2_up a
Hb:b < 0

2 ^ b < a
a, b:t
Ha:0 < a
H:b < log2_up a
Hb:0 <= b
2 ^ b < a
a, b:t
Ha:0 < a
H:b < log2_up a
Hb:b < 0

2 ^ b < a
now rewrite pow_neg_r.
a, b:t
Ha:0 < a
H:b < log2_up a
Hb:0 <= b

2 ^ b < a
a, b:t
Ha:0 < a
H:log2_up (2 ^ b) < log2_up a
Hb:0 <= b

2 ^ b < a
now apply log2_up_lt_cancel. Qed.
When right side is a square, we have an equivalence for <=

forall a b : t, 0 < a -> a <= 2 ^ b <-> log2_up a <= b

forall a b : t, 0 < a -> a <= 2 ^ b <-> log2_up a <= b
a, b:t
Ha:0 < a

a <= 2 ^ b <-> log2_up a <= b
a, b:t
Ha:0 < a
H:a <= 2 ^ b

log2_up a <= b
a, b:t
Ha:0 < a
H:log2_up a <= b
a <= 2 ^ b
a, b:t
Ha:0 < a
H:a <= 2 ^ b

log2_up a <= b
a, b:t
Ha:0 < a
H:a <= 2 ^ b
Hb:b < 0

log2_up a <= b
a, b:t
Ha:0 < a
H:a <= 2 ^ b
Hb:0 <= b
log2_up a <= b
a, b:t
Ha:0 < a
H:a <= 2 ^ b
Hb:b < 0

log2_up a <= b
rewrite pow_neg_r in H; order.
a, b:t
Ha:0 < a
H:a <= 2 ^ b
Hb:0 <= b

log2_up a <= b
a, b:t
Ha:0 < a
H:a <= 2 ^ b
Hb:0 <= b

log2_up a <= log2_up (2 ^ b)
now apply log2_up_le_mono.
a, b:t
Ha:0 < a
H:log2_up a <= b

a <= 2 ^ b
a, b:t
Ha:0 < a
H:log2_up a <= b

a <= 2 ^ log2_up a
a, b:t
Ha:0 < a
H:log2_up a <= b
2 ^ log2_up a <= 2 ^ b
a, b:t
Ha:0 < a
H:log2_up a <= b

a <= 2 ^ log2_up a
now apply log2_log2_up_spec.
a, b:t
Ha:0 < a
H:log2_up a <= b

2 ^ log2_up a <= 2 ^ b
apply pow_le_mono_r; order'. Qed.
Comparing log2_up and identity

forall a : t, 0 < a -> log2_up a < a

forall a : t, 0 < a -> log2_up a < a
a:t
Ha:0 < a

log2_up a < a
a:t
Ha:0 < a
H:S (P a) == a

log2_up a < a
a:t
Ha:0 < a
H:S (P a) == a

log2_up a < S (P a)
a:t
Ha:0 < a
H:S (P a) == a

log2_up a <= P a
a:t
Ha:0 < a
H:S (P a) == a

a <= 2 ^ P a
a:t
Ha:0 < a
H:S (P a) == a

S (P a) <= 2 ^ P a
a:t
Ha:0 < a
H:S (P a) == a

P a < 2 ^ P a
a:t
Ha:0 < a
H:S (P a) == a

1 < 2
a:t
Ha:0 < a
H:S (P a) == a
0 <= P a
a:t
Ha:0 < a
H:S (P a) == a

1 < 2
order'.
a:t
Ha:0 < a
H:S (P a) == a

0 <= P a
apply lt_succ_r; order. Qed.

forall a : t, 0 <= a -> log2_up a <= a

forall a : t, 0 <= a -> log2_up a <= a
a:t
Ha:0 <= a

log2_up a <= a
a:t
Ha:0 < a

log2_up a <= a
a:t
Ha:0 == a
log2_up a <= a
a:t
Ha:0 < a

log2_up a <= a
now apply lt_le_incl, log2_up_lt_lin.
a:t
Ha:0 == a

log2_up a <= a
rewrite <- Ha, log2_up_nonpos; order. Qed.
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 b

forall a b : t, 0 <= a -> 0 <= b -> log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 <= a
Hb:0 <= b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 <= a
Hb:0 <= b
Ha':0 <= log2_up a

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 <= a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 == a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b
log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 < b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 == b
Ha':0 <= log2_up a
Hb':0 <= log2_up b
log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 < b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 < b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

a * b <= 2 ^ (log2_up a + log2_up b)
a, b:t
Ha:0 < a
Hb:0 < b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

a * b <= 2 ^ log2_up a * 2 ^ log2_up b
apply mul_le_mono_nonneg; try apply log2_log2_up_spec; order'.
a, b:t
Ha:0 < a
Hb:0 == b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 < a
Hb:0 == b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * 0) <= log2_up a + log2_up 0
a, b:t
Ha:0 < a
Hb:0 == b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up 0 <= log2_up a + log2_up 0
rewrite log2_up_nonpos; order_pos.
a, b:t
Ha:0 == a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha:0 == a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up (0 * b) <= log2_up 0 + log2_up b
a, b:t
Ha:0 == a
Hb:0 <= b
Ha':0 <= log2_up a
Hb':0 <= log2_up b

log2_up 0 <= log2_up 0 + log2_up b
rewrite log2_up_nonpos; order_pos. Qed.

forall 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:t
Ha:0 < a
Hb:0 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 <= a
Hb:0 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:0 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 == a
Hb:0 < b
log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:0 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 <= b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 == b
log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

S (P (log2_up a)) + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

S (P (log2_up a)) + S (P (log2_up b)) <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

S (S (P (log2_up a) + P (log2_up b))) <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

P (log2_up a) + P (log2_up b) < log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

1 < 2
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b
0 <= log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b
2 ^ (P (log2_up a) + P (log2_up b)) < 2 ^ log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

1 < 2
order'.
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

0 <= log2_up (a * b)
apply log2_up_nonneg.
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

2 ^ (P (log2_up a) + P (log2_up b)) < 2 ^ log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

2 ^ P (log2_up a) * 2 ^ P (log2_up b) < 2 ^ log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

2 ^ P (log2_up a) * 2 ^ P (log2_up b) < a * b
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b
a * b <= 2 ^ log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

2 ^ P (log2_up a) * 2 ^ P (log2_up b) < a * b
apply mul_lt_mono_nonneg; try order_pos; try now apply log2_up_spec.
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

a * b <= 2 ^ log2_up (a * b)
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

1 < a * b
a, b:t
Ha:1 < a
Hb:1 < b
Ha':0 < log2_up a
Hb':0 < log2_up b

1 * 1 < a * b
apply mul_lt_mono_nonneg; order'.
a, b:t
Ha:1 < a
Hb:1 == b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 < a
Hb:1 == b

log2_up a <= S (log2_up a)
apply le_succ_diag_r.
a, b:t
Ha:1 == a
Hb:0 < b

log2_up a + log2_up b <= S (log2_up (a * b))
a, b:t
Ha:1 == a
Hb:0 < b

log2_up b <= S (log2_up b)
apply le_succ_diag_r. Qed.
And we can't find better approximations in general.
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 a

forall a b : t, 0 < a -> 0 <= b -> log2_up (a * 2 ^ b) == b + log2_up a
a, b:t
Ha:0 < a
Hb:0 <= b

log2_up (a * 2 ^ b) == b + log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

log2_up (a * 2 ^ b) == b + log2_up a
a, b:t
Ha:1 == a
Hb:0 <= b
log2_up (a * 2 ^ b) == b + log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

log2_up (a * 2 ^ b) == b + log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

0 < b + log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b
2 ^ P (b + log2_up a) < a * 2 ^ b <= 2 ^ (b + log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b

0 < b + log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

0 < log2_up a
now apply log2_up_pos.
a, b:t
Ha:1 < a
Hb:0 <= b

2 ^ P (b + log2_up a) < a * 2 ^ b <= 2 ^ (b + log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b

2 ^ P (b + log2_up a) < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
a * 2 ^ b <= 2 ^ (b + log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b

2 ^ P (b + log2_up a) < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ P (b + log2_up a) < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ P (b + S (P (log2_up a))) < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ (b + P (log2_up a)) < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ P (log2_up a) * 2 ^ b < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a
0 <= P (log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ P (log2_up a) * 2 ^ b < a * 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

0 < 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a
2 ^ P (log2_up a) < a
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

0 < 2 ^ b
order_pos.
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

2 ^ P (log2_up a) < a
now apply log2_up_spec.
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

0 <= P (log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b
EQ:S (P (log2_up a)) == log2_up a

0 < log2_up a
now apply log2_up_pos.
a, b:t
Ha:1 < a
Hb:0 <= b

a * 2 ^ b <= 2 ^ (b + log2_up a)
a, b:t
Ha:1 < a
Hb:0 <= b

2 ^ b * a <= 2 ^ b * 2 ^ log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b
0 <= log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

2 ^ b * a <= 2 ^ b * 2 ^ log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

0 <= 2 ^ b
a, b:t
Ha:1 < a
Hb:0 <= b
a <= 2 ^ log2_up a
a, b:t
Ha:1 < a
Hb:0 <= b

0 <= 2 ^ b
order_pos.
a, b:t
Ha:1 < a
Hb:0 <= b

a <= 2 ^ log2_up a
now apply log2_up_spec.
a, b:t
Ha:1 < a
Hb:0 <= b

0 <= log2_up a
apply log2_up_nonneg.
a, b:t
Ha:1 == a
Hb:0 <= b

log2_up (a * 2 ^ b) == b + log2_up a
now rewrite <- Ha, mul_1_l, log2_up_1, add_0_r, log2_up_pow2. Qed.

forall 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:t
Ha:0 < a

log2_up (2 * a) == S (log2_up a)
a:t
Ha:0 < a

log2_up (a * 2 ^ 1) == 1 + log2_up a -> log2_up (2 * a) == S (log2_up a)
now nzsimpl'. Qed.
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 * b

forall a b : t, 0 < a -> 0 < b -> log2_up a == log2_up b -> a < 2 * b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up b

a < 2 * b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up b

log2_up a < log2_up (2 * b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up b

log2_up b < S (log2_up b)
apply lt_succ_diag_r. Qed.
log2_up and successor :

forall a : t, log2_up (S a) <= S (log2_up a)

forall a : t, log2_up (S a) <= S (log2_up a)
a:t

log2_up (S a) <= S (log2_up a)
a:t
LT:1 < a

log2_up (S a) <= S (log2_up a)
a:t
EQ:1 == a
log2_up (S a) <= S (log2_up a)
a:t
LT:a < 1
log2_up (S a) <= S (log2_up a)
a:t
LT:1 < a

log2_up (S a) <= S (log2_up a)
a:t
LT:1 < a

S (log2 (P (S a))) <= S (S (log2 (P a)))
a:t
LT:1 < a
1 < S a
a:t
LT:1 < a

S (log2 (P (S a))) <= S (S (log2 (P a)))
a:t
LT:1 < a

log2 a <= S (log2 (P a))
a:t
LT:1 < a

log2 (S (P a)) <= S (log2 (P a))
apply log2_succ_le.
a:t
LT:1 < a

1 < S a
apply lt_succ_r; order.
a:t
EQ:1 == a

log2_up (S a) <= S (log2_up a)
a:t
EQ:1 == a

1 <= S 0
now nzsimpl'.
a:t
LT:a < 1

log2_up (S a) <= S (log2_up a)
a:t
LT:a < 1

0 <= S 0
a:t
LT:a < 1
a <= 1
a:t
LT:a < 1
S a <= 1
a:t
LT:a < 1

0 <= S 0
order_pos.
a:t
LT:a < 1

a <= 1
order'.
a:t
LT:a < 1

S a <= 1
now rewrite le_succ_l. Qed.

forall a : t, log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a

forall a : t, log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t

log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t
H:log2_up (S a) <= log2_up a

log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t
H:log2_up a < log2_up (S a)
log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t
H:log2_up (S a) <= log2_up a

log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t
H:log2_up (S a) <= log2_up a

log2_up (S a) == log2_up a
generalize (log2_up_le_mono _ _ (le_succ_diag_r a)); order.
a:t
H:log2_up a < log2_up (S a)

log2_up (S a) == S (log2_up a) \/ log2_up (S a) == log2_up a
a:t
H:log2_up a < log2_up (S a)

log2_up (S a) == S (log2_up a)
a:t
H:S (log2_up a) <= log2_up (S a)

log2_up (S a) == S (log2_up a)
generalize (log2_up_succ_le a); order. Qed.

forall a : t, log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ b

forall a : t, log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)

exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)
Ha:a <= 0

exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a
exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)
Ha:a <= 0

exists b : t, a == 2 ^ b
a:t
H:0 == S 0
Ha:a <= 0

exists b : t, a == 2 ^ b
a:t
H:0 == S (log2_up a)
Ha:a <= 0
a <= 1
a:t
H:log2_up (S a) == S (log2_up a)
Ha:a <= 0
S a <= 1
a:t
H:0 == S 0
Ha:a <= 0

exists b : t, a == 2 ^ b
generalize (lt_succ_diag_r 0); order.
a:t
H:0 == S (log2_up a)
Ha:a <= 0

a <= 1
order'.
a:t
H:log2_up (S a) == S (log2_up a)
Ha:a <= 0

S a <= 1
a:t
H:log2_up (S a) == S (log2_up a)
Ha:a <= 0

a < 1
order'.
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a

exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a
Ha':1 < S a

exists b : t, a == 2 ^ b
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a
Ha':1 < S a

a == 2 ^ log2_up a
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a
Ha':1 < S a

2 ^ P (log2_up (S a)) < S a -> a <= 2 ^ log2_up a -> a == 2 ^ log2_up a
a:t
H:log2_up (S a) == S (log2_up a)
Ha:0 < a
Ha':1 < S a

2 ^ log2_up a <= a -> a <= 2 ^ log2_up a -> a == 2 ^ log2_up a
order. Qed.

forall 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:t
Ha:0 < a

log2_up (S a) == S (log2_up a) <-> (exists b : t, a == 2 ^ b)
a:t
Ha:0 < a

log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ b
a:t
Ha:0 < a
(exists b : t, a == 2 ^ b) -> log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a

log2_up (S a) == S (log2_up a) -> exists b : t, a == 2 ^ b
apply log2_up_eq_succ_is_pow2.
a:t
Ha:0 < a

(exists b : t, a == 2 ^ b) -> log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b

log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
Hb':b < 0

log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
Hb':0 <= b
log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
Hb':b < 0

log2_up (S a) == S (log2_up a)
rewrite pow_neg_r in Hb; order.
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
Hb':0 <= b

log2_up (S a) == S (log2_up a)
a:t
Ha:0 < a
b:t
Hb:a == 2 ^ b
Hb':0 <= b

log2_up (S (2 ^ b)) == S b
now rewrite log2_up_succ_pow2. Qed.

forall a : t, 0 < a -> log2_up (2 * a + 1) == 2 + log2 a

forall a : t, 0 < a -> log2_up (2 * a + 1) == 2 + log2 a
a:t
Ha:0 < a

log2_up (2 * a + 1) == 2 + log2 a
a:t
Ha:0 < a

S (log2 (P (2 * a + 1))) == 2 + log2 a
a:t
Ha:0 < a
1 < 2 * a + 1
a:t
Ha:0 < a

S (log2 (P (2 * a + 1))) == 2 + log2 a
rewrite add_1_r, pred_succ, log2_double; now nzsimpl'.
a:t
Ha:0 < a

1 < 2 * a + 1
a:t
Ha:0 < a

1 <= 0 + 1
a:t
Ha:0 < a
0 + 1 < 2 * a + 1
a:t
Ha:0 < a

1 <= 0 + 1
now nzsimpl'.
a:t
Ha:0 < a

0 + 1 < 2 * a + 1
a:t
Ha:0 < a

0 < 2 * a
order_pos. Qed.
log2_up and addition

forall a b : t, a ~= 1 -> b ~= 1 -> log2_up (a + b) <= log2_up a + log2_up b

forall a b : t, a ~= 1 -> b ~= 1 -> log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2_up (a + b) <= 0 + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

log2_up (a + b) <= log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a < 1

a + b <= b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

a + b <= b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':a <= 0

a + b <= 0 + b
now apply add_le_mono.
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':1 < b
log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2_up (a + b) <= log2_up a + 0
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

log2_up (a + b) <= log2_up a
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b < 1

a + b <= a
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

a + b <= a
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':b <= 0

a + b <= a + 0
now apply add_le_mono.
a, b:t
Ha:a ~= 1
Hb:b ~= 1
Ha':1 < a
Hb':1 < b

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha':1 < a
Hb':1 < b

log2_up (a + b) <= log2_up a + log2_up b
a, b:t
Ha':1 < a
Hb':1 < b

log2_up (a + b) <= log2_up (a * b)
a, b:t
Ha':1 < a
Hb':1 < b
log2_up (a * b) <= log2_up a + log2_up b
a, b:t
Ha':1 < a
Hb':1 < b

log2_up (a + b) <= log2_up (a * b)
now apply log2_up_le_mono, add_le_mul.
a, b:t
Ha':1 < a
Hb':1 < b

log2_up (a * b) <= log2_up a + log2_up b
apply log2_up_mul_above; order'. Qed.
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:t
Ha:0 < a
Hb:0 < b

log2_up a + log2_up b < 2 * log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2_up a <= log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)
log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

log2_up a <= log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a <= a + b
a, b:t
Ha:0 < a
Hb:0 < b

a + 0 <= a + b
apply add_le_mono; order.
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)

log2_up a + log2_up b < log2_up (a + b) + log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)

log2_up b <= log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)

log2_up b <= log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)

b <= a + b
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a <= log2_up (a + b)

0 + b <= a + b
apply add_le_mono; order.
a, b:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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 b
a, b:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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 b
now apply add_lt_mono_r.
a, b:t
Ha:0 < a
Hb:0 < b
H: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_le_mono_l.
a, b:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up (a + b)
H':log2_up b <= log2_up (a + b)

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up (a + b)
H':log2_up b < log2_up (a + b)

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up (a + b)
H':log2_up b == log2_up (a + b)
log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H: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:t
Ha:0 < a
Hb:0 < b
H:log2_up a == log2_up (a + b)
H':log2_up b == log2_up (a + b)

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:log2_up (a + b) == log2_up a
H':log2_up b == log2_up (a + b)

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':log2_up b == log2_up (a + b)

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':log2_up (a + b) == log2_up b

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b
H:a + b < 2 * a
H':a + b < 2 * b

log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a + b < 2 * a -> a + b < 2 * b -> log2_up b < log2_up (a + b)
a, b:t
Ha:0 < a
Hb:0 < b

a + b < a + a -> a + b < b + b -> log2_up b < log2_up (a + b)
rewrite <- add_lt_mono_l, <- add_lt_mono_r; order. Qed. End NZLog2UpProp.