Built with Alectryon, running Coq+SerAPI v8.10.0+0.7.0. Coq sources are in this panel; goals and messages will appear in the other. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+🖱️ to focus.
(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2018       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)

Require Import Bool NAxioms NSub NPow NDiv NParity NLog.
Derived properties of bitwise operations
Module Type NBitsProp
 (Import A : NAxiomsSig')
 (Import B : NSubProp A)
 (Import C : NParityProp A B)
 (Import D : NPowProp A B C)
 (Import E : NDivProp A B)
 (Import F : NLog2Prop A B C D).

Include BoolEqualityFacts A.

Ltac order_nz := try apply pow_nonzero; order'.
Hint Rewrite div_0_l mod_0_l div_1_r mod_1_r : nz.
Some properties of power and division

forall a b c : t, a ~= 0 -> c <= b -> a ^ (b - c) == a ^ b / a ^ c

forall a b c : t, a ~= 0 -> c <= b -> a ^ (b - c) == a ^ b / a ^ c
a, b, c:t
Ha:a ~= 0
H:c <= b

a ^ (b - c) == a ^ b / a ^ c
a, b, c:t
Ha:a ~= 0
H:c <= b

0 < a ^ c
a, b, c:t
Ha:a ~= 0
H:c <= b
a ^ b == a ^ c * a ^ (b - c) + 0
a, b, c:t
Ha:a ~= 0
H:c <= b

a ^ b == a ^ c * a ^ (b - c) + 0
a, b, c:t
Ha:a ~= 0
H:c <= b

a ^ b == a ^ c * a ^ (b - c)
now rewrite <- pow_add_r, add_comm, sub_add. Qed.

forall a b c : t, b ~= 0 -> a mod b == 0 -> (a / b) ^ c == a ^ c / b ^ c

forall a b c : t, b ~= 0 -> a mod b == 0 -> (a / b) ^ c == a ^ c / b ^ c
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

(a / b) ^ c == a ^ c / b ^ c
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

0 < b ^ c
a, b, c:t
Hb:b ~= 0
H:a mod b == 0
a ^ c == b ^ c * (a / b) ^ c + 0
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

a ^ c == b ^ c * (a / b) ^ c + 0
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

a ^ c == b ^ c * (a / b) ^ c
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

a ^ c == (b * (a / b)) ^ c
a, b, c:t
Hb:b ~= 0
H:a mod b == 0

a == b * (a / b)
now apply div_exact. Qed.
An injection from bits true and false to numbers 1 and 0. We declare it as a (local) coercion for shorter statements.
Definition b2n (b:bool) := if b then 1 else 0.
Coercion b2n : bool >-> t.


Proper (Logic.eq ==> eq) b2n

Proper (Logic.eq ==> eq) b2n
solve_proper. Qed.
a:t

exists (a' : t) (b : bool), a == 2 * a' + b
a:t

exists (a' : t) (b : bool), a == 2 * a' + b
a, a':t
H:a == 2 * a'

exists (a'0 : t) (b : bool), a == 2 * a'0 + b
a, a':t
H:a == 2 * a' + 1
exists (a'0 : t) (b : bool), a == 2 * a'0 + b
a, a':t
H:a == 2 * a'

exists b : bool, a == 2 * a' + b
a, a':t
H:a == 2 * a' + 1
exists (a'0 : t) (b : bool), a == 2 * a'0 + b
a, a':t
H:a == 2 * a'

a == 2 * a' + false
a, a':t
H:a == 2 * a' + 1
exists (a'0 : t) (b : bool), a == 2 * a'0 + b
a, a':t
H:a == 2 * a' + 1

exists (a'0 : t) (b : bool), a == 2 * a'0 + b
a, a':t
H:a == 2 * a' + 1

exists b : bool, a == 2 * a' + b
a, a':t
H:a == 2 * a' + 1

a == 2 * a' + true
now simpl. Qed.
We can compact testbit_odd_0 testbit_even_0 testbit_even_succ testbit_odd_succ in only two lemmas.
a:t
b:bool

(2 * a + b).[0] = b
a:t
b:bool

(2 * a + b).[0] = b
a:t

(2 * a + 1).[0] = true
a:t
(2 * a).[0] = false
a:t

(2 * a).[0] = false
apply testbit_even_0. Qed.
a:t
b:bool
n:t

(2 * a + b).[S n] = a.[n]
a:t
b:bool
n:t

(2 * a + b).[S n] = a.[n]
a, n:t

(2 * a + 1).[S n] = a.[n]
a, n:t
(2 * a).[S n] = a.[n]
a, n:t

(2 * a).[S n] = a.[n]
apply testbit_even_succ, le_0_l. Qed.
Alternative characterisations of testbit
This concise equation could have been taken as specification for testbit in the interface, but it would have been hard to implement with little initial knowledge about div and mod
a, n:t

a.[n] == (a / 2 ^ n) mod 2
a, n:t

a.[n] == (a / 2 ^ n) mod 2
n:t

forall a : t, a.[n] == (a / 2 ^ n) mod 2

forall a : t, a.[0] == (a / 2 ^ 0) mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a:t

a.[0] == (a / 2 ^ 0) mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a:t

a.[0] == a mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

a.[0] == a mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

(2 * a' + b).[0] == a mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

b == a mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

b < 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2

forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a:t

a.[S n] == (a / 2 ^ S n) mod 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

a.[S n] == (a / 2 ^ S n) mod 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

(2 * a' + b).[S n] == (a / 2 ^ S n) mod 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

(a' / 2 ^ n) mod 2 == (a / 2 ^ S n) mod 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

a' / 2 ^ n == a / 2 ^ S n
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

a' / 2 ^ n == a / 2 / 2 ^ n
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

a' == a / 2
n:t
IH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2
a, a':t
b:bool
H:a == 2 * a' + b

b < 2
destruct b; order'. Qed.
This characterisation that uses only basic operations and power was initially taken as specification for testbit. We describe a as having a low part and a high part, with the corresponding bit in the middle. This characterisation is moderatly complex to implement, but also moderately usable...
a, n:t

exists l h : t, 0 <= l < 2 ^ n /\ a == l + (a.[n] + 2 * h) * 2 ^ n
a, n:t

exists l h : t, 0 <= l < 2 ^ n /\ a == l + (a.[n] + 2 * h) * 2 ^ n
a, n:t

exists h : t, 0 <= a mod 2 ^ n < 2 ^ n /\ a == a mod 2 ^ n + (a.[n] + 2 * h) * 2 ^ n
a, n:t

0 <= a mod 2 ^ n < 2 ^ n /\ a == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ n
a, n:t

0 <= a mod 2 ^ n < 2 ^ n
a, n:t
a == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ n
a, n:t

a == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ n
a, n:t

a == 2 ^ n * (2 * (a / 2 ^ n / 2) + a.[n]) + a mod 2 ^ n
a, n:t

2 ^ n * (a / 2 ^ n) + a mod 2 ^ n == 2 ^ n * (2 * (a / 2 ^ n / 2) + a.[n]) + a mod 2 ^ n
a, n:t

a / 2 ^ n == 2 * (a / 2 ^ n / 2) + a.[n]
a, n:t

a / 2 ^ n == 2 * (a / 2 ^ n / 2) + (a / 2 ^ n) mod 2
a, n:t

2 ~= 0
order'. Qed.

forall a n : t, a.[n] = true <-> (a / 2 ^ n) mod 2 == 1

forall a n : t, a.[n] = true <-> (a / 2 ^ n) mod 2 == 1
a, n:t

a.[n] = true <-> (a / 2 ^ n) mod 2 == 1
rewrite <- testbit_spec'; destruct a.[n]; split; simpl; now try order'. Qed.

forall a n : t, a.[n] = false <-> (a / 2 ^ n) mod 2 == 0

forall a n : t, a.[n] = false <-> (a / 2 ^ n) mod 2 == 0
a, n:t

a.[n] = false <-> (a / 2 ^ n) mod 2 == 0
rewrite <- testbit_spec'; destruct a.[n]; split; simpl; now try order'. Qed.

forall a n : t, a.[n] = ((a / 2 ^ n) mod 2 =? 1)

forall a n : t, a.[n] = ((a / 2 ^ n) mod 2 =? 1)
a, n:t

a.[n] = ((a / 2 ^ n) mod 2 =? 1)
a, n:t

a.[n] = true <-> ((a / 2 ^ n) mod 2 =? 1) = true
now rewrite testbit_true, eqb_eq. Qed.
Results about the injection b2n

forall a0 b0 : bool, a0 == b0 -> a0 = b0

forall a0 b0 : bool, a0 == b0 -> a0 = b0
intros [|] [|]; simpl; trivial; order'. Qed.

forall (a0 : bool) (a : t), (a0 + 2 * a) / 2 == a

forall (a0 : bool) (a : t), (a0 + 2 * a) / 2 == a
a0:bool
a:t

(a0 + 2 * a) / 2 == a
a0:bool
a:t

a0 / 2 + a == a
now rewrite div_small, add_0_l by (destruct a0; order'). Qed.

forall (a0 : bool) (a : t), (a0 + 2 * a).[0] = a0

forall (a0 : bool) (a : t), (a0 + 2 * a).[0] = a0
a0:bool
a:t

(a0 + 2 * a).[0] = a0
a0:bool
a:t

(a0 + 2 * a).[0] == a0
a0:bool
a:t

((a0 + 2 * a) / 2 ^ 0) mod 2 == a0
a0:bool
a:t

(a0 + 2 * a) mod 2 == a0
a0:bool
a:t

a0 mod 2 == a0
now rewrite mod_small by (destruct a0; order'). Qed.

forall a0 : bool, a0 / 2 == 0

forall a0 : bool, a0 / 2 == 0
a0:bool

a0 / 2 == 0
a0:bool

a0 / 2 == (a0 + 2 * 0) / 2
now nzsimpl. Qed.

forall a0 : bool, a0.[0] = a0

forall a0 : bool, a0.[0] = a0
a0:bool

a0.[0] = a0
a0:bool

a0.[0] = (a0 + 2 * 0).[0]
now nzsimpl. Qed.
The specification of testbit by low and high parts is complete

forall (a n : t) (a0 : bool) (l h : t), l < 2 ^ n -> a == l + (a0 + 2 * h) * 2 ^ n -> a.[n] = a0

forall (a n : t) (a0 : bool) (l h : t), l < 2 ^ n -> a == l + (a0 + 2 * h) * 2 ^ n -> a.[n] = a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a.[n] = a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a.[n] == a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

(a / 2 ^ n) mod 2 == a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a0 == (a / 2 ^ n) mod 2
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a0 < 2
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n
a / 2 ^ n == 2 * h + a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a / 2 ^ n == 2 * h + a0
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

2 * h + a0 == a / 2 ^ n
a, n:t
a0:bool
l, h:t
Hl:l < 2 ^ n
EQ:a == l + (a0 + 2 * h) * 2 ^ n

a == 2 ^ n * (2 * h + a0) + l
now rewrite add_comm, (add_comm _ a0), mul_comm. Qed.
All bits of number 0 are 0

forall n : t, 0.[n] = false

forall n : t, 0.[n] = false
n:t

0.[n] = false
n:t

(0 / 2 ^ n) mod 2 == 0
nzsimpl; order_nz. Qed.
Various ways to refer to the lowest bit of a number

forall a : t, a.[0] = odd a

forall a : t, a.[0] = odd a
a:t

a.[0] = odd a
a:t

odd a = a.[0]
a, a':t
b:bool
EQ:a == 2 * a' + b

odd a = a.[0]
a, a':t
b:bool
EQ:a == 2 * a' + b

odd b = b
destruct b; simpl; apply odd_1 || apply odd_0. Qed.

forall a : t, a.[0] = (a mod 2 =? 1)

forall a : t, a.[0] = (a mod 2 =? 1)
a:t

a.[0] = (a mod 2 =? 1)
a:t

((a / 2 ^ 0) mod 2 =? 1) = (a mod 2 =? 1)
now nzsimpl. Qed.

forall a : t, a.[0] == a mod 2

forall a : t, a.[0] == a mod 2
a:t

a.[0] == a mod 2
a:t

(a / 2 ^ 0) mod 2 == a mod 2
now nzsimpl. Qed.
Hence testing a bit is equivalent to shifting and testing parity

forall a n : t, a.[n] = odd (a >> n)

forall a n : t, a.[n] = odd (a >> n)
a, n:t

a.[n] = odd (a >> n)
now rewrite <- bit0_odd, shiftr_spec, add_0_l. Qed.
log2 gives the highest nonzero bit

forall a : t, a ~= 0 -> a.[log2 a] = true

forall a : t, a ~= 0 -> a.[log2 a] = true
a:t
Ha:a ~= 0

a.[log2 a] = true
a:t
Ha:a ~= 0
Ha':0 < a

a.[log2 a] = true
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

a.[log2 a] = true
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

(2 ^ log2 a + r).[log2 a] = true
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

((r + 2 ^ log2 a) / 2 ^ log2 a) mod 2 == 1
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

((r + 1 * 2 ^ log2 a) / 2 ^ log2 a) mod 2 == 1
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

(r / 2 ^ log2 a + 1) mod 2 == 1
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

(0 + 1) mod 2 == 1
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

1 mod 2 == 1
a:t
Ha:a ~= 0
Ha':0 < a
r:t
EQ:a == 2 ^ log2 a + r
Hr:r < 2 ^ log2 a

1 < 2
order'. Qed.

forall a n : t, log2 a < n -> a.[n] = false

forall a n : t, log2 a < n -> a.[n] = false
a, n:t
H:log2 a < n

a.[n] = false
a, n:t
H:log2 a < n

(a / 2 ^ n) mod 2 == 0
a, n:t
H:log2 a < n

0 mod 2 == 0
a, n:t
H:log2 a < n
a < 2 ^ n
a, n:t
H:log2 a < n

a < 2 ^ n
a, n:t
H:log2 a < n

log2 a < log2 (2 ^ n)
rewrite log2_pow2; trivial using le_0_l. Qed.
Hence the number of bits of a is 1+log2 a (see Pos.size_nat and Pos.size).
Testing bits after division or multiplication by a power of two

forall a n : t, (a / 2).[n] = a.[S n]

forall a n : t, (a / 2).[n] = a.[S n]
a, n:t

(a / 2).[n] = a.[S n]
a, n:t

(a / 2).[n] = true <-> a.[S n] = true
a, n:t

(a / 2 / 2 ^ n) mod 2 == 1 <-> (a / 2 ^ S n) mod 2 == 1
a, n:t

(a / 2 / 2 ^ n) mod 2 == 1 <-> (a / (2 * 2 ^ n)) mod 2 == 1
now rewrite div_div by order_nz. Qed.

forall a n m : t, (a / 2 ^ n).[m] = a.[m + n]

forall a n m : t, (a / 2 ^ n).[m] = a.[m + n]
a, n:t

forall m : t, (a / 2 ^ n).[m] = a.[m + n]
n:t

forall a m : t, (a / 2 ^ n).[m] = a.[m + n]

forall a m : t, (a / 2 ^ 0).[m] = a.[m + 0]

forall n : t, (forall a m : t, (a / 2 ^ n).[m] = a.[m + n]) -> forall a m : t, (a / 2 ^ S n).[m] = a.[m + S n]
a, m:t

(a / 2 ^ 0).[m] = a.[m + 0]

forall n : t, (forall a m : t, (a / 2 ^ n).[m] = a.[m + n]) -> forall a m : t, (a / 2 ^ S n).[m] = a.[m + S n]

forall n : t, (forall a m : t, (a / 2 ^ n).[m] = a.[m + n]) -> forall a m : t, (a / 2 ^ S n).[m] = a.[m + S n]
n:t
IH:forall a0 m0 : t, (a0 / 2 ^ n).[m0] = a0.[m0 + n]
a, m:t

(a / 2 ^ S n).[m] = a.[m + S n]
n:t
IH:forall a0 m0 : t, (a0 / 2 ^ n).[m0] = a0.[m0 + n]
a, m:t

(a / (2 * 2 ^ n)).[m] = a.[S (m + n)]
n:t
IH:forall a0 m0 : t, (a0 / 2 ^ n).[m0] = a0.[m0 + n]
a, m:t

(a / 2 / 2 ^ n).[m] = a.[S (m + n)]
now rewrite IH, div2_bits. Qed.

forall a n : t, (2 * a).[S n] = a.[n]

forall a n : t, (2 * a).[S n] = a.[n]
a, n:t

(2 * a).[S n] = a.[n]
a, n:t

(2 * a / 2).[n] = a.[n]
now rewrite mul_comm, div_mul by order'. Qed.

forall a n m : t, (a * 2 ^ n).[m + n] = a.[m]

forall a n m : t, (a * 2 ^ n).[m + n] = a.[m]
a, n, m:t

(a * 2 ^ n).[m + n] = a.[m]
a, n, m:t

(a * 2 ^ n / 2 ^ n).[m] = a.[m]
now rewrite div_mul by order_nz. Qed.

forall a n m : t, n <= m -> (a * 2 ^ n).[m] = a.[m - n]

forall a n m : t, n <= m -> (a * 2 ^ n).[m] = a.[m - n]
a, n, m:t
H:n <= m

(a * 2 ^ n).[m] = a.[m - n]
a, n, m:t
H:n <= m

(a * 2 ^ n).[m - n + n] = a.[m - n]
now rewrite mul_pow2_bits_add. Qed.

forall a n m : t, m < n -> (a * 2 ^ n).[m] = false

forall a n m : t, m < n -> (a * 2 ^ n).[m] = false
a, n, m:t
H:m < n

(a * 2 ^ n).[m] = false
a, n, m:t
H:m < n

(a * 2 ^ n / 2 ^ m) mod 2 == 0
a, n, m:t
H:m < n

(a * 2 ^ (n - m + m) / 2 ^ m) mod 2 == 0
a, n, m:t
H:m < n

(a * 2 ^ (n - m) * 2 ^ m / 2 ^ m) mod 2 == 0
a, n, m:t
H:m < n

(a * 2 ^ (n - m)) mod 2 == 0
a, n, m:t
H:m < n

(a * 2 ^ S (P (n - m))) mod 2 == 0
a, n, m:t
H:m < n
n - m ~= 0
a, n, m:t
H:m < n

(a * (2 * 2 ^ P (n - m))) mod 2 == 0
a, n, m:t
H:m < n
0 <= P (n - m)
a, n, m:t
H:m < n
n - m ~= 0
a, n, m:t
H:m < n

0 <= P (n - m)
a, n, m:t
H:m < n
n - m ~= 0
a, n, m:t
H:m < n

0 < n - m
a, n, m:t
H:m < n
n - m ~= 0
a, n, m:t
H:n - m ~= 0

0 < n - m
a, n, m:t
H:m < n
n - m ~= 0
a, n, m:t
H:m < n

n - m ~= 0
now apply sub_gt. Qed.
Selecting the low part of a number can be done by a modulo

forall a n m : t, n <= m -> (a mod 2 ^ n).[m] = false

forall a n m : t, n <= m -> (a mod 2 ^ n).[m] = false
a, n, m:t
H:n <= m

(a mod 2 ^ n).[m] = false
a, n, m:t
H:n <= m
EQ:a mod 2 ^ n == 0

(a mod 2 ^ n).[m] = false
a, n, m:t
H:n <= m
LT:0 < a mod 2 ^ n
(a mod 2 ^ n).[m] = false
a, n, m:t
H:n <= m
LT:0 < a mod 2 ^ n

(a mod 2 ^ n).[m] = false
a, n, m:t
H:n <= m
LT:0 < a mod 2 ^ n

log2 (a mod 2 ^ n) < m
a, n, m:t
H:n <= m
LT:0 < a mod 2 ^ n

log2 (a mod 2 ^ n) < n
a, n, m:t
H:n <= m
LT:0 < a mod 2 ^ n

a mod 2 ^ n < 2 ^ n
apply mod_upper_bound; order_nz. Qed.

forall a n m : t, m < n -> (a mod 2 ^ n).[m] = a.[m]

forall a n m : t, m < n -> (a mod 2 ^ n).[m] = a.[m]
a, n, m:t
H:m < n

(a mod 2 ^ n).[m] = a.[m]
a, n, m:t
H:m < n

((a mod 2 ^ n / 2 ^ m) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

((a mod 2 ^ n / 2 ^ m + 2 ^ P (n - m) * (a / 2 ^ n) * 2) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

(((a mod 2 ^ n + 2 ^ P (n - m) * (a / 2 ^ n) * 2 * 2 ^ m) / 2 ^ m) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

(((a mod 2 ^ n + 2 ^ (n - m) * (a / 2 ^ n) * 2 ^ m) / 2 ^ m) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

(((a mod 2 ^ n + 2 ^ n * (a / 2 ^ n)) / 2 ^ m) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

((a / 2 ^ m) mod 2 =? 1) = a.[m]
a, n, m:t
H:m < n

a.[m] = ((a / 2 ^ m) mod 2 =? 1)
apply testbit_eqb. Qed.
We now prove that having the same bits implies equality. For that we use a notion of equality over functional streams of bits.
Definition eqf (f g:t -> bool) := forall n:t, f n = g n.


Equivalence eqf

Equivalence eqf
split; congruence. Qed. Local Infix "===" := eqf (at level 70, no associativity).

Proper (eq ==> eqf) testbit

Proper (eq ==> eqf) testbit
a, a':t
Ha:a == a'
n:t

a.[n] = a'.[n]
now rewrite Ha. Qed.
Only zero corresponds to the always-false stream.

forall a : t, (forall n : t, a.[n] = false) -> a == 0

forall a : t, (forall n : t, a.[n] = false) -> a == 0
a:t
H:forall n : t, a.[n] = false

a == 0
a:t
H:forall n : t, a.[n] = false
NEQ:a ~= 0

a == 0
a:t
H:forall n : t, a.[n] = false
NEQ:a.[log2 a] = true

a == 0
now rewrite H in NEQ. Qed.
If two numbers produce the same stream of bits, they are equal.

forall a b : t, testbit a === testbit b -> a == b

forall a b : t, testbit a === testbit b -> a == b
a:t

forall b : t, testbit a === testbit b -> a == b
a:t

(fun t0 : t => forall b : t, testbit t0 === testbit b -> t0 == b) a

forall n : t, 0 <= n -> (forall m : t, 0 <= m -> m < n -> forall b : t, testbit m === testbit b -> m == b) -> forall b : t, testbit n === testbit b -> n == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b

a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
EQ:a == 0

a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit 0 === testbit b
EQ:a == 0

0 == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit 0 === testbit b
EQ:a == 0

b == 0
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit 0 === testbit b
EQ:a == 0

forall n : t, b.[n] = false
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit 0 === testbit b
EQ:a == 0
n:t

b.[n] = false
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

a == b
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

2 * (a / 2) + a mod 2 == 2 * (b / 2) + b mod 2
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

2 * (a / 2) == 2 * (b / 2)
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

a / 2 == b / 2
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

a / 2 < a
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
testbit (a / 2) === testbit (b / 2)
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a

testbit (a / 2) === testbit (b / 2)
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
n:t

(a / 2).[n] = (b / 2).[n]
a:t
IH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0
b:t
H:testbit a === testbit b
LT:0 < a
n:t

a.[S n] = b.[S n]
apply H. Qed.

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

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

testbit a === testbit b -> a == b
a, b:t
a == b -> testbit a === testbit b
a, b:t

a == b -> testbit a === testbit b
intros EQ; now rewrite EQ. Qed. Hint Rewrite lxor_spec lor_spec land_spec ldiff_spec bits_0 : bitwise. Ltac bitwise := apply bits_inj; intros ?m; autorewrite with bitwise.
The streams of bits that correspond to a natural numbers are exactly the ones that are always 0 after some point

forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (exists n : t, f === testbit n) <-> (exists k : t, forall m : t, k <= m -> f m = false)

forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (exists n : t, f === testbit n) <-> (exists k : t, forall m : t, k <= m -> f m = false)
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f

(exists n : t, f === testbit n) <-> (exists k : t, forall m : t, k <= m -> f m = false)
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f

(exists n : t, f === testbit n) -> exists k : t, forall m : t, k <= m -> f m = false
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
a:t
H:f === testbit a

exists k : t, forall m : t, k <= m -> f m = false
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
a:t
H:f === testbit a

forall m : t, S (log2 a) <= m -> f m = false
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
a:t
H:f === testbit a
m:t
Hm:S (log2 a) <= m

f m = false
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
a:t
H:f === testbit a
m:t
Hm:log2 a < m

f m = false
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f

(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
k:t
Hk:forall m : t, k <= m -> f m = false

exists n : t, f === testbit n
k:t

forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit n

forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, 0 <= m -> f m = false) -> exists n : t, f === testbit n

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
H0:forall m : t, 0 <= m -> f m = false

exists n : t, f === testbit n

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
H0:forall m : t, 0 <= m -> f m = false

f === testbit 0

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
H0:forall m0 : t, 0 <= m0 -> f m0 = false
m:t

f m = 0.[m]

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
H0:forall m0 : t, 0 <= m0 -> f m0 = false
m:t

0 <= m

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0

forall n : t, (forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, n <= m -> f m = false) -> exists n0 : t, f === testbit n0) -> forall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, S n <= m -> f m = false) -> exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false

exists n : t, f === testbit n
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false

Proper (eq ==> Logic.eq) (fun m : t => f (S m))
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
forall m : t, k <= m -> f (S m) = false
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n
exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false

forall m : t, k <= m -> f (S m) = false
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n
exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
m:t
Hm:k <= m

f (S m) = false
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n
exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n : t, f0 === testbit n
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
m:t
Hm:k <= m

S k <= S m
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n
exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n

exists n0 : t, f === testbit n0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m : t, S k <= m -> f m = false
n:t
Hn:(fun m : t => f (S m)) === testbit n

f === testbit (f 0 + 2 * n)
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m:t

f m = (f 0 + 2 * n).[m]
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m:t
Hm:m == 0

f 0 = (f 0 + 2 * n).[0]
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m, m':t
Hm:m == S m'
f (S m') = (f 0 + 2 * n).[S m']
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m:t
Hm:m == 0

(f 0 + 2 * n).[0] = f 0
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m, m':t
Hm:m == S m'
f (S m') = (f 0 + 2 * n).[S m']
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m, m':t
Hm:m == S m'

f (S m') = (f 0 + 2 * n).[S m']
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m, m':t
Hm:m == S m'

n.[m'] = ((f 0 + 2 * n) / 2).[m']
k:t
IH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0
f:t -> bool
Hf:Proper (eq ==> Logic.eq) f
Hk:forall m0 : t, S k <= m0 -> f m0 = false
n:t
Hn:(fun m0 : t => f (S m0)) === testbit n
m, m':t
Hm:m == S m'

2 ~= 0
order'. Qed.
Properties of shifts

forall a n m : t, (a >> n).[m] = a.[m + n]

forall a n m : t, (a >> n).[m] = a.[m + n]
a, n, m:t

(a >> n).[m] = a.[m + n]
a, n, m:t

0 <= m
apply le_0_l. Qed.

forall a n m : t, n <= m -> (a << n).[m] = a.[m - n]

forall a n m : t, n <= m -> (a << n).[m] = a.[m - n]
a, n, m:t
H:n <= m

(a << n).[m] = a.[m - n]
a, n, m:t
H:n <= m

0 <= m
apply le_0_l. Qed.

forall a n : t, a >> n == a / 2 ^ n

forall a n : t, a >> n == a / 2 ^ n
a, n:t

a >> n == a / 2 ^ n
a, n, m:t

(a >> n).[m] = (a / 2 ^ n).[m]
a, n, m:t

a.[m + n] = (a / 2 ^ n).[m]
a, n, m:t

(a / 2 ^ n).[m] = a.[m + n]
apply div_pow2_bits. Qed.

forall a n : t, a << n == a * 2 ^ n

forall a n : t, a << n == a * 2 ^ n
a, n:t

a << n == a * 2 ^ n
a, n, m:t

(a << n).[m] = (a * 2 ^ n).[m]
a, n, m:t
H:n <= m

(a << n).[m] = (a * 2 ^ n).[m]
a, n, m:t
H:m < n
(a << n).[m] = (a * 2 ^ n).[m]
a, n, m:t
H:m < n

(a << n).[m] = (a * 2 ^ n).[m]
now rewrite shiftl_spec_low, mul_pow2_bits_low. Qed.

forall a n m : t, (a << n).[m + n] = a.[m]

forall a n m : t, (a << n).[m + n] = a.[m]
a, n, m:t

(a << n).[m + n] = a.[m]
now rewrite shiftl_mul_pow2, mul_pow2_bits_add. Qed.

Proper (eq ==> eq ==> eq) shiftr

Proper (eq ==> eq ==> eq) shiftr
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

a >> b == a' >> b'
now rewrite 2 shiftr_div_pow2, Ha, Hb. Qed.

Proper (eq ==> eq ==> eq) shiftl

Proper (eq ==> eq ==> eq) shiftl
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

a << b == a' << b'
now rewrite 2 shiftl_mul_pow2, Ha, Hb. Qed.

forall a n m : t, (a << n) << m == a << (n + m)

forall a n m : t, (a << n) << m == a << (n + m)
a, n, m:t

(a << n) << m == a << (n + m)
now rewrite !shiftl_mul_pow2, pow_add_r, mul_assoc. Qed.

forall a n m : t, (a >> n) >> m == a >> (n + m)

forall a n m : t, (a >> n) >> m == a >> (n + m)
a, n, m:t

(a >> n) >> m == a >> (n + m)
now rewrite !shiftr_div_pow2, pow_add_r, div_div by order_nz. Qed.

forall a n m : t, m <= n -> (a << n) >> m == a << (n - m)

forall a n m : t, m <= n -> (a << n) >> m == a << (n - m)
a, n, m:t
H:m <= n

(a << n) >> m == a << (n - m)
a, n, m:t
H:m <= n

a * 2 ^ n / 2 ^ m == a * 2 ^ (n - m)
a, n, m:t
H:m <= n

a * 2 ^ (n - m + m) / 2 ^ m == a * 2 ^ (n - m)
now rewrite pow_add_r, mul_assoc, div_mul by order_nz. Qed.

forall a n m : t, n <= m -> (a << n) >> m == a >> (m - n)

forall a n m : t, n <= m -> (a << n) >> m == a >> (m - n)
a, n, m:t
H:n <= m

(a << n) >> m == a >> (m - n)
a, n, m:t
H:n <= m

a * 2 ^ n / 2 ^ m == a / 2 ^ (m - n)
a, n, m:t
H:n <= m

a * 2 ^ n / 2 ^ (m - n + n) == a / 2 ^ (m - n)
a, n, m:t
H:n <= m

a * 2 ^ n / (2 ^ n * 2 ^ (m - n)) == a / 2 ^ (m - n)
now rewrite <- div_div, div_mul by order_nz. Qed.
shifts and constants

forall n : t, 1 << n == 2 ^ n

forall n : t, 1 << n == 2 ^ n
n:t

1 << n == 2 ^ n
now rewrite shiftl_mul_pow2, mul_1_l. Qed.

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

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

a << 0 == a
a:t

a * 2 ^ 0 == a
now nzsimpl. Qed.

forall a : t, a >> 0 == a

forall a : t, a >> 0 == a
a:t

a >> 0 == a
a:t

a / 2 ^ 0 == a
now nzsimpl. Qed.

forall n : t, 0 << n == 0

forall n : t, 0 << n == 0
n:t

0 << n == 0
n:t

0 * 2 ^ n == 0
now nzsimpl. Qed.

forall n : t, 0 >> n == 0

forall n : t, 0 >> n == 0
n:t

0 >> n == 0
n:t

0 / 2 ^ n == 0
nzsimpl; order_nz. Qed.

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

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

a << n == 0 <-> a == 0
a, n:t

a * 2 ^ n == 0 <-> a == 0
a, n:t

a == 0 \/ 2 ^ n == 0 <-> a == 0
a, n:t

a == 0 \/ 2 ^ n == 0 -> a == 0
a, n:t
a == 0 -> a == 0 \/ 2 ^ n == 0
a, n:t
H:2 ^ n == 0

a == 0
a, n:t
a == 0 -> a == 0 \/ 2 ^ n == 0
a, n:t

a == 0 -> a == 0 \/ 2 ^ n == 0
a, n:t
H:a == 0

a == 0 \/ 2 ^ n == 0
now left. Qed.

forall a n : t, a >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < n

forall a n : t, a >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t

a >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t

a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0

a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0

0 < 2 ^ n <-> 0 == 0 \/ 0 < 0 /\ log2 0 < n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0

0 < 2 ^ n -> 0 == 0 \/ 0 < 0 /\ log2 0 < n
a, n:t
EQ:a == 0
0 == 0 \/ 0 < 0 /\ log2 0 < n -> 0 < 2 ^ n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0

0 == 0 \/ 0 < 0 /\ log2 0 < n -> 0 < 2 ^ n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0

0 < 2 ^ n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
EQ:a == 0
H:2 ~= 0

0 < 2 ^ n
a, n:t
LT:0 < a
a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
LT:0 < a

a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
LT:0 < a

log2 a < n <-> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
LT:0 < a

log2 a < n -> a == 0 \/ 0 < a /\ log2 a < n
a, n:t
LT:0 < a
a == 0 \/ 0 < a /\ log2 a < n -> log2 a < n
a, n:t
LT:0 < a

a == 0 \/ 0 < a /\ log2 a < n -> log2 a < n
intros [H|[_ H]]; now order. Qed.

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

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

a >> n == 0
a, n:t
H:log2 a < n

a == 0 \/ 0 < a /\ log2 a < n
a, n:t
H:log2 a < n
EQ:a == 0

a == 0 \/ 0 < a /\ log2 a < n
a, n:t
H:log2 a < n
LT:0 < a
a == 0 \/ 0 < a /\ log2 a < n
a, n:t
H:log2 a < n
LT:0 < a

a == 0 \/ 0 < a /\ log2 a < n
right; now split. Qed.
Properties of div2.

forall a : t, div2 a == a / 2

forall a : t, div2 a == a / 2
a:t

div2 a == a / 2
a:t

a / 2 ^ 1 == a / 2
now nzsimpl. Qed.

Proper (eq ==> eq) div2

Proper (eq ==> eq) div2
a, a':t
Ha:a == a'

div2 a == div2 a'
now rewrite 2 div2_div, Ha. Qed.

forall a : t, a == 2 * div2 a + odd a

forall a : t, a == 2 * div2 a + odd a
a:t

a == 2 * div2 a + odd a
a:t

a == 2 * (a / 2) + a mod 2
a:t

2 ~= 0
order'. Qed.
Properties of lxor and others, directly deduced from properties of xorb and others.

Proper (eq ==> eq ==> eq) lxor

Proper (eq ==> eq ==> eq) lxor
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

lxor a b == lxor a' b'
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'
m:t

xorb a.[m] b.[m] = xorb a'.[m] b'.[m]
now rewrite Ha, Hb. Qed.

Proper (eq ==> eq ==> eq) land

Proper (eq ==> eq ==> eq) land
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

land a b == land a' b'
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'
m:t

a.[m] && b.[m] = a'.[m] && b'.[m]
now rewrite Ha, Hb. Qed.

Proper (eq ==> eq ==> eq) lor

Proper (eq ==> eq ==> eq) lor
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

lor a b == lor a' b'
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'
m:t

a.[m] || b.[m] = a'.[m] || b'.[m]
now rewrite Ha, Hb. Qed.

Proper (eq ==> eq ==> eq) ldiff

Proper (eq ==> eq ==> eq) ldiff
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'

ldiff a b == ldiff a' b'
a, a':t
Ha:a == a'
b, b':t
Hb:b == b'
m:t

a.[m] && negb b.[m] = a'.[m] && negb b'.[m]
now rewrite Ha, Hb. Qed.

forall a a' : t, lxor a a' == 0 -> a == a'

forall a a' : t, lxor a a' == 0 -> a == a'
a, a':t
H:lxor a a' == 0

a == a'
a, a':t
H:lxor a a' == 0
m:t

a.[m] = a'.[m]
a, a':t
H:lxor a a' == 0
m:t

xorb a.[m] a'.[m] = false
now rewrite <- lxor_spec, H, bits_0. Qed.

forall a : t, lxor a a == 0

forall a : t, lxor a a == 0
a:t

lxor a a == 0
a, m:t

xorb a.[m] a.[m] = false
apply xorb_nilpotent. Qed.

forall a a' : t, lxor a a' == 0 <-> a == a'

forall a a' : t, lxor a a' == 0 <-> a == a'
a, a':t

lxor a a' == 0 -> a == a'
a, a':t
a == a' -> lxor a a' == 0
a, a':t

a == a' -> lxor a a' == 0
intros EQ; rewrite EQ; apply lxor_nilpotent. Qed.

forall a : t, lxor 0 a == a

forall a : t, lxor 0 a == a
a:t

lxor 0 a == a
a, m:t

xorb false a.[m] = a.[m]
apply xorb_false_l. Qed.

forall a : t, lxor a 0 == a

forall a : t, lxor a 0 == a
a:t

lxor a 0 == a
a, m:t

xorb a.[m] false = a.[m]
apply xorb_false_r. Qed.

forall a b : t, lxor a b == lxor b a

forall a b : t, lxor a b == lxor b a
a, b:t

lxor a b == lxor b a
a, b, m:t

xorb a.[m] b.[m] = xorb b.[m] a.[m]
apply xorb_comm. Qed.

forall a b c : t, lxor (lxor a b) c == lxor a (lxor b c)

forall a b c : t, lxor (lxor a b) c == lxor a (lxor b c)
a, b, c:t

lxor (lxor a b) c == lxor a (lxor b c)
a, b, c, m:t

xorb (xorb a.[m] b.[m]) c.[m] = xorb a.[m] (xorb b.[m] c.[m])
apply xorb_assoc. Qed.

forall a : t, lor 0 a == a

forall a : t, lor 0 a == a
a:t

lor 0 a == a
a, m:t

false || a.[m] = a.[m]
trivial. Qed.

forall a : t, lor a 0 == a

forall a : t, lor a 0 == a
a:t

lor a 0 == a
a, m:t

a.[m] || false = a.[m]
apply orb_false_r. Qed.

forall a b : t, lor a b == lor b a

forall a b : t, lor a b == lor b a
a, b:t

lor a b == lor b a
a, b, m:t

a.[m] || b.[m] = b.[m] || a.[m]
apply orb_comm. Qed.

forall a b c : t, lor a (lor b c) == lor (lor a b) c

forall a b c : t, lor a (lor b c) == lor (lor a b) c
a, b, c:t

lor a (lor b c) == lor (lor a b) c
a, b, c, m:t

a.[m] || (b.[m] || c.[m]) = a.[m] || b.[m] || c.[m]
apply orb_assoc. Qed.

forall a : t, lor a a == a

forall a : t, lor a a == a
a:t

lor a a == a
a, m:t

a.[m] || a.[m] = a.[m]
apply orb_diag. Qed.

forall a b : t, lor a b == 0 -> a == 0

forall a b : t, lor a b == 0 -> a == 0
a, b:t
H:lor a b == 0

a == 0
a, b:t
H:lor a b == 0
m:t

a.[m] = false
a, b:t
H:lor a b == 0
m:t

a.[m] || b.[m] = false
now rewrite <- lor_spec, H, bits_0. Qed.

forall a b : t, lor a b == 0 <-> a == 0 /\ b == 0

forall a b : t, lor a b == 0 <-> a == 0 /\ b == 0
a, b:t

lor a b == 0 <-> a == 0 /\ b == 0
a, b:t

lor a b == 0 -> a == 0 /\ b == 0
a, b:t
a == 0 /\ b == 0 -> lor a b == 0
a, b:t
H:lor a b == 0

a == 0
a, b:t
H:lor a b == 0
b == 0
a, b:t
a == 0 /\ b == 0 -> lor a b == 0
a, b:t
H:lor a b == 0

b == 0
a, b:t
a == 0 /\ b == 0 -> lor a b == 0
a, b:t
H:lor b a == 0

b == 0
a, b:t
a == 0 /\ b == 0 -> lor a b == 0
a, b:t

a == 0 /\ b == 0 -> lor a b == 0
a, b:t
EQ:a == 0
EQ':b == 0

lor a b == 0
now rewrite EQ, lor_0_l. Qed.

forall a : t, land 0 a == 0

forall a : t, land 0 a == 0
a:t

land 0 a == 0
a, m:t

false && a.[m] = false
trivial. Qed.

forall a : t, land a 0 == 0

forall a : t, land a 0 == 0
a:t

land a 0 == 0
a, m:t

a.[m] && false = false
apply andb_false_r. Qed.

forall a b : t, land a b == land b a

forall a b : t, land a b == land b a
a, b:t

land a b == land b a
a, b, m:t

a.[m] && b.[m] = b.[m] && a.[m]
apply andb_comm. Qed.

forall a b c : t, land a (land b c) == land (land a b) c

forall a b c : t, land a (land b c) == land (land a b) c
a, b, c:t

land a (land b c) == land (land a b) c
a, b, c, m:t

a.[m] && (b.[m] && c.[m]) = a.[m] && b.[m] && c.[m]
apply andb_assoc. Qed.

forall a : t, land a a == a

forall a : t, land a a == a
a:t

land a a == a
a, m:t

a.[m] && a.[m] = a.[m]
apply andb_diag. Qed.

forall a : t, ldiff 0 a == 0

forall a : t, ldiff 0 a == 0
a:t

ldiff 0 a == 0
a, m:t

false && negb a.[m] = false
trivial. Qed.

forall a : t, ldiff a 0 == a

forall a : t, ldiff a 0 == a
a:t

ldiff a 0 == a
a, m:t

a.[m] && negb false = a.[m]
now rewrite andb_true_r. Qed.

forall a : t, ldiff a a == 0

forall a : t, ldiff a a == 0
a:t

ldiff a a == 0
a, m:t

a.[m] && negb a.[m] = false
apply andb_negb_r. Qed.

forall a b c : t, lor (land a b) c == land (lor a c) (lor b c)

forall a b c : t, lor (land a b) c == land (lor a c) (lor b c)
a, b, c:t

lor (land a b) c == land (lor a c) (lor b c)
a, b, c, m:t

a.[m] && b.[m] || c.[m] = (a.[m] || c.[m]) && (b.[m] || c.[m])
apply orb_andb_distrib_l. Qed.

forall a b c : t, lor a (land b c) == land (lor a b) (lor a c)

forall a b c : t, lor a (land b c) == land (lor a b) (lor a c)
a, b, c:t

lor a (land b c) == land (lor a b) (lor a c)
a, b, c, m:t

a.[m] || b.[m] && c.[m] = (a.[m] || b.[m]) && (a.[m] || c.[m])
apply orb_andb_distrib_r. Qed.

forall a b c : t, land (lor a b) c == lor (land a c) (land b c)

forall a b c : t, land (lor a b) c == lor (land a c) (land b c)
a, b, c:t

land (lor a b) c == lor (land a c) (land b c)
a, b, c, m:t

(a.[m] || b.[m]) && c.[m] = a.[m] && c.[m] || b.[m] && c.[m]
apply andb_orb_distrib_l. Qed.

forall a b c : t, land a (lor b c) == lor (land a b) (land a c)

forall a b c : t, land a (lor b c) == lor (land a b) (land a c)
a, b, c:t

land a (lor b c) == lor (land a b) (land a c)
a, b, c, m:t

a.[m] && (b.[m] || c.[m]) = a.[m] && b.[m] || a.[m] && c.[m]
apply andb_orb_distrib_r. Qed.

forall a b c : t, ldiff (ldiff a b) c == ldiff a (lor b c)

forall a b c : t, ldiff (ldiff a b) c == ldiff a (lor b c)
a, b, c:t

ldiff (ldiff a b) c == ldiff a (lor b c)
a, b, c, m:t

a.[m] && negb b.[m] && negb c.[m] = a.[m] && negb (b.[m] || c.[m])
now rewrite negb_orb, andb_assoc. Qed.

forall a b : t, lor (ldiff a b) (land a b) == a

forall a b : t, lor (ldiff a b) (land a b) == a
a, b:t

lor (ldiff a b) (land a b) == a
a, b, m:t

a.[m] && negb b.[m] || a.[m] && b.[m] = a.[m]
now rewrite <- andb_orb_distrib_r, orb_comm, orb_negb_r, andb_true_r. Qed.

forall a b : t, land (ldiff a b) b == 0

forall a b : t, land (ldiff a b) b == 0
a, b:t

land (ldiff a b) b == 0
a, b, m:t

a.[m] && negb b.[m] && b.[m] = false
now rewrite <-andb_assoc, (andb_comm (negb _)), andb_negb_r, andb_false_r. Qed.
Properties of setbit and clearbit
Definition setbit a n := lor a (1<<n).
Definition clearbit a n := ldiff a (1<<n).


forall a n : t, setbit a n == lor a (2 ^ n)

forall a n : t, setbit a n == lor a (2 ^ n)
a, n:t

setbit a n == lor a (2 ^ n)
a, n:t

lor a (1 << n) == lor a (2 ^ n)
now rewrite shiftl_1_l. Qed.

forall a n : t, clearbit a n == ldiff a (2 ^ n)

forall a n : t, clearbit a n == ldiff a (2 ^ n)
a, n:t

clearbit a n == ldiff a (2 ^ n)
a, n:t

ldiff a (1 << n) == ldiff a (2 ^ n)
now rewrite shiftl_1_l. Qed.

Proper (eq ==> eq ==> eq) setbit

Proper (eq ==> eq ==> eq) setbit

Proper (eq ==> eq ==> eq) (fun a n : t => lor a (1 << n))
solve_proper. Qed.

Proper (eq ==> eq ==> eq) clearbit

Proper (eq ==> eq ==> eq) clearbit

Proper (eq ==> eq ==> eq) (fun a n : t => ldiff a (1 << n))
solve_proper. Qed.

forall n : t, (2 ^ n).[n] = true

forall n : t, (2 ^ n).[n] = true
n:t

(2 ^ n).[n] = true
n:t

(1 * 2 ^ n).[n] = true
n:t

(1 * 2 ^ n).[0 + n] = true
now rewrite mul_pow2_bits_add, bit0_odd, odd_1. Qed.

forall n m : t, n ~= m -> (2 ^ n).[m] = false

forall n m : t, n ~= m -> (2 ^ n).[m] = false
n, m:t
H:n ~= m

(2 ^ n).[m] = false
n, m:t
H:n ~= m

(1 * 2 ^ n).[m] = false
n, m:t
H:n ~= m
H0:n <= m

(1 * 2 ^ n).[m] = false
n, m:t
H:n ~= m
H0:m < n
(1 * 2 ^ n).[m] = false
n, m:t
H:n ~= m
H0:n <= m

1.[m - n] = false
n, m:t
H:n ~= m
H0:m < n
(1 * 2 ^ n).[m] = false
n, m:t
H:n ~= m
H0:n <= m

1.[S (P (m - n))] = false
n, m:t
H:n ~= m
H0:m < n
(1 * 2 ^ n).[m] = false
n, m:t
H:n ~= m
H0:m < n

(1 * 2 ^ n).[m] = false
rewrite mul_pow2_bits_low; trivial. Qed.

forall n m : t, (2 ^ n).[m] = (n =? m)

forall n m : t, (2 ^ n).[m] = (n =? m)
n, m:t

(2 ^ n).[m] = (n =? m)
n, m:t

(2 ^ n).[m] = true <-> (n =? m) = true
n, m:t

(2 ^ n).[m] = true <-> n == m
n, m:t

(2 ^ n).[m] = true -> n == m
n, m:t
n == m -> (2 ^ n).[m] = true
n, m:t
H:n == m

(2 ^ n).[m] = true -> n == m
n, m:t
H:n ~= m
(2 ^ n).[m] = true -> n == m
n, m:t
n == m -> (2 ^ n).[m] = true
n, m:t
H:n ~= m

(2 ^ n).[m] = true -> n == m
n, m:t
n == m -> (2 ^ n).[m] = true
n, m:t

n == m -> (2 ^ n).[m] = true
n, m:t
EQ:n == m

(2 ^ n).[m] = true
n, m:t
EQ:n == m

(2 ^ m).[m] = true
apply pow2_bits_true. Qed.

forall a n m : t, (setbit a n).[m] = (n =? m) || a.[m]

forall a n m : t, (setbit a n).[m] = (n =? m) || a.[m]
a, n, m:t

(setbit a n).[m] = (n =? m) || a.[m]
now rewrite setbit_spec', lor_spec, pow2_bits_eqb, orb_comm. Qed.

forall a n m : t, (setbit a n).[m] = true <-> n == m \/ a.[m] = true

forall a n m : t, (setbit a n).[m] = true <-> n == m \/ a.[m] = true
a, n, m:t

(setbit a n).[m] = true <-> n == m \/ a.[m] = true
now rewrite setbit_eqb, orb_true_iff, eqb_eq. Qed.

forall a n : t, (setbit a n).[n] = true

forall a n : t, (setbit a n).[n] = true
a, n:t

(setbit a n).[n] = true
a, n:t

n == n \/ a.[n] = true
now left. Qed.

forall a n m : t, n ~= m -> (setbit a n).[m] = a.[m]

forall a n m : t, n ~= m -> (setbit a n).[m] = a.[m]
a, n, m:t
H:n ~= m

(setbit a n).[m] = a.[m]
a, n, m:t
H:n ~= m

(n =? m) || a.[m] = a.[m]
a, n, m:t
H:(n =? m) <> true

(n =? m) || a.[m] = a.[m]
a, n, m:t
H:(n =? m) = false

(n =? m) || a.[m] = a.[m]
now rewrite H. Qed.

forall a n m : t, (clearbit a n).[m] = a.[m] && negb (n =? m)

forall a n m : t, (clearbit a n).[m] = a.[m] && negb (n =? m)
a, n, m:t

(clearbit a n).[m] = a.[m] && negb (n =? m)
now rewrite clearbit_spec', ldiff_spec, pow2_bits_eqb. Qed.

forall a n m : t, (clearbit a n).[m] = true <-> a.[m] = true /\ n ~= m

forall a n m : t, (clearbit a n).[m] = true <-> a.[m] = true /\ n ~= m
a, n, m:t

(clearbit a n).[m] = true <-> a.[m] = true /\ n ~= m
a, n, m:t

a.[m] = true /\ negb (n =? m) = true <-> a.[m] = true /\ (n =? m) <> true
now rewrite negb_true_iff, not_true_iff_false. Qed.

forall a n : t, (clearbit a n).[n] = false

forall a n : t, (clearbit a n).[n] = false
a, n:t

(clearbit a n).[n] = false
a, n:t

a.[n] && negb true = false
apply andb_false_r. Qed.

forall a n m : t, n ~= m -> (clearbit a n).[m] = a.[m]

forall a n m : t, n ~= m -> (clearbit a n).[m] = a.[m]
a, n, m:t
H:n ~= m

(clearbit a n).[m] = a.[m]
a, n, m:t
H:n ~= m

a.[m] && negb (n =? m) = a.[m]
a, n, m:t
H:(n =? m) <> true

a.[m] && negb (n =? m) = a.[m]
a, n, m:t
H:(n =? m) = false

a.[m] && negb (n =? m) = a.[m]
a, n, m:t
H:(n =? m) = false

a.[m] && negb false = a.[m]
apply andb_true_r. Qed.
Shifts of bitwise operations

forall a b n : t, lxor a b << n == lxor (a << n) (b << n)

forall a b n : t, lxor a b << n == lxor (a << n) (b << n)
a, b, n:t

lxor a b << n == lxor (a << n) (b << n)
a, b, n, m:t

(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]
a, b, n, m:t
H:n <= m

(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]
a, b, n, m:t
H:m < n
(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]
a, b, n, m:t
H:m < n

(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]
now rewrite !shiftl_spec_low. Qed.

forall a b n : t, lxor a b >> n == lxor (a >> n) (b >> n)

forall a b n : t, lxor a b >> n == lxor (a >> n) (b >> n)
a, b, n:t

lxor a b >> n == lxor (a >> n) (b >> n)
a, b, n, m:t

(lxor a b >> n).[m] = xorb (a >> n).[m] (b >> n).[m]
now rewrite !shiftr_spec', lxor_spec. Qed.

forall a b n : t, land a b << n == land (a << n) (b << n)

forall a b n : t, land a b << n == land (a << n) (b << n)
a, b, n:t

land a b << n == land (a << n) (b << n)
a, b, n, m:t

(land a b << n).[m] = (a << n).[m] && (b << n).[m]
a, b, n, m:t
H:n <= m

(land a b << n).[m] = (a << n).[m] && (b << n).[m]
a, b, n, m:t
H:m < n
(land a b << n).[m] = (a << n).[m] && (b << n).[m]
a, b, n, m:t
H:m < n

(land a b << n).[m] = (a << n).[m] && (b << n).[m]
now rewrite !shiftl_spec_low. Qed.

forall a b n : t, land a b >> n == land (a >> n) (b >> n)

forall a b n : t, land a b >> n == land (a >> n) (b >> n)
a, b, n:t

land a b >> n == land (a >> n) (b >> n)
a, b, n, m:t

(land a b >> n).[m] = (a >> n).[m] && (b >> n).[m]
now rewrite !shiftr_spec', land_spec. Qed.

forall a b n : t, lor a b << n == lor (a << n) (b << n)

forall a b n : t, lor a b << n == lor (a << n) (b << n)
a, b, n:t

lor a b << n == lor (a << n) (b << n)
a, b, n, m:t

(lor a b << n).[m] = (a << n).[m] || (b << n).[m]
a, b, n, m:t
H:n <= m

(lor a b << n).[m] = (a << n).[m] || (b << n).[m]
a, b, n, m:t
H:m < n
(lor a b << n).[m] = (a << n).[m] || (b << n).[m]
a, b, n, m:t
H:m < n

(lor a b << n).[m] = (a << n).[m] || (b << n).[m]
now rewrite !shiftl_spec_low. Qed.

forall a b n : t, lor a b >> n == lor (a >> n) (b >> n)

forall a b n : t, lor a b >> n == lor (a >> n) (b >> n)
a, b, n:t

lor a b >> n == lor (a >> n) (b >> n)
a, b, n, m:t

(lor a b >> n).[m] = (a >> n).[m] || (b >> n).[m]
now rewrite !shiftr_spec', lor_spec. Qed.

forall a b n : t, ldiff a b << n == ldiff (a << n) (b << n)

forall a b n : t, ldiff a b << n == ldiff (a << n) (b << n)
a, b, n:t

ldiff a b << n == ldiff (a << n) (b << n)
a, b, n, m:t

(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]
a, b, n, m:t
H:n <= m

(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]
a, b, n, m:t
H:m < n
(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]
a, b, n, m:t
H:m < n

(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]
now rewrite !shiftl_spec_low. Qed.

forall a b n : t, ldiff a b >> n == ldiff (a >> n) (b >> n)

forall a b n : t, ldiff a b >> n == ldiff (a >> n) (b >> n)
a, b, n:t

ldiff a b >> n == ldiff (a >> n) (b >> n)
a, b, n, m:t

(ldiff a b >> n).[m] = (a >> n).[m] && negb (b >> n).[m]
now rewrite !shiftr_spec', ldiff_spec. Qed.
We cannot have a function complementing all bits of a number, otherwise it would have an infinity of bit 1. Nonetheless, we can design a bounded complement
Definition ones n := P (1 << n).

Definition lnot a n := lxor a (ones n).


Proper (eq ==> eq) ones

Proper (eq ==> eq) ones

Proper (eq ==> eq) (fun n : t => P (1 << n))
solve_proper. Qed.

Proper (eq ==> eq ==> eq) lnot

Proper (eq ==> eq ==> eq) lnot

Proper (eq ==> eq ==> eq) (fun a n : t => lxor a (ones n))
solve_proper. Qed.

forall n : t, ones n == P (2 ^ n)

forall n : t, ones n == P (2 ^ n)
intros; unfold ones; now rewrite shiftl_1_l. Qed.

forall n m : t, ones (m + n) == 2 ^ m * ones n + ones m

forall n m : t, ones (m + n) == 2 ^ m * ones n + ones m
n, m:t

ones (m + n) == 2 ^ m * ones n + ones m
n, m:t

P (2 ^ (m + n)) == 2 ^ m * P (2 ^ n) + P (2 ^ m)
n, m:t

2 ^ (m + n) - 1 == 2 ^ (m + n) - 2 ^ m + (2 ^ m - 1)
n, m:t

2 ^ (m + n) - 1 == 2 ^ (m + n) - 1
n, m:t
2 ^ m <= 2 ^ (m + n)
n, m:t
1 <= 2 ^ m
n, m:t

2 ^ m <= 2 ^ (m + n)
n, m:t
1 <= 2 ^ m
n, m:t

2 ~= 0
n, m:t
m <= m + n
n, m:t
1 <= 2 ^ m
n, m:t

m <= m + n
n, m:t
1 <= 2 ^ m
n, m:t

m + 0 <= m + n
n, m:t
1 <= 2 ^ m
n, m:t

1 <= 2 ^ m
n, m:t

2 ^ 0 <= 2 ^ m
n, m:t

2 ~= 0
n, m:t
0 <= m
n, m:t

0 <= m
apply le_0_l. Qed.

forall n m : t, m <= n -> ones n / 2 ^ m == ones (n - m)

forall n m : t, m <= n -> ones n / 2 ^ m == ones (n - m)
n, m:t
H:m <= n

ones n / 2 ^ m == ones (n - m)
n, m:t
H:m <= n

ones (n - m) == ones n / 2 ^ m
n, m:t
H:m <= n

ones m < 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

P (2 ^ m) < 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

S (P (2 ^ m)) <= 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones (n - m + m) == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones (m + (n - m)) == 2 ^ m * ones (n - m) + ones m
apply ones_add. Qed.

forall n m : t, m <= n -> ones n mod 2 ^ m == ones m

forall n m : t, m <= n -> ones n mod 2 ^ m == ones m
n, m:t
H:m <= n

ones n mod 2 ^ m == ones m
n, m:t
H:m <= n

ones m == ones n mod 2 ^ m
n, m:t
H:m <= n

ones m < 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

P (2 ^ m) < 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

S (P (2 ^ m)) <= 2 ^ m
n, m:t
H:m <= n
ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones n == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones (n - m + m) == 2 ^ m * ones (n - m) + ones m
n, m:t
H:m <= n

ones (m + (n - m)) == 2 ^ m * ones (n - m) + ones m
apply ones_add. Qed.

forall n m : t, m < n -> (ones n).[m] = true

forall n m : t, m < n -> (ones n).[m] = true
n, m:t
H:m < n

(ones n).[m] = true
n, m:t
H:m < n

(ones n / 2 ^ m) mod 2 == 1
n, m:t
H:m < n

ones (n - m) mod 2 == 1
n, m:t
H:m < n

ones (n - m) mod 2 ^ 1 == 1
n, m:t
H:m < n

ones 1 == 1
n, m:t
H:m < n
1 <= n - m
n, m:t
H:m < n

P (2 ^ 1) == 1
n, m:t
H:m < n
1 <= n - m
n, m:t
H:m < n

1 <= n - m
n, m:t
H:m < n

1 + m <= n
n, m:t
H:m < n

S m <= n
now apply le_succ_l. Qed.

forall n m : t, n <= m -> (ones n).[m] = false

forall n m : t, n <= m -> (ones n).[m] = false
n, m:t
H:n <= m

(ones n).[m] = false
n, m:t
H:n <= m
EQ:n == 0

(P (2 ^ n)).[m] = false
n, m:t
H:n <= m
LT:0 < n
(P (2 ^ n)).[m] = false
n, m:t
H:n <= m
LT:0 < n

(P (2 ^ n)).[m] = false
n, m:t
H:n <= m
LT:0 < n

log2 (P (2 ^ n)) < m
n, m:t
H:n <= m
LT:0 < n

P n < m
rewrite <-le_succ_l, succ_pred; order. Qed.

forall n m : t, (ones n).[m] = true <-> m < n

forall n m : t, (ones n).[m] = true <-> m < n
n, m:t

(ones n).[m] = true <-> m < n
n, m:t

(ones n).[m] = true -> m < n
n, m:t
m < n -> (ones n).[m] = true
n, m:t
H:(ones n).[m] = true

m < n
n, m:t
m < n -> (ones n).[m] = true
n, m:t
H:(ones n).[m] = true

~ n <= m
n, m:t
m < n -> (ones n).[m] = true
n, m:t
H:(ones n).[m] = true
H':n <= m

False
n, m:t
m < n -> (ones n).[m] = true
n, m:t
H:(ones n).[m] = true
H':(ones n).[m] = false

False
n, m:t
m < n -> (ones n).[m] = true
n, m:t

m < n -> (ones n).[m] = true
apply ones_spec_low. Qed.

forall a n m : t, m < n -> (lnot a n).[m] = negb a.[m]

forall a n m : t, m < n -> (lnot a n).[m] = negb a.[m]
a, n, m:t
H:m < n

(lnot a n).[m] = negb a.[m]
a, n, m:t
H:m < n

(lxor a (ones n)).[m] = negb a.[m]
now rewrite lxor_spec, ones_spec_low. Qed.

forall a n m : t, n <= m -> (lnot a n).[m] = a.[m]

forall a n m : t, n <= m -> (lnot a n).[m] = a.[m]
a, n, m:t
H:n <= m

(lnot a n).[m] = a.[m]
a, n, m:t
H:n <= m

(lxor a (ones n)).[m] = a.[m]
now rewrite lxor_spec, ones_spec_high, xorb_false_r. Qed.

forall a n : t, lnot (lnot a n) n == a

forall a n : t, lnot (lnot a n) n == a
a, n:t

lnot (lnot a n) n == a
a, n, m:t

(lnot (lnot a n) n).[m] = a.[m]
a, n, m:t
H:n <= m

(lnot (lnot a n) n).[m] = a.[m]
a, n, m:t
H:m < n
(lnot (lnot a n) n).[m] = a.[m]
a, n, m:t
H:m < n

(lnot (lnot a n) n).[m] = a.[m]
now rewrite 2 lnot_spec_low, negb_involutive. Qed.

forall n : t, lnot 0 n == ones n

forall n : t, lnot 0 n == ones n
n:t

lnot 0 n == ones n
n:t

lxor 0 (ones n) == ones n
apply lxor_0_l. Qed.

forall n : t, lnot (ones n) n == 0

forall n : t, lnot (ones n) n == 0
n:t

lnot (ones n) n == 0
n:t

lxor (ones n) (ones n) == 0
apply lxor_nilpotent. Qed.
Bounded complement and other operations

forall a n : t, log2 a < n -> lor a (ones n) == ones n

forall a n : t, log2 a < n -> lor a (ones n) == ones n
a, n:t
H:log2 a < n

lor a (ones n) == ones n
a, n:t
H:log2 a < n
m:t

a.[m] || (ones n).[m] = (ones n).[m]
a, n:t
H:log2 a < n
m:t
H0:n <= m

a.[m] || (ones n).[m] = (ones n).[m]
a, n:t
H:log2 a < n
m:t
H0:m < n
a.[m] || (ones n).[m] = (ones n).[m]
a, n:t
H:log2 a < n
m:t
H0:n <= m

log2 a < m
a, n:t
H:log2 a < n
m:t
H0:m < n
a.[m] || (ones n).[m] = (ones n).[m]
a, n:t
H:log2 a < n
m:t
H0:m < n

a.[m] || (ones n).[m] = (ones n).[m]
now rewrite ones_spec_low, orb_true_r. Qed.

forall a n : t, land a (ones n) == a mod 2 ^ n

forall a n : t, land a (ones n) == a mod 2 ^ n
a, n:t

land a (ones n) == a mod 2 ^ n
a, n, m:t

a.[m] && (ones n).[m] = (a mod 2 ^ n).[m]
a, n, m:t
H:n <= m

a.[m] && (ones n).[m] = (a mod 2 ^ n).[m]
a, n, m:t
H:m < n
a.[m] && (ones n).[m] = (a mod 2 ^ n).[m]
a, n, m:t
H:m < n

a.[m] && (ones n).[m] = (a mod 2 ^ n).[m]
now rewrite ones_spec_low, mod_pow2_bits_low, andb_true_r. Qed.

forall a n : t, log2 a < n -> land a (ones n) == a

forall a n : t, log2 a < n -> land a (ones n) == a
a, n:t
H:log2 a < n

a mod 2 ^ n == a
a, n:t
H:log2 a < n

a < 2 ^ n
a, n:t
H:log2 a < n

log2 a < log2 (2 ^ n)
rewrite log2_pow2; trivial using le_0_l. Qed.

forall a n : t, ldiff a (ones n) == (a >> n) << n

forall a n : t, ldiff a (ones n) == (a >> n) << n
a, n:t

ldiff a (ones n) == (a >> n) << n
a, n, m:t

a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
a, n, m:t
H:n <= m

a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
a, n, m:t
H:m < n
a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
a, n, m:t
H:n <= m

a.[m] && negb false = a.[m - n + n]
a, n, m:t
H:m < n
a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
a, n, m:t
H:n <= m

a.[m] && negb false = a.[m]
a, n, m:t
H:m < n
a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
a, n, m:t
H:m < n

a.[m] && negb (ones n).[m] = ((a >> n) << n).[m]
now rewrite ones_spec_low, shiftl_spec_low, andb_false_r. Qed.

forall a n : t, log2 a < n -> ldiff a (ones n) == 0

forall a n : t, log2 a < n -> ldiff a (ones n) == 0
a, n:t
H:log2 a < n

ldiff a (ones n) == 0
a, n:t
H:log2 a < n
m:t

a.[m] && negb (ones n).[m] = false
a, n:t
H:log2 a < n
m:t
H0:n <= m

a.[m] && negb (ones n).[m] = false
a, n:t
H:log2 a < n
m:t
H0:m < n
a.[m] && negb (ones n).[m] = false
a, n:t
H:log2 a < n
m:t
H0:n <= m

log2 a < m
a, n:t
H:log2 a < n
m:t
H0:m < n
a.[m] && negb (ones n).[m] = false
a, n:t
H:log2 a < n
m:t
H0:m < n

a.[m] && negb (ones n).[m] = false
now rewrite ones_spec_low, andb_false_r. Qed.

forall a n : t, log2 a < n -> ldiff (ones n) a == lnot a n

forall a n : t, log2 a < n -> ldiff (ones n) a == lnot a n
a, n:t
H:log2 a < n

ldiff (ones n) a == lnot a n
a, n:t
H:log2 a < n
m:t

(ones n).[m] && negb a.[m] = (lnot a n).[m]
a, n:t
H:log2 a < n
m:t
H0:n <= m

(ones n).[m] && negb a.[m] = (lnot a n).[m]
a, n:t
H:log2 a < n
m:t
H0:m < n
(ones n).[m] && negb a.[m] = (lnot a n).[m]
a, n:t
H:log2 a < n
m:t
H0:n <= m

log2 a < m
a, n:t
H:log2 a < n
m:t
H0:m < n
(ones n).[m] && negb a.[m] = (lnot a n).[m]
a, n:t
H:log2 a < n
m:t
H0:m < n

(ones n).[m] && negb a.[m] = (lnot a n).[m]
now rewrite ones_spec_low, lnot_spec_low. Qed.

forall a n : t, lor a (lnot a n) == lor a (ones n)

forall a n : t, lor a (lnot a n) == lor a (ones n)
a, n:t

lor a (lnot a n) == lor a (ones n)
a, n, m:t

a.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]
a, n, m:t
H:n <= m

a.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]
a, n, m:t
H:m < n
a.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]
a, n, m:t
H:n <= m

a.[m] || a.[m] = a.[m] || false
a, n, m:t
H:m < n
a.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]
a, n, m:t
H:m < n

a.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]
a, n, m:t
H:m < n

a.[m] || negb a.[m] = a.[m] || true
now destruct a.[m]. Qed.

forall a n : t, log2 a < n -> lor a (lnot a n) == ones n

forall a n : t, log2 a < n -> lor a (lnot a n) == ones n
a, n:t
H:log2 a < n

lor a (lnot a n) == ones n
now rewrite lor_lnot_diag, lor_ones_low. Qed.

forall a n : t, land a (lnot a n) == ldiff a (ones n)

forall a n : t, land a (lnot a n) == ldiff a (ones n)
a, n:t

land a (lnot a n) == ldiff a (ones n)
a, n, m:t

a.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]
a, n, m:t
H:n <= m

a.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]
a, n, m:t
H:m < n
a.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]
a, n, m:t
H:n <= m

a.[m] && a.[m] = a.[m] && negb false
a, n, m:t
H:m < n
a.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]
a, n, m:t
H:m < n

a.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]
a, n, m:t
H:m < n

a.[m] && negb a.[m] = a.[m] && negb true
now destruct a.[m]. Qed.

forall a n : t, log2 a < n -> land a (lnot a n) == 0

forall a n : t, log2 a < n -> land a (lnot a n) == 0
a, n:t
H:log2 a < n

land a (lnot a n) == 0
now rewrite land_lnot_diag, ldiff_ones_r_low. Qed.

forall a b n : t, log2 a < n -> log2 b < n -> lnot (lor a b) n == land (lnot a n) (lnot b n)

forall a b n : t, log2 a < n -> log2 b < n -> lnot (lor a b) n == land (lnot a n) (lnot b n)
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n

lnot (lor a b) n == land (lnot a n) (lnot b n)
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t

(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 b < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m
log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n

(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]
now rewrite !lnot_spec_low, lor_spec, negb_orb. Qed.

forall a b n : t, log2 a < n -> log2 b < n -> lnot (land a b) n == lor (lnot a n) (lnot b n)

forall a b n : t, log2 a < n -> log2 b < n -> lnot (land a b) n == lor (lnot a n) (lnot b n)
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n

lnot (land a b) n == lor (lnot a n) (lnot b n)
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t

(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 b < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m
log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n

(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]
now rewrite !lnot_spec_low, land_spec, negb_andb. Qed.

forall a b n : t, log2 a < n -> ldiff a b == land a (lnot b n)

forall a b n : t, log2 a < n -> ldiff a b == land a (lnot b n)
a, b, n:t
Ha:log2 a < n

ldiff a b == land a (lnot b n)
a, b, n:t
Ha:log2 a < n
m:t

a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:n <= m

a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:m < n
a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:n <= m

false && negb b.[m] = false && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:n <= m
log2 a < m
a, b, n:t
Ha:log2 a < n
m:t
H:m < n
a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:n <= m

log2 a < m
a, b, n:t
Ha:log2 a < n
m:t
H:m < n
a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
a, b, n:t
Ha:log2 a < n
m:t
H:m < n

a.[m] && negb b.[m] = a.[m] && (lnot b n).[m]
rewrite !lnot_spec_low; trivial. Qed.

forall a b n : t, log2 a < n -> log2 b < n -> lnot (ldiff a b) n == lor (lnot a n) b

forall a b n : t, log2 a < n -> log2 b < n -> lnot (ldiff a b) n == lor (lnot a n) b
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n

lnot (ldiff a b) n == lor (lnot a n) b
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t

(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 b < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m
log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:n <= m

log2 a < m
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n
(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
a, b, n:t
Ha:log2 a < n
Hb:log2 b < n
m:t
H:m < n

(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]
now rewrite !lnot_spec_low, ldiff_spec, negb_andb, negb_involutive. Qed.

forall a b n : t, lxor (lnot a n) (lnot b n) == lxor a b

forall a b n : t, lxor (lnot a n) (lnot b n) == lxor a b
a, b, n:t

lxor (lnot a n) (lnot b n) == lxor a b
a, b, n, m:t

xorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]
a, b, n, m:t
H:n <= m

xorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]
a, b, n, m:t
H:m < n
xorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]
a, b, n, m:t
H:m < n

xorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]
rewrite !lnot_spec_low, xorb_negb_negb; trivial. Qed.

forall a b n : t, lnot (lxor a b) n == lxor (lnot a n) b

forall a b n : t, lnot (lxor a b) n == lxor (lnot a n) b
a, b, n:t

lnot (lxor a b) n == lxor (lnot a n) b
a, b, n, m:t

(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]
a, b, n, m:t
H:n <= m

(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]
a, b, n, m:t
H:m < n
(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]
a, b, n, m:t
H:m < n

(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]
rewrite !lnot_spec_low, lxor_spec, negb_xorb_l; trivial. Qed.

forall a b n : t, lnot (lxor a b) n == lxor a (lnot b n)

forall a b n : t, lnot (lxor a b) n == lxor a (lnot b n)
a, b, n:t

lnot (lxor a b) n == lxor a (lnot b n)
a, b, n, m:t

(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]
a, b, n, m:t
H:n <= m

(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]
a, b, n, m:t
H:m < n
(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]
a, b, n, m:t
H:m < n

(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]
rewrite !lnot_spec_low, lxor_spec, negb_xorb_r; trivial. Qed.

forall a b : t, land a b == 0 -> lxor a b == lor a b

forall a b : t, land a b == 0 -> lxor a b == lor a b
a, b:t
H:land a b == 0

lxor a b == lor a b
a, b:t
H:land a b == 0
m:t

xorb a.[m] b.[m] = a.[m] || b.[m]
a, b:t
H:land a b == 0
m:t
H0:a.[m] && b.[m] = false

xorb a.[m] b.[m] = a.[m] || b.[m]
now destruct a.[m], b.[m]. Qed.
Bitwise operations and log2

forall a n : t, a.[n] = true -> (forall m : t, n < m -> a.[m] = false) -> log2 a == n

forall a n : t, a.[n] = true -> (forall m : t, n < m -> a.[m] = false) -> log2 a == n
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false

log2 a == n
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:a == 0

log2 a == n
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a
log2 a == n
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a

log2 a == n
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a
LT:n < log2 a

False
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a
LT:log2 a < n
False
a, n:t
H:a.[n] = true
H':a.[log2 a] = false
Ha:0 < a
LT:n < log2 a

False
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a
LT:log2 a < n
False
a, n:t
H:a.[n] = true
H':forall m : t, n < m -> a.[m] = false
Ha:0 < a
LT:log2 a < n

False
now rewrite bits_above_log2 in H by order. Qed.

forall a n : t, log2 (a >> n) == log2 a - n

forall a n : t, log2 (a >> n) == log2 a - n
a, n:t

log2 (a >> n) == log2 a - n
a, n:t
Ha:a == 0

log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a

log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:log2 a < n

log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:n <= log2 a
log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:log2 a < n

0 == log2 a - n
a, n:t
Ha:0 < a
H:n <= log2 a
log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:log2 a < n

log2 a - n == 0
a, n:t
Ha:0 < a
H:n <= log2 a
log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:n <= log2 a

log2 (a >> n) == log2 a - n
a, n:t
Ha:0 < a
H:n <= log2 a

(a >> n).[log2 a - n] = true
a, n:t
Ha:0 < a
H:n <= log2 a
forall m : t, log2 a - n < m -> (a >> n).[m] = false
a, n:t
Ha:0 < a
H:n <= log2 a

forall m : t, log2 a - n < m -> (a >> n).[m] = false
a, n:t
Ha:0 < a
H:n <= log2 a
m:t
Hm:log2 a - n < m

(a >> n).[m] = false
a, n:t
Ha:0 < a
H:n <= log2 a
m:t
Hm:log2 a - n < m

a.[m + n] = false
a, n:t
Ha:0 < a
H:n <= log2 a
m:t
Hm:log2 a - n < m

log2 a < m + n
now apply lt_sub_lt_add_r. Qed.

forall a n : t, a ~= 0 -> log2 (a << n) == log2 a + n

forall a n : t, a ~= 0 -> log2 (a << n) == log2 a + n
a, n:t
Ha:a ~= 0

log2 (a << n) == log2 a + n
a, n:t
Ha:a ~= 0

log2 (a * 2 ^ n) == n + log2 a
a, n:t
Ha:a ~= 0

0 < a
a, n:t
Ha:a ~= 0
0 <= n
a, n:t
Ha:a ~= 0

0 <= n
apply le_0_l. Qed.

forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)

forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)

forall a b : t, a <= b -> log2 (lor a b) == log2 b
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b

log2 (lor a b) == log2 b
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:a == 0

log2 (lor a b) == log2 b
a, b:t
H:a <= b
Ha:0 < a
log2 (lor a b) == log2 b
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:0 < a

log2 (lor a b) == log2 b
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:0 < a

(lor a b).[log2 b] = true
a, b:t
H:a <= b
Ha:0 < a
forall m : t, log2 b < m -> (lor a b).[m] = false
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:0 < a

forall m : t, log2 b < m -> (lor a b).[m] = false
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:0 < a
m:t
Hm:log2 b < m

(lor a b).[m] = false
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
a, b:t
H:a <= b
Ha:0 < a
m:t
Hm:log2 b < m
H':log2 a <= log2 b

(lor a b).[m] = false
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b
forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 b

forall a b : t, log2 (lor a b) == max (log2 a) (log2 b)
(* main *)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t

log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:a <= b

log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:b <= a
log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:a <= b

log2 (lor a b) == log2 b
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:b <= a
log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:b <= a

log2 (lor a b) == max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:b <= a

log2 (lor a b) == log2 a
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0
a, b:t
H:b <= a

log2 (lor b a) == log2 a
now apply AUX. Qed.

forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)

forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)

forall a b : t, a <= b -> log2 (land a b) <= log2 a
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b

log2 (land a b) <= log2 a
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b

~ log2 a < log2 (land a b)
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 a < log2 (land a b)

False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
EQ:land a b == 0

False
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
NEQ:land a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 a < log2 0
EQ:land a b == 0

False
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
NEQ:land a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':a < 0
EQ:land a b == 0

False
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
NEQ:land a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
NEQ:land a b ~= 0

False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 a < log2 (land a b)
NEQ:land a b ~= 0

(land a b).[log2 (land a b)] = true -> False
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a
forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 a

forall a b : t, log2 (land a b) <= min (log2 a) (log2 b)
(* main *)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t

log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:a <= b

log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:b <= a
log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:a <= b

log2 (land a b) <= log2 a
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:b <= a
log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:b <= a

log2 (land a b) <= min (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:b <= a

log2 (land a b) <= log2 b
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0
a, b:t
H:b <= a

log2 (land b a) <= log2 b
now apply AUX. Qed.

forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)

forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)

forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b

log2 (lxor a b) <= log2 b
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b

~ log2 b < log2 (lxor a b)
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)

False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
EQ:lxor a b == 0

False
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 0
EQ:lxor a b == 0

False
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':b < 0
EQ:lxor a b == 0

False
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0
False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0

False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0

(lxor a b).[log2 (lxor a b)] = true -> False
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0

xorb false false = true -> False
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0
log2 a < log2 (lxor a b)
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0

log2 a < log2 (lxor a b)
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
a, b:t
H:a <= b
H':log2 b < log2 (lxor a b)
NEQ:lxor a b ~= 0

log2 a <= log2 b
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b
forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 b

forall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)
(* main *)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t

log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:a <= b

log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:b <= a
log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:a <= b

log2 (lxor a b) <= log2 b
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:b <= a
log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:b <= a

log2 (lxor a b) <= max (log2 a) (log2 b)
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:b <= a

log2 (lxor a b) <= log2 a
AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0
a, b:t
H:b <= a

log2 (lxor b a) <= log2 a
now apply AUX. Qed.
Bitwise operations and arithmetical operations
Notation xor3 a b c := (xorb (xorb a b) c).
Notation lxor3 a b c := (lxor (lxor a b) c).

Notation nextcarry a b c := ((a&&b) || (c && (a||b))).
Notation lnextcarry a b c := (lor (land a b) (land c (lor a b))).


forall a b : t, (a + b).[0] = xorb a.[0] b.[0]

forall a b : t, (a + b).[0] = xorb a.[0] b.[0]
a, b:t

(a + b).[0] = xorb a.[0] b.[0]
now rewrite !bit0_odd, odd_add. Qed.

forall a b c : t, (a + b + c).[0] = xor3 a.[0] b.[0] c.[0]

forall a b c : t, (a + b + c).[0] = xor3 a.[0] b.[0] c.[0]
a, b, c:t

(a + b + c).[0] = xor3 a.[0] b.[0] c.[0]
now rewrite !add_bit0. Qed.

forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0

forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0
H:1 + 1 == 2

forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0
H:1 + 1 == 2

(2 + 1) / 2 == 1
H:1 + 1 == 2

1 == (2 + 1) / 2
H:1 + 1 == 2

1 < 2
H:1 + 1 == 2
2 + 1 == 2 * 1 + 1
H:1 + 1 == 2

2 + 1 == 2 * 1 + 1
now nzsimpl'. Qed.

forall (a b : t) (c0 : bool), (a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0

forall (a b : t) (c0 : bool), (a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0
a, b:t
c0:bool

(a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0
a, b:t
c0:bool

(a + b + c0) / 2 == a / 2 + b / 2 + (a.[0] + b.[0] + c0) / 2
a, b:t
c0:bool

(a + b + c0) / 2 == (a.[0] + b.[0] + c0) / 2 + (a / 2 + b / 2)
a, b:t
c0:bool

(a + b + c0) / 2 == (a.[0] + b.[0] + c0 + (a / 2 + b / 2) * 2) / 2
a, b:t
c0:bool

a + b + c0 == a.[0] + b.[0] + c0 + (a / 2 + b / 2) * 2
a, b:t
c0:bool

a + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + a.[0] + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + a.[0] + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + a.[0] + (2 * div2 b + b.[0]) + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + a.[0] + (2 * div2 b + b.[0]) + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + 2 * div2 b + (a.[0] + b.[0]) + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
a, b:t
c0:bool

2 * div2 a + 2 * div2 b + (a.[0] + b.[0] + c0) == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
apply add_comm. Qed.
The main result concerning addition: we express the bits of the sum in term of bits of a and b and of some carry stream which is also recursively determined by another equation.

forall (a b : t) (c0 : bool), exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall (a b : t) (c0 : bool), exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
(* induction over some n such that [a<2^n] and [b<2^n] *)
a, b:t
c0:bool
n:=max a b:t

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

a < 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

a < 2 ^ a
a, b:t
c0:bool
n:=max a b:t
2 ^ a <= 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

2 ^ a <= 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

2 ~= 0
a, b:t
c0:bool
n:=max a b:t
a <= n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

a <= n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t

a <= max a b
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

b < 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

b < 2 ^ b
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
2 ^ b <= 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

2 ^ b <= 2 ^ n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

2 ~= 0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
b <= n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

b <= n
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n

b <= max a b
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n
exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:=max a b:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
n:t
Ha:a < 2 ^ n
Hb:b < 2 ^ n

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
n:t

forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall (a b : t) (c0 : bool), a < 2 ^ 0 -> b < 2 ^ 0 -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
(*base*)
a, b:t
c0:bool

a < 2 ^ 0 -> b < 2 ^ 0 -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool

a <= 0 -> b <= 0 -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
Ha:a <= 0
Hb:b <= 0

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
Ha:a <= 0
Hb:b <= 0

a + b + c0 == lxor3 a b c0 /\ c0 / 2 == lnextcarry a b c0 /\ c0.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
Ha:a <= 0
Hb:b <= 0

0 + b + c0 == lxor3 0 b c0 /\ c0 / 2 == lnextcarry 0 b c0 /\ c0.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
Ha:a <= 0
Hb:b <= 0

0 + 0 + c0 == lxor3 0 0 c0 /\ c0 / 2 == lnextcarry 0 0 c0 /\ c0.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
a, b:t
c0:bool
Ha:a <= 0
Hb:b <= 0

c0 == c0 /\ c0 / 2 == 0 /\ c0.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0

forall n : t, (forall (a b : t) (c0 : bool), a < 2 ^ n -> b < 2 ^ n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0) -> forall (a b : t) (c0 : bool), a < 2 ^ S n -> b < 2 ^ S n -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
(*step*)
n:t
IH:forall (a0 b0 : t) (c1 : bool), a0 < 2 ^ n -> b0 < 2 ^ n -> exists c : t, a0 + b0 + c1 == lxor3 a0 b0 c /\ c / 2 == lnextcarry a0 b0 c /\ c.[0] = c1
a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
n:t
IH:forall (a0 b0 : t) (c2 : bool), a0 < 2 ^ n -> b0 < 2 ^ n -> exists c : t, a0 + b0 + c2 == lxor3 a0 b0 c /\ c / 2 == lnextcarry a0 b0 c /\ c.[0] = c2
a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

a / 2 < 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
b / 2 < 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

2 ~= 0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
a < 2 * 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
b / 2 < 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

a < 2 * 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
b / 2 < 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

b / 2 < 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

2 ~= 0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
b < 2 * 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool

b < 2 * 2 ^ n
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

a + b + c0 == lxor3 a b (c0 + 2 * c) /\ (c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c) /\ (c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

a + b + c0 == lxor3 a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
(* - add *)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m:t

(a + b + c0).[m] = xor3 a.[m] b.[m] (c0 + 2 * c).[m]
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m:t

(a + b + c0).[0] = xor3 a.[0] b.[0] (c0 + 2 * c).[0]
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t
(a + b + c0).[S m'] = xor3 a.[S m'] b.[S m'] (c0 + 2 * c).[S m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

(a + b + c0).[S m'] = xor3 a.[S m'] b.[S m'] (c0 + 2 * c).[S m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

((a + b + c0) / 2).[m'] = (lxor3 (a / 2) (b / 2) ((c0 + 2 * c) / 2)).[m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

(a + b + c0) / 2 == lxor3 (a / 2) (b / 2) ((c0 + 2 * c) / 2)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

(a + b + c0) / 2 == a / 2 + b / 2 + c1
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
(* - carry *)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

c == lnextcarry a b (c0 + 2 * c)
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m:t

c.[m] = nextcarry a.[m] b.[m] (c0 + 2 * c).[m]
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m:t

c.[0] = nextcarry a.[0] b.[0] (c0 + 2 * c).[0]
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t
c.[S m'] = nextcarry a.[S m'] b.[S m'] (c0 + 2 * c).[S m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

c.[S m'] = nextcarry a.[S m'] b.[S m'] (c0 + 2 * c).[S m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

(lnextcarry (a / 2) (b / 2) c).[m'] = nextcarry (a / 2).[m'] (b / 2).[m'] ((c0 + 2 * c) / 2).[m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
m, m':t

nextcarry (a / 2).[m'] (b / 2).[m'] c.[m'] = nextcarry (a / 2).[m'] (b / 2).[m'] ((c0 + 2 * c) / 2).[m']
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1
(c0 + 2 * c).[0] = c0
n, a, b:t
c0:bool
Ha:a < 2 ^ S n
Hb:b < 2 ^ S n
c1:=nextcarry a.[0] b.[0] c0:bool
c:t
IH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) c
IH2:c / 2 == lnextcarry (a / 2) (b / 2) c
Hc:c.[0] = c1

(c0 + 2 * c).[0] = c0
(* - carry0 *) apply add_b2n_double_bit0. Qed.
Particular case : the second bit of an addition

forall a b : t, (a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])

forall a b : t, (a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b:t

(a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b, c:t
EQ1:a + b + false == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

(a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

(a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

(lxor3 a b c).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

xor3 a.[1] b.[1] c.[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

c.[1] = a.[0] && b.[0]
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

(lnextcarry a b c).[0] = a.[0] && b.[0]
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

nextcarry a.[0] b.[0] c.[0] = a.[0] && b.[0]
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

nextcarry a.[0] b.[0] false = a.[0] && b.[0]
a, b, c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

a.[0] && b.[0] || false = a.[0] && b.[0]
apply orb_false_r. Qed.
In an addition, there will be no carries iff there is no common bits in the numbers to add

forall a b c : t, c / 2 == lnextcarry a b c -> c.[0] = false -> c == 0 <-> land a b == 0

forall a b c : t, c / 2 == lnextcarry a b c -> c.[0] = false -> c == 0 <-> land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false

c == 0 <-> land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false

c == 0 -> land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false
land a b == 0 -> c == 0
a, b, c:t
H:0 / 2 == lnextcarry a b 0
H':0.[0] = false
EQ:c == 0

land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false
land a b == 0 -> c == 0
a, b, c:t
H:0 == lnextcarry a b 0
H':0.[0] = false
EQ:c == 0

land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false
land a b == 0 -> c == 0
a, b, c:t
H:lnextcarry a b 0 == 0
H':0.[0] = false
EQ:c == 0

land a b == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false
land a b == 0 -> c == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false

land a b == 0 -> c == 0
a, b, c:t
H:c / 2 == lnextcarry a b c
H':c.[0] = false
EQ:land a b == 0

c == 0
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0

c == 0
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0

forall n : t, c.[n] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0

c.[0] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0
forall n : t, c.[n] = false -> c.[S n] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0

forall n : t, c.[n] = false -> c.[S n] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0
n:t
IH:c.[n] = false

c.[S n] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0
n:t
IH:c.[n] = false

(land c (lor a b)).[n] = false
a, b, c:t
H:c / 2 == land c (lor a b)
H':c.[0] = false
EQ:land a b == 0
n:t
IH:c.[n] = false

c.[n] && (a.[n] || b.[n]) = false
now rewrite IH. Qed.
When there is no common bits, the addition is just a xor

forall a b : t, land a b == 0 -> a + b == lxor a b

forall a b : t, land a b == 0 -> a + b == lxor a b
a, b:t
H:land a b == 0

a + b == lxor a b
a, b:t
H:land a b == 0
c:t
EQ1:a + b + false == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

a + b == lxor a b
a, b:t
H:land a b == 0
c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

a + b == lxor a b
a, b:t
H:land a b == 0
c:t
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

lxor3 a b c == lxor a b
a, b, c:t
H:c == 0
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

lxor3 a b c == lxor a b
a, b, c:t
H:c == 0
EQ1:a + b == lxor3 a b c
EQ2:c / 2 == lnextcarry a b c
Hc:c.[0] = false

lxor3 a b 0 == lxor a b
now rewrite lxor_0_r. Qed.
A null ldiff implies being smaller

forall a b : t, ldiff a b == 0 -> a <= b

forall a b : t, ldiff a b == 0 -> a <= b

(forall n a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b) -> forall a b : t, ldiff a b == 0 -> a <= b

forall n a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b
H:forall n a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t

ldiff a b == 0 -> a <= b

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

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

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

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

a <= b

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

a <= b

forall n : t, (forall a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b) -> forall a b : t, a < 2 ^ S n -> ldiff a b == 0 -> a <= b
a, b:t
Ha:a <= 0
Ha':a == 0

a <= b

forall n : t, (forall a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b) -> forall a b : t, a < 2 ^ S n -> ldiff a b == 0 -> a <= b
a, b:t
Ha:a <= 0
Ha':a == 0

0 <= b

forall n : t, (forall a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b) -> forall a b : t, a < 2 ^ S n -> ldiff a b == 0 -> a <= b

forall n : t, (forall a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= b) -> forall a b : t, a < 2 ^ S n -> ldiff a b == 0 -> a <= b
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0

a <= b
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a <= b
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

2 * (a / 2) + a mod 2 <= 2 * (b / 2) + b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

2 * (a / 2) <= 2 * (b / 2)
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a / 2 <= b / 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a / 2 < 2 ^ n
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
ldiff (a / 2) (b / 2) == 0
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a < 2 * 2 ^ n
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
ldiff (a / 2) (b / 2) == 0
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

ldiff (a / 2) (b / 2) == 0
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

ldiff (a >> 1) (b >> 1) == 0
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0
a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a mod 2 <= b mod 2
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:ldiff a b == 0
NEQ:2 ~= 0

a.[0] <= b.[0]
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:testbit (ldiff a b) === testbit 0
NEQ:2 ~= 0

a.[0] <= b.[0]
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:(ldiff a b).[0] = 0.[0]
NEQ:2 ~= 0

a.[0] <= b.[0]
n:t
IH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0
a, b:t
Ha:a < 2 ^ S n
H:a.[0] && negb b.[0] = false
NEQ:2 ~= 0

a.[0] <= b.[0]
destruct a.[0], b.[0]; try discriminate; simpl; order'. Qed.
Subtraction can be a ldiff when the opposite ldiff is null.

forall a b : t, ldiff b a == 0 -> a - b == ldiff a b

forall a b : t, ldiff b a == 0 -> a - b == ldiff a b
a, b:t
H:ldiff b a == 0

a - b == ldiff a b
a, b:t
H:ldiff b a == 0

a - b + b == ldiff a b + b
a, b:t
H:ldiff b a == 0

a == ldiff a b + b
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:ldiff b a == 0

ldiff a b + b == a
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:ldiff b a == 0

lxor (ldiff a b) b == a
a, b:t
H:ldiff b a == 0
land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:ldiff b a == 0
m:t

xorb (a.[m] && negb b.[m]) b.[m] = a.[m]
a, b:t
H:ldiff b a == 0
land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:testbit (ldiff b a) === testbit 0
m:t

xorb (a.[m] && negb b.[m]) b.[m] = a.[m]
a, b:t
H:ldiff b a == 0
land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b, m:t
H:(ldiff b a).[m] = 0.[m]

xorb (a.[m] && negb b.[m]) b.[m] = a.[m]
a, b:t
H:ldiff b a == 0
land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b, m:t
H:b.[m] && negb a.[m] = false

xorb (a.[m] && negb b.[m]) b.[m] = a.[m]
a, b:t
H:ldiff b a == 0
land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:ldiff b a == 0

land (ldiff a b) b == 0
a, b:t
H:ldiff b a == 0
b <= a
a, b:t
H:ldiff b a == 0

b <= a
now apply ldiff_le. Qed.
We can express lnot in term of subtraction

forall a n : t, log2 a < n -> a + lnot a n == ones n

forall a n : t, log2 a < n -> a + lnot a n == ones n
a, n:t
H:log2 a < n

a + lnot a n == ones n
a, n:t
H:log2 a < n
H':land a (lnot a n) == 0

a + lnot a n == ones n
a, n:t
H:log2 a < n
H':land a (lnot a n) == 0

lor a (lnot a n) == ones n
now apply lor_lnot_diag_low. Qed.

forall a n : t, log2 a < n -> lnot a n == ones n - a

forall a n : t, log2 a < n -> lnot a n == ones n - a
a, n:t
H:log2 a < n

lnot a n == ones n - a
now rewrite <- (add_lnot_diag_low a n H), add_comm, add_sub. Qed.
Adding numbers with no common bits cannot lead to a much bigger number

forall a b n : t, land a b == 0 -> a < 2 ^ n -> b < 2 ^ n -> a + b < 2 ^ n

forall a b n : t, land a b == 0 -> a < 2 ^ n -> b < 2 ^ n -> a + b < 2 ^ n
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

a + b < 2 ^ n
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

lxor a b < 2 ^ n
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

2 ^ n ~= 0
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n
lxor a b / 2 ^ n == 0
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

lxor a b / 2 ^ n == 0
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

lxor (a / 2 ^ n) (b / 2 ^ n) == 0
a, b, n:t
H:land a b == 0
Ha:a < 2 ^ n
Hb:b < 2 ^ n

lxor 0 0 == 0
apply lxor_0_l. Qed.

forall a b n : t, land a b == 0 -> a mod 2 ^ n + b mod 2 ^ n < 2 ^ n

forall a b n : t, land a b == 0 -> a mod 2 ^ n + b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0

a mod 2 ^ n + b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0

land (a mod 2 ^ n) (b mod 2 ^ n) == 0
a, b, n:t
H:land a b == 0
a mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
m:t

(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = false
a, b, n:t
H:land a b == 0
a mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
m:t
H0:n <= m

(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = false
a, b, n:t
H:land a b == 0
m:t
H0:m < n
(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = false
a, b, n:t
H:land a b == 0
a mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
m:t
H0:m < n

(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = false
a, b, n:t
H:land a b == 0
a mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0

a mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0
b mod 2 ^ n < 2 ^ n
a, b, n:t
H:land a b == 0

b mod 2 ^ n < 2 ^ n
apply mod_upper_bound; order_nz. Qed. End NBitsProp.