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 ^ cforall a b c : t, a ~= 0 -> c <= b -> a ^ (b - c) == a ^ b / a ^ ca, b, c:tHa:a ~= 0H:c <= ba ^ (b - c) == a ^ b / a ^ ca, b, c:tHa:a ~= 0H:c <= b0 < a ^ ca, b, c:tHa:a ~= 0H:c <= ba ^ b == a ^ c * a ^ (b - c) + 0a, b, c:tHa:a ~= 0H:c <= ba ^ b == a ^ c * a ^ (b - c) + 0now rewrite <- pow_add_r, add_comm, sub_add. Qed.a, b, c:tHa:a ~= 0H:c <= ba ^ b == a ^ c * a ^ (b - c)forall a b c : t, b ~= 0 -> a mod b == 0 -> (a / b) ^ c == a ^ c / b ^ cforall a b c : t, b ~= 0 -> a mod b == 0 -> (a / b) ^ c == a ^ c / b ^ ca, b, c:tHb:b ~= 0H:a mod b == 0(a / b) ^ c == a ^ c / b ^ ca, b, c:tHb:b ~= 0H:a mod b == 00 < b ^ ca, b, c:tHb:b ~= 0H:a mod b == 0a ^ c == b ^ c * (a / b) ^ c + 0a, b, c:tHb:b ~= 0H:a mod b == 0a ^ c == b ^ c * (a / b) ^ c + 0a, b, c:tHb:b ~= 0H:a mod b == 0a ^ c == b ^ c * (a / b) ^ ca, b, c:tHb:b ~= 0H:a mod b == 0a ^ c == (b * (a / b)) ^ cnow apply div_exact. Qed.a, b, c:tHb:b ~= 0H:a mod b == 0a == b * (a / b)
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) b2nsolve_proper. Qed.Proper (Logic.eq ==> eq) b2na:texists (a' : t) (b : bool), a == 2 * a' + ba:texists (a' : t) (b : bool), a == 2 * a' + ba, a':tH:a == 2 * a'exists (a'0 : t) (b : bool), a == 2 * a'0 + ba, a':tH:a == 2 * a' + 1exists (a'0 : t) (b : bool), a == 2 * a'0 + ba, a':tH:a == 2 * a'exists b : bool, a == 2 * a' + ba, a':tH:a == 2 * a' + 1exists (a'0 : t) (b : bool), a == 2 * a'0 + ba, a':tH:a == 2 * a'a == 2 * a' + falsea, a':tH:a == 2 * a' + 1exists (a'0 : t) (b : bool), a == 2 * a'0 + ba, a':tH:a == 2 * a' + 1exists (a'0 : t) (b : bool), a == 2 * a'0 + ba, a':tH:a == 2 * a' + 1exists b : bool, a == 2 * a' + bnow simpl. Qed.a, a':tH:a == 2 * a' + 1a == 2 * a' + true
We can compact testbit_odd_0 testbit_even_0
testbit_even_succ testbit_odd_succ in only two lemmas.
a:tb:bool(2 * a + b).[0] = ba:tb:bool(2 * a + b).[0] = ba:t(2 * a + 1).[0] = truea:t(2 * a).[0] = falseapply testbit_even_0. Qed.a:t(2 * a).[0] = falsea:tb:booln:t(2 * a + b).[S n] = a.[n]a:tb:booln: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]apply testbit_even_succ, le_0_l. Qed.a, n:t(2 * a).[S n] = a.[n]
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:ta.[n] == (a / 2 ^ n) mod 2a, n:ta.[n] == (a / 2 ^ n) mod 2n:tforall a : t, a.[n] == (a / 2 ^ n) mod 2forall a : t, a.[0] == (a / 2 ^ 0) mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a:ta.[0] == (a / 2 ^ 0) mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a:ta.[0] == a mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a, a':tb:boolH:a == 2 * a' + ba.[0] == a mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a, a':tb:boolH:a == 2 * a' + b(2 * a' + b).[0] == a mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a, a':tb:boolH:a == 2 * a' + bb == a mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2a, a':tb:boolH:a == 2 * a' + bb < 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2forall n : t, (forall a : t, a.[n] == (a / 2 ^ n) mod 2) -> forall a : t, a.[S n] == (a / 2 ^ S n) mod 2n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a:ta.[S n] == (a / 2 ^ S n) mod 2n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + ba.[S n] == (a / 2 ^ S n) mod 2n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + b(2 * a' + b).[S n] == (a / 2 ^ S n) mod 2n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + b(a' / 2 ^ n) mod 2 == (a / 2 ^ S n) mod 2n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + ba' / 2 ^ n == a / 2 ^ S nn:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + ba' / 2 ^ n == a / 2 / 2 ^ nn:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + ba' == a / 2destruct b; order'. Qed.n:tIH:forall a0 : t, a0.[n] == (a0 / 2 ^ n) mod 2a, a':tb:boolH:a == 2 * a' + bb < 2
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:texists l h : t, 0 <= l < 2 ^ n /\ a == l + (a.[n] + 2 * h) * 2 ^ na, n:texists l h : t, 0 <= l < 2 ^ n /\ a == l + (a.[n] + 2 * h) * 2 ^ na, n:texists h : t, 0 <= a mod 2 ^ n < 2 ^ n /\ a == a mod 2 ^ n + (a.[n] + 2 * h) * 2 ^ na, n:t0 <= a mod 2 ^ n < 2 ^ n /\ a == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ na, n:t0 <= a mod 2 ^ n < 2 ^ na, n:ta == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ na, n:ta == a mod 2 ^ n + (a.[n] + 2 * (a / 2 ^ n / 2)) * 2 ^ na, n:ta == 2 ^ n * (2 * (a / 2 ^ n / 2) + a.[n]) + a mod 2 ^ na, n:t2 ^ n * (a / 2 ^ n) + a mod 2 ^ n == 2 ^ n * (2 * (a / 2 ^ n / 2) + a.[n]) + a mod 2 ^ na, n:ta / 2 ^ n == 2 * (a / 2 ^ n / 2) + a.[n]a, n:ta / 2 ^ n == 2 * (a / 2 ^ n / 2) + (a / 2 ^ n) mod 2order'. Qed.a, n:t2 ~= 0forall a n : t, a.[n] = true <-> (a / 2 ^ n) mod 2 == 1forall a n : t, a.[n] = true <-> (a / 2 ^ n) mod 2 == 1rewrite <- testbit_spec'; destruct a.[n]; split; simpl; now try order'. Qed.a, n:ta.[n] = true <-> (a / 2 ^ n) mod 2 == 1forall a n : t, a.[n] = false <-> (a / 2 ^ n) mod 2 == 0forall a n : t, a.[n] = false <-> (a / 2 ^ n) mod 2 == 0rewrite <- testbit_spec'; destruct a.[n]; split; simpl; now try order'. Qed.a, n:ta.[n] = false <-> (a / 2 ^ n) mod 2 == 0forall 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:ta.[n] = ((a / 2 ^ n) mod 2 =? 1)now rewrite testbit_true, eqb_eq. Qed.a, n:ta.[n] = true <-> ((a / 2 ^ n) mod 2 =? 1) = true
Results about the injection b2n
forall a0 b0 : bool, a0 == b0 -> a0 = b0intros [|] [|]; simpl; trivial; order'. Qed.forall a0 b0 : bool, a0 == b0 -> a0 = b0forall (a0 : bool) (a : t), (a0 + 2 * a) / 2 == aforall (a0 : bool) (a : t), (a0 + 2 * a) / 2 == aa0:boola:t(a0 + 2 * a) / 2 == anow rewrite div_small, add_0_l by (destruct a0; order'). Qed.a0:boola:ta0 / 2 + a == aforall (a0 : bool) (a : t), (a0 + 2 * a).[0] = a0forall (a0 : bool) (a : t), (a0 + 2 * a).[0] = a0a0:boola:t(a0 + 2 * a).[0] = a0a0:boola:t(a0 + 2 * a).[0] == a0a0:boola:t((a0 + 2 * a) / 2 ^ 0) mod 2 == a0a0:boola:t(a0 + 2 * a) mod 2 == a0now rewrite mod_small by (destruct a0; order'). Qed.a0:boola:ta0 mod 2 == a0forall a0 : bool, a0 / 2 == 0forall a0 : bool, a0 / 2 == 0a0:boola0 / 2 == 0now nzsimpl. Qed.a0:boola0 / 2 == (a0 + 2 * 0) / 2forall a0 : bool, a0.[0] = a0forall a0 : bool, a0.[0] = a0a0:boola0.[0] = a0now nzsimpl. Qed.a0:boola0.[0] = (a0 + 2 * 0).[0]
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] = a0forall (a n : t) (a0 : bool) (l h : t), l < 2 ^ n -> a == l + (a0 + 2 * h) * 2 ^ n -> a.[n] = a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na.[n] = a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na.[n] == a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ n(a / 2 ^ n) mod 2 == a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na0 == (a / 2 ^ n) mod 2a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na0 < 2a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na / 2 ^ n == 2 * h + a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na / 2 ^ n == 2 * h + a0a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ n2 * h + a0 == a / 2 ^ nnow rewrite add_comm, (add_comm _ a0), mul_comm. Qed.a, n:ta0:booll, h:tHl:l < 2 ^ nEQ:a == l + (a0 + 2 * h) * 2 ^ na == 2 ^ n * (2 * h + a0) + l
All bits of number 0 are 0
forall n : t, 0.[n] = falseforall n : t, 0.[n] = falsen:t0.[n] = falsenzsimpl; order_nz. Qed.n:t(0 / 2 ^ n) mod 2 == 0
Various ways to refer to the lowest bit of a number
forall a : t, a.[0] = odd aforall a : t, a.[0] = odd aa:ta.[0] = odd aa:todd a = a.[0]a, a':tb:boolEQ:a == 2 * a' + bodd a = a.[0]destruct b; simpl; apply odd_1 || apply odd_0. Qed.a, a':tb:boolEQ:a == 2 * a' + bodd b = bforall a : t, a.[0] = (a mod 2 =? 1)forall a : t, a.[0] = (a mod 2 =? 1)a:ta.[0] = (a mod 2 =? 1)now nzsimpl. Qed.a:t((a / 2 ^ 0) mod 2 =? 1) = (a mod 2 =? 1)forall a : t, a.[0] == a mod 2forall a : t, a.[0] == a mod 2a:ta.[0] == a mod 2now nzsimpl. Qed.a:t(a / 2 ^ 0) mod 2 == a mod 2
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)now rewrite <- bit0_odd, shiftr_spec, add_0_l. Qed.a, n:ta.[n] = odd (a >> n)
log2 gives the highest nonzero bit
forall a : t, a ~= 0 -> a.[log2 a] = trueforall a : t, a ~= 0 -> a.[log2 a] = truea:tHa:a ~= 0a.[log2 a] = truea:tHa:a ~= 0Ha':0 < aa.[log2 a] = truea:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 aa.[log2 a] = truea:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a(2 ^ log2 a + r).[log2 a] = truea:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a((r + 2 ^ log2 a) / 2 ^ log2 a) mod 2 == 1a:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a((r + 1 * 2 ^ log2 a) / 2 ^ log2 a) mod 2 == 1a:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a(r / 2 ^ log2 a + 1) mod 2 == 1a:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a(0 + 1) mod 2 == 1a:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a1 mod 2 == 1order'. Qed.a:tHa:a ~= 0Ha':0 < ar:tEQ:a == 2 ^ log2 a + rHr:r < 2 ^ log2 a1 < 2forall a n : t, log2 a < n -> a.[n] = falseforall a n : t, log2 a < n -> a.[n] = falsea, n:tH:log2 a < na.[n] = falsea, n:tH:log2 a < n(a / 2 ^ n) mod 2 == 0a, n:tH:log2 a < n0 mod 2 == 0a, n:tH:log2 a < na < 2 ^ na, n:tH:log2 a < na < 2 ^ nrewrite log2_pow2; trivial using le_0_l. Qed.a, n:tH:log2 a < nlog2 a < log2 (2 ^ n)
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] = truea, n:t(a / 2 / 2 ^ n) mod 2 == 1 <-> (a / 2 ^ S n) mod 2 == 1now rewrite div_div by order_nz. Qed.a, n:t(a / 2 / 2 ^ n) mod 2 == 1 <-> (a / (2 * 2 ^ n)) mod 2 == 1forall 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:tforall m : t, (a / 2 ^ n).[m] = a.[m + n]n:tforall 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:tIH:forall a0 m0 : t, (a0 / 2 ^ n).[m0] = a0.[m0 + n]a, m:t(a / 2 ^ S n).[m] = a.[m + S n]n:tIH: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.n:tIH:forall a0 m0 : t, (a0 / 2 ^ n).[m0] = a0.[m0 + n]a, m:t(a / 2 / 2 ^ n).[m] = a.[S (m + n)]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]now rewrite mul_comm, div_mul by order'. Qed.a, n:t(2 * a / 2).[n] = a.[n]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]now rewrite div_mul by order_nz. Qed.a, n, m:t(a * 2 ^ n / 2 ^ n).[m] = a.[m]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:tH:n <= m(a * 2 ^ n).[m] = a.[m - n]now rewrite mul_pow2_bits_add. Qed.a, n, m:tH:n <= m(a * 2 ^ n).[m - n + n] = a.[m - n]forall a n m : t, m < n -> (a * 2 ^ n).[m] = falseforall a n m : t, m < n -> (a * 2 ^ n).[m] = falsea, n, m:tH:m < n(a * 2 ^ n).[m] = falsea, n, m:tH:m < n(a * 2 ^ n / 2 ^ m) mod 2 == 0a, n, m:tH:m < n(a * 2 ^ (n - m + m) / 2 ^ m) mod 2 == 0a, n, m:tH:m < n(a * 2 ^ (n - m) * 2 ^ m / 2 ^ m) mod 2 == 0a, n, m:tH:m < n(a * 2 ^ (n - m)) mod 2 == 0a, n, m:tH:m < n(a * 2 ^ S (P (n - m))) mod 2 == 0a, n, m:tH:m < nn - m ~= 0a, n, m:tH:m < n(a * (2 * 2 ^ P (n - m))) mod 2 == 0a, n, m:tH:m < n0 <= P (n - m)a, n, m:tH:m < nn - m ~= 0a, n, m:tH:m < n0 <= P (n - m)a, n, m:tH:m < nn - m ~= 0a, n, m:tH:m < n0 < n - ma, n, m:tH:m < nn - m ~= 0a, n, m:tH:n - m ~= 00 < n - ma, n, m:tH:m < nn - m ~= 0now apply sub_gt. Qed.a, n, m:tH:m < nn - m ~= 0
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] = falseforall a n m : t, n <= m -> (a mod 2 ^ n).[m] = falsea, n, m:tH:n <= m(a mod 2 ^ n).[m] = falsea, n, m:tH:n <= mEQ:a mod 2 ^ n == 0(a mod 2 ^ n).[m] = falsea, n, m:tH:n <= mLT:0 < a mod 2 ^ n(a mod 2 ^ n).[m] = falsea, n, m:tH:n <= mLT:0 < a mod 2 ^ n(a mod 2 ^ n).[m] = falsea, n, m:tH:n <= mLT:0 < a mod 2 ^ nlog2 (a mod 2 ^ n) < ma, n, m:tH:n <= mLT:0 < a mod 2 ^ nlog2 (a mod 2 ^ n) < napply mod_upper_bound; order_nz. Qed.a, n, m:tH:n <= mLT:0 < a mod 2 ^ na mod 2 ^ n < 2 ^ nforall 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:tH:m < n(a mod 2 ^ n).[m] = a.[m]a, n, m:tH:m < n((a mod 2 ^ n / 2 ^ m) mod 2 =? 1) = a.[m]a, n, m:tH:m < n((a mod 2 ^ n / 2 ^ m + 2 ^ P (n - m) * (a / 2 ^ n) * 2) mod 2 =? 1) = a.[m]a, n, m:tH: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:tH:m < n(((a mod 2 ^ n + 2 ^ (n - m) * (a / 2 ^ n) * 2 ^ m) / 2 ^ m) mod 2 =? 1) = a.[m]a, n, m:tH:m < n(((a mod 2 ^ n + 2 ^ n * (a / 2 ^ n)) / 2 ^ m) mod 2 =? 1) = a.[m]a, n, m:tH:m < n((a / 2 ^ m) mod 2 =? 1) = a.[m]apply testbit_eqb. Qed.a, n, m:tH:m < na.[m] = ((a / 2 ^ m) mod 2 =? 1)
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 eqfsplit; congruence. Qed. Local Infix "===" := eqf (at level 70, no associativity).Equivalence eqfProper (eq ==> eqf) testbitProper (eq ==> eqf) testbitnow rewrite Ha. Qed.a, a':tHa:a == a'n:ta.[n] = a'.[n]
Only zero corresponds to the always-false stream.
forall a : t, (forall n : t, a.[n] = false) -> a == 0forall a : t, (forall n : t, a.[n] = false) -> a == 0a:tH:forall n : t, a.[n] = falsea == 0a:tH:forall n : t, a.[n] = falseNEQ:a ~= 0a == 0now rewrite H in NEQ. Qed.a:tH:forall n : t, a.[n] = falseNEQ:a.[log2 a] = truea == 0
If two numbers produce the same stream of bits, they are equal.
forall a b : t, testbit a === testbit b -> a == bforall a b : t, testbit a === testbit b -> a == ba:tforall b : t, testbit a === testbit b -> a == ba:t(fun t0 : t => forall b : t, testbit t0 === testbit b -> t0 == b) aforall 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 == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit ba == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bEQ:a == 0a == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit 0 === testbit bEQ:a == 00 == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit 0 === testbit bEQ:a == 0b == 0a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit 0 === testbit bEQ:a == 0forall n : t, b.[n] = falsea:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit 0 === testbit bEQ:a == 0n:tb.[n] = falsea:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa == ba:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < a2 * (a / 2) + a mod 2 == 2 * (b / 2) + b mod 2a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < a2 * (a / 2) == 2 * (b / 2)a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa / 2 == b / 2a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < aa / 2 < aa:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < atestbit (a / 2) === testbit (b / 2)a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < atestbit (a / 2) === testbit (b / 2)a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < an:t(a / 2).[n] = (b / 2).[n]apply H. Qed.a:tIH:forall m : t, 0 <= m -> m < a -> forall b0 : t, testbit m === testbit b0 -> m == b0b:tH:testbit a === testbit bLT:0 < an:ta.[S n] = b.[S n]forall a b : t, testbit a === testbit b <-> a == bforall a b : t, testbit a === testbit b <-> a == ba, b:ttestbit a === testbit b -> a == ba, b:ta == b -> testbit a === testbit bintros 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.a, b:ta == b -> testbit a === testbit b
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 -> boolHf:Proper (eq ==> Logic.eq) f(exists n : t, f === testbit n) <-> (exists k : t, forall m : t, k <= m -> f m = false)f:t -> boolHf:Proper (eq ==> Logic.eq) f(exists n : t, f === testbit n) -> exists k : t, forall m : t, k <= m -> f m = falsef:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fa:tH:f === testbit aexists k : t, forall m : t, k <= m -> f m = falsef:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fa:tH:f === testbit aforall m : t, S (log2 a) <= m -> f m = falsef:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fa:tH:f === testbit am:tHm:S (log2 a) <= mf m = falsef:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fa:tH:f === testbit am:tHm:log2 a < mf m = falsef:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) f(exists k : t, forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fk:tHk:forall m : t, k <= m -> f m = falseexists n : t, f === testbit nk:tforall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, k <= m -> f m = false) -> exists n : t, f === testbit nforall f : t -> bool, Proper (eq ==> Logic.eq) f -> (forall m : t, 0 <= m -> f m = false) -> exists n : t, f === testbit nforall 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 n0f:t -> boolHf:Proper (eq ==> Logic.eq) fH0:forall m : t, 0 <= m -> f m = falseexists n : t, f === testbit nforall 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 n0f:t -> boolHf:Proper (eq ==> Logic.eq) fH0:forall m : t, 0 <= m -> f m = falsef === testbit 0forall 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 n0f:t -> boolHf:Proper (eq ==> Logic.eq) fH0:forall m0 : t, 0 <= m0 -> f m0 = falsem:tf 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 n0f:t -> boolHf:Proper (eq ==> Logic.eq) fH0:forall m0 : t, 0 <= m0 -> f m0 = falsem:t0 <= mforall 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 n0forall 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 n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falseexists n : t, f === testbit nk:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falseProper (eq ==> Logic.eq) (fun m : t => f (S m))k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falseforall m : t, k <= m -> f (S m) = falsek:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nexists n0 : t, f === testbit n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falseforall m : t, k <= m -> f (S m) = falsek:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nexists n0 : t, f === testbit n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsem:tHm:k <= mf (S m) = falsek:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nexists n0 : t, f === testbit n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n : t, f0 === testbit nf:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsem:tHm:k <= mS k <= S mk:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nexists n0 : t, f === testbit n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nexists n0 : t, f === testbit n0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m : t, k <= m -> f0 m = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m : t, S k <= m -> f m = falsen:tHn:(fun m : t => f (S m)) === testbit nf === testbit (f 0 + 2 * n)k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm:tf m = (f 0 + 2 * n).[m]k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm:tHm:m == 0f 0 = (f 0 + 2 * n).[0]k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm, m':tHm:m == S m'f (S m') = (f 0 + 2 * n).[S m']k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm:tHm:m == 0(f 0 + 2 * n).[0] = f 0k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm, m':tHm:m == S m'f (S m') = (f 0 + 2 * n).[S m']k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm, m':tHm:m == S m'f (S m') = (f 0 + 2 * n).[S m']k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm, m':tHm:m == S m'n.[m'] = ((f 0 + 2 * n) / 2).[m']order'. Qed.k:tIH:forall f0 : t -> bool, Proper (eq ==> Logic.eq) f0 -> (forall m0 : t, k <= m0 -> f0 m0 = false) -> exists n0 : t, f0 === testbit n0f:t -> boolHf:Proper (eq ==> Logic.eq) fHk:forall m0 : t, S k <= m0 -> f m0 = falsen:tHn:(fun m0 : t => f (S m0)) === testbit nm, m':tHm:m == S m'2 ~= 0
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]apply le_0_l. Qed.a, n, m:t0 <= mforall 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:tH:n <= m(a << n).[m] = a.[m - n]apply le_0_l. Qed.a, n, m:tH:n <= m0 <= mforall a n : t, a >> n == a / 2 ^ nforall a n : t, a >> n == a / 2 ^ na, n:ta >> n == a / 2 ^ na, n, m:t(a >> n).[m] = (a / 2 ^ n).[m]a, n, m:ta.[m + n] = (a / 2 ^ n).[m]apply div_pow2_bits. Qed.a, n, m:t(a / 2 ^ n).[m] = a.[m + n]forall a n : t, a << n == a * 2 ^ nforall a n : t, a << n == a * 2 ^ na, n:ta << n == a * 2 ^ na, n, m:t(a << n).[m] = (a * 2 ^ n).[m]a, n, m:tH:n <= m(a << n).[m] = (a * 2 ^ n).[m]a, n, m:tH:m < n(a << n).[m] = (a * 2 ^ n).[m]now rewrite shiftl_spec_low, mul_pow2_bits_low. Qed.a, n, m:tH:m < n(a << n).[m] = (a * 2 ^ n).[m]forall a n m : t, (a << n).[m + n] = a.[m]forall a n m : t, (a << n).[m + n] = a.[m]now rewrite shiftl_mul_pow2, mul_pow2_bits_add. Qed.a, n, m:t(a << n).[m + n] = a.[m]Proper (eq ==> eq ==> eq) shiftrProper (eq ==> eq ==> eq) shiftrnow rewrite 2 shiftr_div_pow2, Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'a >> b == a' >> b'Proper (eq ==> eq ==> eq) shiftlProper (eq ==> eq ==> eq) shiftlnow rewrite 2 shiftl_mul_pow2, Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'a << b == a' << b'forall a n m : t, (a << n) << m == a << (n + m)forall a n m : t, (a << n) << m == a << (n + m)now rewrite !shiftl_mul_pow2, pow_add_r, mul_assoc. Qed.a, n, m:t(a << n) << m == a << (n + m)forall a n m : t, (a >> n) >> m == a >> (n + m)forall a n m : t, (a >> n) >> m == a >> (n + m)now rewrite !shiftr_div_pow2, pow_add_r, div_div by order_nz. Qed.a, n, m:t(a >> n) >> m == a >> (n + m)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:tH:m <= n(a << n) >> m == a << (n - m)a, n, m:tH:m <= na * 2 ^ n / 2 ^ m == a * 2 ^ (n - m)now rewrite pow_add_r, mul_assoc, div_mul by order_nz. Qed.a, n, m:tH:m <= na * 2 ^ (n - m + m) / 2 ^ m == a * 2 ^ (n - m)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:tH:n <= m(a << n) >> m == a >> (m - n)a, n, m:tH:n <= ma * 2 ^ n / 2 ^ m == a / 2 ^ (m - n)a, n, m:tH:n <= ma * 2 ^ n / 2 ^ (m - n + n) == a / 2 ^ (m - n)now rewrite <- div_div, div_mul by order_nz. Qed.a, n, m:tH:n <= ma * 2 ^ n / (2 ^ n * 2 ^ (m - n)) == a / 2 ^ (m - n)
shifts and constants
forall n : t, 1 << n == 2 ^ nforall n : t, 1 << n == 2 ^ nnow rewrite shiftl_mul_pow2, mul_1_l. Qed.n:t1 << n == 2 ^ nforall a : t, a << 0 == aforall a : t, a << 0 == aa:ta << 0 == anow nzsimpl. Qed.a:ta * 2 ^ 0 == aforall a : t, a >> 0 == aforall a : t, a >> 0 == aa:ta >> 0 == anow nzsimpl. Qed.a:ta / 2 ^ 0 == aforall n : t, 0 << n == 0forall n : t, 0 << n == 0n:t0 << n == 0now nzsimpl. Qed.n:t0 * 2 ^ n == 0forall n : t, 0 >> n == 0forall n : t, 0 >> n == 0n:t0 >> n == 0nzsimpl; order_nz. Qed.n:t0 / 2 ^ n == 0forall a n : t, a << n == 0 <-> a == 0forall a n : t, a << n == 0 <-> a == 0a, n:ta << n == 0 <-> a == 0a, n:ta * 2 ^ n == 0 <-> a == 0a, n:ta == 0 \/ 2 ^ n == 0 <-> a == 0a, n:ta == 0 \/ 2 ^ n == 0 -> a == 0a, n:ta == 0 -> a == 0 \/ 2 ^ n == 0a, n:tH:2 ^ n == 0a == 0a, n:ta == 0 -> a == 0 \/ 2 ^ n == 0a, n:ta == 0 -> a == 0 \/ 2 ^ n == 0now left. Qed.a, n:tH:a == 0a == 0 \/ 2 ^ n == 0forall a n : t, a >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < nforall a n : t, a >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < na, n:ta >> n == 0 <-> a == 0 \/ 0 < a /\ log2 a < na, n:ta < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 0a < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 00 < 2 ^ n <-> 0 == 0 \/ 0 < 0 /\ log2 0 < na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 00 < 2 ^ n -> 0 == 0 \/ 0 < 0 /\ log2 0 < na, n:tEQ:a == 00 == 0 \/ 0 < 0 /\ log2 0 < n -> 0 < 2 ^ na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 00 == 0 \/ 0 < 0 /\ log2 0 < n -> 0 < 2 ^ na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 00 < 2 ^ na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tEQ:a == 0H:2 ~= 00 < 2 ^ na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tLT:0 < aa < 2 ^ n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tLT:0 < alog2 a < n <-> a == 0 \/ 0 < a /\ log2 a < na, n:tLT:0 < alog2 a < n -> a == 0 \/ 0 < a /\ log2 a < na, n:tLT:0 < aa == 0 \/ 0 < a /\ log2 a < n -> log2 a < nintros [H|[_ H]]; now order. Qed.a, n:tLT:0 < aa == 0 \/ 0 < a /\ log2 a < n -> log2 a < nforall a n : t, log2 a < n -> a >> n == 0forall a n : t, log2 a < n -> a >> n == 0a, n:tH:log2 a < na >> n == 0a, n:tH:log2 a < na == 0 \/ 0 < a /\ log2 a < na, n:tH:log2 a < nEQ:a == 0a == 0 \/ 0 < a /\ log2 a < na, n:tH:log2 a < nLT:0 < aa == 0 \/ 0 < a /\ log2 a < nright; now split. Qed.a, n:tH:log2 a < nLT:0 < aa == 0 \/ 0 < a /\ log2 a < n
Properties of div2.
forall a : t, div2 a == a / 2forall a : t, div2 a == a / 2a:tdiv2 a == a / 2now nzsimpl. Qed.a:ta / 2 ^ 1 == a / 2Proper (eq ==> eq) div2Proper (eq ==> eq) div2now rewrite 2 div2_div, Ha. Qed.a, a':tHa:a == a'div2 a == div2 a'forall a : t, a == 2 * div2 a + odd aforall a : t, a == 2 * div2 a + odd aa:ta == 2 * div2 a + odd aa:ta == 2 * (a / 2) + a mod 2order'. Qed.a:t2 ~= 0
Properties of lxor and others, directly deduced
from properties of xorb and others.
Proper (eq ==> eq ==> eq) lxorProper (eq ==> eq ==> eq) lxora, a':tHa:a == a'b, b':tHb:b == b'lxor a b == lxor a' b'now rewrite Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'm:txorb a.[m] b.[m] = xorb a'.[m] b'.[m]Proper (eq ==> eq ==> eq) landProper (eq ==> eq ==> eq) landa, a':tHa:a == a'b, b':tHb:b == b'land a b == land a' b'now rewrite Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'm:ta.[m] && b.[m] = a'.[m] && b'.[m]Proper (eq ==> eq ==> eq) lorProper (eq ==> eq ==> eq) lora, a':tHa:a == a'b, b':tHb:b == b'lor a b == lor a' b'now rewrite Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'm:ta.[m] || b.[m] = a'.[m] || b'.[m]Proper (eq ==> eq ==> eq) ldiffProper (eq ==> eq ==> eq) ldiffa, a':tHa:a == a'b, b':tHb:b == b'ldiff a b == ldiff a' b'now rewrite Ha, Hb. Qed.a, a':tHa:a == a'b, b':tHb:b == b'm:ta.[m] && negb b.[m] = a'.[m] && negb b'.[m]forall a a' : t, lxor a a' == 0 -> a == a'forall a a' : t, lxor a a' == 0 -> a == a'a, a':tH:lxor a a' == 0a == a'a, a':tH:lxor a a' == 0m:ta.[m] = a'.[m]now rewrite <- lxor_spec, H, bits_0. Qed.a, a':tH:lxor a a' == 0m:txorb a.[m] a'.[m] = falseforall a : t, lxor a a == 0forall a : t, lxor a a == 0a:tlxor a a == 0apply xorb_nilpotent. Qed.a, m:txorb a.[m] a.[m] = falseforall a a' : t, lxor a a' == 0 <-> a == a'forall a a' : t, lxor a a' == 0 <-> a == a'a, a':tlxor a a' == 0 -> a == a'a, a':ta == a' -> lxor a a' == 0intros EQ; rewrite EQ; apply lxor_nilpotent. Qed.a, a':ta == a' -> lxor a a' == 0forall a : t, lxor 0 a == aforall a : t, lxor 0 a == aa:tlxor 0 a == aapply xorb_false_l. Qed.a, m:txorb false a.[m] = a.[m]forall a : t, lxor a 0 == aforall a : t, lxor a 0 == aa:tlxor a 0 == aapply xorb_false_r. Qed.a, m:txorb a.[m] false = a.[m]forall a b : t, lxor a b == lxor b aforall a b : t, lxor a b == lxor b aa, b:tlxor a b == lxor b aapply xorb_comm. Qed.a, b, m:txorb a.[m] b.[m] = xorb b.[m] a.[m]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:tlxor (lxor a b) c == lxor a (lxor b c)apply xorb_assoc. Qed.a, b, c, m:txorb (xorb a.[m] b.[m]) c.[m] = xorb a.[m] (xorb b.[m] c.[m])forall a : t, lor 0 a == aforall a : t, lor 0 a == aa:tlor 0 a == atrivial. Qed.a, m:tfalse || a.[m] = a.[m]forall a : t, lor a 0 == aforall a : t, lor a 0 == aa:tlor a 0 == aapply orb_false_r. Qed.a, m:ta.[m] || false = a.[m]forall a b : t, lor a b == lor b aforall a b : t, lor a b == lor b aa, b:tlor a b == lor b aapply orb_comm. Qed.a, b, m:ta.[m] || b.[m] = b.[m] || a.[m]forall a b c : t, lor a (lor b c) == lor (lor a b) cforall a b c : t, lor a (lor b c) == lor (lor a b) ca, b, c:tlor a (lor b c) == lor (lor a b) capply orb_assoc. Qed.a, b, c, m:ta.[m] || (b.[m] || c.[m]) = a.[m] || b.[m] || c.[m]forall a : t, lor a a == aforall a : t, lor a a == aa:tlor a a == aapply orb_diag. Qed.a, m:ta.[m] || a.[m] = a.[m]forall a b : t, lor a b == 0 -> a == 0forall a b : t, lor a b == 0 -> a == 0a, b:tH:lor a b == 0a == 0a, b:tH:lor a b == 0m:ta.[m] = falsenow rewrite <- lor_spec, H, bits_0. Qed.a, b:tH:lor a b == 0m:ta.[m] || b.[m] = falseforall a b : t, lor a b == 0 <-> a == 0 /\ b == 0forall a b : t, lor a b == 0 <-> a == 0 /\ b == 0a, b:tlor a b == 0 <-> a == 0 /\ b == 0a, b:tlor a b == 0 -> a == 0 /\ b == 0a, b:ta == 0 /\ b == 0 -> lor a b == 0a, b:tH:lor a b == 0a == 0a, b:tH:lor a b == 0b == 0a, b:ta == 0 /\ b == 0 -> lor a b == 0a, b:tH:lor a b == 0b == 0a, b:ta == 0 /\ b == 0 -> lor a b == 0a, b:tH:lor b a == 0b == 0a, b:ta == 0 /\ b == 0 -> lor a b == 0a, b:ta == 0 /\ b == 0 -> lor a b == 0now rewrite EQ, lor_0_l. Qed.a, b:tEQ:a == 0EQ':b == 0lor a b == 0forall a : t, land 0 a == 0forall a : t, land 0 a == 0a:tland 0 a == 0trivial. Qed.a, m:tfalse && a.[m] = falseforall a : t, land a 0 == 0forall a : t, land a 0 == 0a:tland a 0 == 0apply andb_false_r. Qed.a, m:ta.[m] && false = falseforall a b : t, land a b == land b aforall a b : t, land a b == land b aa, b:tland a b == land b aapply andb_comm. Qed.a, b, m:ta.[m] && b.[m] = b.[m] && a.[m]forall a b c : t, land a (land b c) == land (land a b) cforall a b c : t, land a (land b c) == land (land a b) ca, b, c:tland a (land b c) == land (land a b) capply andb_assoc. Qed.a, b, c, m:ta.[m] && (b.[m] && c.[m]) = a.[m] && b.[m] && c.[m]forall a : t, land a a == aforall a : t, land a a == aa:tland a a == aapply andb_diag. Qed.a, m:ta.[m] && a.[m] = a.[m]forall a : t, ldiff 0 a == 0forall a : t, ldiff 0 a == 0a:tldiff 0 a == 0trivial. Qed.a, m:tfalse && negb a.[m] = falseforall a : t, ldiff a 0 == aforall a : t, ldiff a 0 == aa:tldiff a 0 == anow rewrite andb_true_r. Qed.a, m:ta.[m] && negb false = a.[m]forall a : t, ldiff a a == 0forall a : t, ldiff a a == 0a:tldiff a a == 0apply andb_negb_r. Qed.a, m:ta.[m] && negb a.[m] = falseforall 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:tlor (land a b) c == land (lor a c) (lor b c)apply orb_andb_distrib_l. Qed.a, b, c, m:ta.[m] && b.[m] || c.[m] = (a.[m] || c.[m]) && (b.[m] || c.[m])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:tlor a (land b c) == land (lor a b) (lor a c)apply orb_andb_distrib_r. Qed.a, b, c, m:ta.[m] || b.[m] && c.[m] = (a.[m] || b.[m]) && (a.[m] || c.[m])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:tland (lor a b) c == lor (land a c) (land b c)apply andb_orb_distrib_l. Qed.a, b, c, m:t(a.[m] || b.[m]) && c.[m] = a.[m] && c.[m] || b.[m] && c.[m]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:tland a (lor b c) == lor (land a b) (land a c)apply andb_orb_distrib_r. Qed.a, b, c, m:ta.[m] && (b.[m] || c.[m]) = a.[m] && b.[m] || a.[m] && c.[m]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:tldiff (ldiff a b) c == ldiff a (lor b c)now rewrite negb_orb, andb_assoc. Qed.a, b, c, m:ta.[m] && negb b.[m] && negb c.[m] = a.[m] && negb (b.[m] || c.[m])forall a b : t, lor (ldiff a b) (land a b) == aforall a b : t, lor (ldiff a b) (land a b) == aa, b:tlor (ldiff a b) (land a b) == anow rewrite <- andb_orb_distrib_r, orb_comm, orb_negb_r, andb_true_r. Qed.a, b, m:ta.[m] && negb b.[m] || a.[m] && b.[m] = a.[m]forall a b : t, land (ldiff a b) b == 0forall a b : t, land (ldiff a b) b == 0a, b:tland (ldiff a b) b == 0now rewrite <-andb_assoc, (andb_comm (negb _)), andb_negb_r, andb_false_r. Qed.a, b, m:ta.[m] && negb b.[m] && b.[m] = false
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:tsetbit a n == lor a (2 ^ n)now rewrite shiftl_1_l. Qed.a, n:tlor a (1 << n) == lor a (2 ^ n)forall a n : t, clearbit a n == ldiff a (2 ^ n)forall a n : t, clearbit a n == ldiff a (2 ^ n)a, n:tclearbit a n == ldiff a (2 ^ n)now rewrite shiftl_1_l. Qed.a, n:tldiff a (1 << n) == ldiff a (2 ^ n)Proper (eq ==> eq ==> eq) setbitProper (eq ==> eq ==> eq) setbitsolve_proper. Qed.Proper (eq ==> eq ==> eq) (fun a n : t => lor a (1 << n))Proper (eq ==> eq ==> eq) clearbitProper (eq ==> eq ==> eq) clearbitsolve_proper. Qed.Proper (eq ==> eq ==> eq) (fun a n : t => ldiff a (1 << n))forall n : t, (2 ^ n).[n] = trueforall n : t, (2 ^ n).[n] = truen:t(2 ^ n).[n] = truen:t(1 * 2 ^ n).[n] = truenow rewrite mul_pow2_bits_add, bit0_odd, odd_1. Qed.n:t(1 * 2 ^ n).[0 + n] = trueforall n m : t, n ~= m -> (2 ^ n).[m] = falseforall n m : t, n ~= m -> (2 ^ n).[m] = falsen, m:tH:n ~= m(2 ^ n).[m] = falsen, m:tH:n ~= m(1 * 2 ^ n).[m] = falsen, m:tH:n ~= mH0:n <= m(1 * 2 ^ n).[m] = falsen, m:tH:n ~= mH0:m < n(1 * 2 ^ n).[m] = falsen, m:tH:n ~= mH0:n <= m1.[m - n] = falsen, m:tH:n ~= mH0:m < n(1 * 2 ^ n).[m] = falsen, m:tH:n ~= mH0:n <= m1.[S (P (m - n))] = falsen, m:tH:n ~= mH0:m < n(1 * 2 ^ n).[m] = falserewrite mul_pow2_bits_low; trivial. Qed.n, m:tH:n ~= mH0:m < n(1 * 2 ^ n).[m] = falseforall 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) = truen, m:t(2 ^ n).[m] = true <-> n == mn, m:t(2 ^ n).[m] = true -> n == mn, m:tn == m -> (2 ^ n).[m] = truen, m:tH:n == m(2 ^ n).[m] = true -> n == mn, m:tH:n ~= m(2 ^ n).[m] = true -> n == mn, m:tn == m -> (2 ^ n).[m] = truen, m:tH:n ~= m(2 ^ n).[m] = true -> n == mn, m:tn == m -> (2 ^ n).[m] = truen, m:tn == m -> (2 ^ n).[m] = truen, m:tEQ:n == m(2 ^ n).[m] = trueapply pow2_bits_true. Qed.n, m:tEQ:n == m(2 ^ m).[m] = trueforall 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]now rewrite setbit_spec', lor_spec, pow2_bits_eqb, orb_comm. Qed.a, n, m:t(setbit a n).[m] = (n =? m) || a.[m]forall a n m : t, (setbit a n).[m] = true <-> n == m \/ a.[m] = trueforall a n m : t, (setbit a n).[m] = true <-> n == m \/ a.[m] = truenow rewrite setbit_eqb, orb_true_iff, eqb_eq. Qed.a, n, m:t(setbit a n).[m] = true <-> n == m \/ a.[m] = trueforall a n : t, (setbit a n).[n] = trueforall a n : t, (setbit a n).[n] = truea, n:t(setbit a n).[n] = truenow left. Qed.a, n:tn == n \/ a.[n] = trueforall 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:tH:n ~= m(setbit a n).[m] = a.[m]a, n, m:tH:n ~= m(n =? m) || a.[m] = a.[m]a, n, m:tH:(n =? m) <> true(n =? m) || a.[m] = a.[m]now rewrite H. Qed.a, n, m:tH:(n =? m) = false(n =? m) || a.[m] = a.[m]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)now rewrite clearbit_spec', ldiff_spec, pow2_bits_eqb. Qed.a, n, m:t(clearbit a n).[m] = a.[m] && negb (n =? m)forall a n m : t, (clearbit a n).[m] = true <-> a.[m] = true /\ n ~= mforall a n m : t, (clearbit a n).[m] = true <-> a.[m] = true /\ n ~= ma, n, m:t(clearbit a n).[m] = true <-> a.[m] = true /\ n ~= mnow rewrite negb_true_iff, not_true_iff_false. Qed.a, n, m:ta.[m] = true /\ negb (n =? m) = true <-> a.[m] = true /\ (n =? m) <> trueforall a n : t, (clearbit a n).[n] = falseforall a n : t, (clearbit a n).[n] = falsea, n:t(clearbit a n).[n] = falseapply andb_false_r. Qed.a, n:ta.[n] && negb true = falseforall 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:tH:n ~= m(clearbit a n).[m] = a.[m]a, n, m:tH:n ~= ma.[m] && negb (n =? m) = a.[m]a, n, m:tH:(n =? m) <> truea.[m] && negb (n =? m) = a.[m]a, n, m:tH:(n =? m) = falsea.[m] && negb (n =? m) = a.[m]apply andb_true_r. Qed.a, n, m:tH:(n =? m) = falsea.[m] && negb false = a.[m]
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:tlxor 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:tH:n <= m(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]a, b, n, m:tH:m < n(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]now rewrite !shiftl_spec_low. Qed.a, b, n, m:tH:m < n(lxor a b << n).[m] = xorb (a << n).[m] (b << n).[m]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:tlxor a b >> n == lxor (a >> n) (b >> n)now rewrite !shiftr_spec', lxor_spec. Qed.a, b, n, m:t(lxor a b >> n).[m] = xorb (a >> n).[m] (b >> n).[m]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:tland 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:tH:n <= m(land a b << n).[m] = (a << n).[m] && (b << n).[m]a, b, n, m:tH:m < n(land a b << n).[m] = (a << n).[m] && (b << n).[m]now rewrite !shiftl_spec_low. Qed.a, b, n, m:tH:m < n(land a b << n).[m] = (a << n).[m] && (b << n).[m]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:tland a b >> n == land (a >> n) (b >> n)now rewrite !shiftr_spec', land_spec. Qed.a, b, n, m:t(land a b >> n).[m] = (a >> n).[m] && (b >> n).[m]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:tlor 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:tH:n <= m(lor a b << n).[m] = (a << n).[m] || (b << n).[m]a, b, n, m:tH:m < n(lor a b << n).[m] = (a << n).[m] || (b << n).[m]now rewrite !shiftl_spec_low. Qed.a, b, n, m:tH:m < n(lor a b << n).[m] = (a << n).[m] || (b << n).[m]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:tlor a b >> n == lor (a >> n) (b >> n)now rewrite !shiftr_spec', lor_spec. Qed.a, b, n, m:t(lor a b >> n).[m] = (a >> n).[m] || (b >> n).[m]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:tldiff 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:tH:n <= m(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]a, b, n, m:tH:m < n(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]now rewrite !shiftl_spec_low. Qed.a, b, n, m:tH:m < n(ldiff a b << n).[m] = (a << n).[m] && negb (b << n).[m]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:tldiff a b >> n == ldiff (a >> n) (b >> n)now rewrite !shiftr_spec', ldiff_spec. Qed.a, b, n, m:t(ldiff a b >> n).[m] = (a >> n).[m] && negb (b >> n).[m]
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) onesProper (eq ==> eq) onessolve_proper. Qed.Proper (eq ==> eq) (fun n : t => P (1 << n))Proper (eq ==> eq ==> eq) lnotProper (eq ==> eq ==> eq) lnotsolve_proper. Qed.Proper (eq ==> eq ==> eq) (fun a n : t => lxor a (ones n))forall n : t, ones n == P (2 ^ n)intros; unfold ones; now rewrite shiftl_1_l. Qed.forall n : t, ones n == P (2 ^ n)forall n m : t, ones (m + n) == 2 ^ m * ones n + ones mforall n m : t, ones (m + n) == 2 ^ m * ones n + ones mn, m:tones (m + n) == 2 ^ m * ones n + ones mn, m:tP (2 ^ (m + n)) == 2 ^ m * P (2 ^ n) + P (2 ^ m)n, m:t2 ^ (m + n) - 1 == 2 ^ (m + n) - 2 ^ m + (2 ^ m - 1)n, m:t2 ^ (m + n) - 1 == 2 ^ (m + n) - 1n, m:t2 ^ m <= 2 ^ (m + n)n, m:t1 <= 2 ^ mn, m:t2 ^ m <= 2 ^ (m + n)n, m:t1 <= 2 ^ mn, m:t2 ~= 0n, m:tm <= m + nn, m:t1 <= 2 ^ mn, m:tm <= m + nn, m:t1 <= 2 ^ mn, m:tm + 0 <= m + nn, m:t1 <= 2 ^ mn, m:t1 <= 2 ^ mn, m:t2 ^ 0 <= 2 ^ mn, m:t2 ~= 0n, m:t0 <= mapply le_0_l. Qed.n, m:t0 <= mforall 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:tH:m <= nones n / 2 ^ m == ones (n - m)n, m:tH:m <= nones (n - m) == ones n / 2 ^ mn, m:tH:m <= nones m < 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nP (2 ^ m) < 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nS (P (2 ^ m)) <= 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nones (n - m + m) == 2 ^ m * ones (n - m) + ones mapply ones_add. Qed.n, m:tH:m <= nones (m + (n - m)) == 2 ^ m * ones (n - m) + ones mforall n m : t, m <= n -> ones n mod 2 ^ m == ones mforall n m : t, m <= n -> ones n mod 2 ^ m == ones mn, m:tH:m <= nones n mod 2 ^ m == ones mn, m:tH:m <= nones m == ones n mod 2 ^ mn, m:tH:m <= nones m < 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nP (2 ^ m) < 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nS (P (2 ^ m)) <= 2 ^ mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nones n == 2 ^ m * ones (n - m) + ones mn, m:tH:m <= nones (n - m + m) == 2 ^ m * ones (n - m) + ones mapply ones_add. Qed.n, m:tH:m <= nones (m + (n - m)) == 2 ^ m * ones (n - m) + ones mforall n m : t, m < n -> (ones n).[m] = trueforall n m : t, m < n -> (ones n).[m] = truen, m:tH:m < n(ones n).[m] = truen, m:tH:m < n(ones n / 2 ^ m) mod 2 == 1n, m:tH:m < nones (n - m) mod 2 == 1n, m:tH:m < nones (n - m) mod 2 ^ 1 == 1n, m:tH:m < nones 1 == 1n, m:tH:m < n1 <= n - mn, m:tH:m < nP (2 ^ 1) == 1n, m:tH:m < n1 <= n - mn, m:tH:m < n1 <= n - mn, m:tH:m < n1 + m <= nnow apply le_succ_l. Qed.n, m:tH:m < nS m <= nforall n m : t, n <= m -> (ones n).[m] = falseforall n m : t, n <= m -> (ones n).[m] = falsen, m:tH:n <= m(ones n).[m] = falsen, m:tH:n <= mEQ:n == 0(P (2 ^ n)).[m] = falsen, m:tH:n <= mLT:0 < n(P (2 ^ n)).[m] = falsen, m:tH:n <= mLT:0 < n(P (2 ^ n)).[m] = falsen, m:tH:n <= mLT:0 < nlog2 (P (2 ^ n)) < mrewrite <-le_succ_l, succ_pred; order. Qed.n, m:tH:n <= mLT:0 < nP n < mforall n m : t, (ones n).[m] = true <-> m < nforall n m : t, (ones n).[m] = true <-> m < nn, m:t(ones n).[m] = true <-> m < nn, m:t(ones n).[m] = true -> m < nn, m:tm < n -> (ones n).[m] = truen, m:tH:(ones n).[m] = truem < nn, m:tm < n -> (ones n).[m] = truen, m:tH:(ones n).[m] = true~ n <= mn, m:tm < n -> (ones n).[m] = truen, m:tH:(ones n).[m] = trueH':n <= mFalsen, m:tm < n -> (ones n).[m] = truen, m:tH:(ones n).[m] = trueH':(ones n).[m] = falseFalsen, m:tm < n -> (ones n).[m] = trueapply ones_spec_low. Qed.n, m:tm < n -> (ones n).[m] = trueforall 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:tH:m < n(lnot a n).[m] = negb a.[m]now rewrite lxor_spec, ones_spec_low. Qed.a, n, m:tH:m < n(lxor a (ones n)).[m] = negb a.[m]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:tH:n <= m(lnot a n).[m] = a.[m]now rewrite lxor_spec, ones_spec_high, xorb_false_r. Qed.a, n, m:tH:n <= m(lxor a (ones n)).[m] = a.[m]forall a n : t, lnot (lnot a n) n == aforall a n : t, lnot (lnot a n) n == aa, n:tlnot (lnot a n) n == aa, n, m:t(lnot (lnot a n) n).[m] = a.[m]a, n, m:tH:n <= m(lnot (lnot a n) n).[m] = a.[m]a, n, m:tH:m < n(lnot (lnot a n) n).[m] = a.[m]now rewrite 2 lnot_spec_low, negb_involutive. Qed.a, n, m:tH:m < n(lnot (lnot a n) n).[m] = a.[m]forall n : t, lnot 0 n == ones nforall n : t, lnot 0 n == ones nn:tlnot 0 n == ones napply lxor_0_l. Qed.n:tlxor 0 (ones n) == ones nforall n : t, lnot (ones n) n == 0forall n : t, lnot (ones n) n == 0n:tlnot (ones n) n == 0apply lxor_nilpotent. Qed.n:tlxor (ones n) (ones n) == 0
Bounded complement and other operations
forall a n : t, log2 a < n -> lor a (ones n) == ones nforall a n : t, log2 a < n -> lor a (ones n) == ones na, n:tH:log2 a < nlor a (ones n) == ones na, n:tH:log2 a < nm:ta.[m] || (ones n).[m] = (ones n).[m]a, n:tH:log2 a < nm:tH0:n <= ma.[m] || (ones n).[m] = (ones n).[m]a, n:tH:log2 a < nm:tH0:m < na.[m] || (ones n).[m] = (ones n).[m]a, n:tH:log2 a < nm:tH0:n <= mlog2 a < ma, n:tH:log2 a < nm:tH0:m < na.[m] || (ones n).[m] = (ones n).[m]now rewrite ones_spec_low, orb_true_r. Qed.a, n:tH:log2 a < nm:tH0:m < na.[m] || (ones n).[m] = (ones n).[m]forall a n : t, land a (ones n) == a mod 2 ^ nforall a n : t, land a (ones n) == a mod 2 ^ na, n:tland a (ones n) == a mod 2 ^ na, n, m:ta.[m] && (ones n).[m] = (a mod 2 ^ n).[m]a, n, m:tH:n <= ma.[m] && (ones n).[m] = (a mod 2 ^ n).[m]a, n, m:tH:m < na.[m] && (ones n).[m] = (a mod 2 ^ n).[m]now rewrite ones_spec_low, mod_pow2_bits_low, andb_true_r. Qed.a, n, m:tH:m < na.[m] && (ones n).[m] = (a mod 2 ^ n).[m]forall a n : t, log2 a < n -> land a (ones n) == aforall a n : t, log2 a < n -> land a (ones n) == aa, n:tH:log2 a < na mod 2 ^ n == aa, n:tH:log2 a < na < 2 ^ nrewrite log2_pow2; trivial using le_0_l. Qed.a, n:tH:log2 a < nlog2 a < log2 (2 ^ n)forall a n : t, ldiff a (ones n) == (a >> n) << nforall a n : t, ldiff a (ones n) == (a >> n) << na, n:tldiff a (ones n) == (a >> n) << na, n, m:ta.[m] && negb (ones n).[m] = ((a >> n) << n).[m]a, n, m:tH:n <= ma.[m] && negb (ones n).[m] = ((a >> n) << n).[m]a, n, m:tH:m < na.[m] && negb (ones n).[m] = ((a >> n) << n).[m]a, n, m:tH:n <= ma.[m] && negb false = a.[m - n + n]a, n, m:tH:m < na.[m] && negb (ones n).[m] = ((a >> n) << n).[m]a, n, m:tH:n <= ma.[m] && negb false = a.[m]a, n, m:tH:m < na.[m] && negb (ones n).[m] = ((a >> n) << n).[m]now rewrite ones_spec_low, shiftl_spec_low, andb_false_r. Qed.a, n, m:tH:m < na.[m] && negb (ones n).[m] = ((a >> n) << n).[m]forall a n : t, log2 a < n -> ldiff a (ones n) == 0forall a n : t, log2 a < n -> ldiff a (ones n) == 0a, n:tH:log2 a < nldiff a (ones n) == 0a, n:tH:log2 a < nm:ta.[m] && negb (ones n).[m] = falsea, n:tH:log2 a < nm:tH0:n <= ma.[m] && negb (ones n).[m] = falsea, n:tH:log2 a < nm:tH0:m < na.[m] && negb (ones n).[m] = falsea, n:tH:log2 a < nm:tH0:n <= mlog2 a < ma, n:tH:log2 a < nm:tH0:m < na.[m] && negb (ones n).[m] = falsenow rewrite ones_spec_low, andb_false_r. Qed.a, n:tH:log2 a < nm:tH0:m < na.[m] && negb (ones n).[m] = falseforall a n : t, log2 a < n -> ldiff (ones n) a == lnot a nforall a n : t, log2 a < n -> ldiff (ones n) a == lnot a na, n:tH:log2 a < nldiff (ones n) a == lnot a na, n:tH:log2 a < nm:t(ones n).[m] && negb a.[m] = (lnot a n).[m]a, n:tH:log2 a < nm:tH0:n <= m(ones n).[m] && negb a.[m] = (lnot a n).[m]a, n:tH:log2 a < nm:tH0:m < n(ones n).[m] && negb a.[m] = (lnot a n).[m]a, n:tH:log2 a < nm:tH0:n <= mlog2 a < ma, n:tH:log2 a < nm:tH0:m < n(ones n).[m] && negb a.[m] = (lnot a n).[m]now rewrite ones_spec_low, lnot_spec_low. Qed.a, n:tH:log2 a < nm:tH0:m < n(ones n).[m] && negb a.[m] = (lnot a n).[m]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:tlor a (lnot a n) == lor a (ones n)a, n, m:ta.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]a, n, m:tH:n <= ma.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]a, n, m:tH:m < na.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]a, n, m:tH:n <= ma.[m] || a.[m] = a.[m] || falsea, n, m:tH:m < na.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]a, n, m:tH:m < na.[m] || (lnot a n).[m] = a.[m] || (ones n).[m]now destruct a.[m]. Qed.a, n, m:tH:m < na.[m] || negb a.[m] = a.[m] || trueforall a n : t, log2 a < n -> lor a (lnot a n) == ones nforall a n : t, log2 a < n -> lor a (lnot a n) == ones nnow rewrite lor_lnot_diag, lor_ones_low. Qed.a, n:tH:log2 a < nlor a (lnot a n) == ones nforall 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:tland a (lnot a n) == ldiff a (ones n)a, n, m:ta.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]a, n, m:tH:n <= ma.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]a, n, m:tH:m < na.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]a, n, m:tH:n <= ma.[m] && a.[m] = a.[m] && negb falsea, n, m:tH:m < na.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]a, n, m:tH:m < na.[m] && (lnot a n).[m] = a.[m] && negb (ones n).[m]now destruct a.[m]. Qed.a, n, m:tH:m < na.[m] && negb a.[m] = a.[m] && negb trueforall a n : t, log2 a < n -> land a (lnot a n) == 0forall a n : t, log2 a < n -> land a (lnot a n) == 0now rewrite land_lnot_diag, ldiff_ones_r_low. Qed.a, n:tH:log2 a < nland a (lnot a n) == 0forall 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:tHa:log2 a < nHb:log2 b < nlnot (lor a b) n == land (lnot a n) (lnot b n)a, b, n:tHa:log2 a < nHb:log2 b < nm:t(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= m(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 b < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH: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.a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (lor a b) n).[m] = (lnot a n).[m] && (lnot b n).[m]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:tHa:log2 a < nHb:log2 b < nlnot (land a b) n == lor (lnot a n) (lnot b n)a, b, n:tHa:log2 a < nHb:log2 b < nm:t(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= m(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 b < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH: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.a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (land a b) n).[m] = (lnot a n).[m] || (lnot b n).[m]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:tHa:log2 a < nldiff a b == land a (lnot b n)a, b, n:tHa:log2 a < nm:ta.[m] && negb b.[m] = a.[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nm:tH:n <= ma.[m] && negb b.[m] = a.[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nm:tH:m < na.[m] && negb b.[m] = a.[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nm:tH:n <= mfalse && negb b.[m] = false && (lnot b n).[m]a, b, n:tHa:log2 a < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nm:tH:m < na.[m] && negb b.[m] = a.[m] && (lnot b n).[m]a, b, n:tHa:log2 a < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nm:tH:m < na.[m] && negb b.[m] = a.[m] && (lnot b n).[m]rewrite !lnot_spec_low; trivial. Qed.a, b, n:tHa:log2 a < nm:tH:m < na.[m] && negb b.[m] = a.[m] && (lnot b n).[m]forall a b n : t, log2 a < n -> log2 b < n -> lnot (ldiff a b) n == lor (lnot a n) bforall a b n : t, log2 a < n -> log2 b < n -> lnot (ldiff a b) n == lor (lnot a n) ba, b, n:tHa:log2 a < nHb:log2 b < nlnot (ldiff a b) n == lor (lnot a n) ba, b, n:tHa:log2 a < nHb:log2 b < nm:t(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= m(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 b < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:n <= mlog2 a < ma, b, n:tHa:log2 a < nHb:log2 b < nm:tH: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.a, b, n:tHa:log2 a < nHb:log2 b < nm:tH:m < n(lnot (ldiff a b) n).[m] = (lnot a n).[m] || b.[m]forall a b n : t, lxor (lnot a n) (lnot b n) == lxor a bforall a b n : t, lxor (lnot a n) (lnot b n) == lxor a ba, b, n:tlxor (lnot a n) (lnot b n) == lxor a ba, b, n, m:txorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]a, b, n, m:tH:n <= mxorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]a, b, n, m:tH:m < nxorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]rewrite !lnot_spec_low, xorb_negb_negb; trivial. Qed.a, b, n, m:tH:m < nxorb (lnot a n).[m] (lnot b n).[m] = xorb a.[m] b.[m]forall a b n : t, lnot (lxor a b) n == lxor (lnot a n) bforall a b n : t, lnot (lxor a b) n == lxor (lnot a n) ba, b, n:tlnot (lxor a b) n == lxor (lnot a n) ba, b, n, m:t(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]a, b, n, m:tH:n <= m(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]a, b, n, m:tH: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.a, b, n, m:tH:m < n(lnot (lxor a b) n).[m] = xorb (lnot a n).[m] b.[m]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:tlnot (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:tH:n <= m(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]a, b, n, m:tH: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.a, b, n, m:tH:m < n(lnot (lxor a b) n).[m] = xorb a.[m] (lnot b n).[m]forall a b : t, land a b == 0 -> lxor a b == lor a bforall a b : t, land a b == 0 -> lxor a b == lor a ba, b:tH:land a b == 0lxor a b == lor a ba, b:tH:land a b == 0m:txorb a.[m] b.[m] = a.[m] || b.[m]now destruct a.[m], b.[m]. Qed.a, b:tH:land a b == 0m:tH0:a.[m] && b.[m] = falsexorb a.[m] b.[m] = a.[m] || b.[m]
Bitwise operations and log2
forall a n : t, a.[n] = true -> (forall m : t, n < m -> a.[m] = false) -> log2 a == nforall a n : t, a.[n] = true -> (forall m : t, n < m -> a.[m] = false) -> log2 a == na, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falselog2 a == na, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:a == 0log2 a == na, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < alog2 a == na, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < alog2 a == na, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < aLT:n < log2 aFalsea, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < aLT:log2 a < nFalsea, n:tH:a.[n] = trueH':a.[log2 a] = falseHa:0 < aLT:n < log2 aFalsea, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < aLT:log2 a < nFalsenow rewrite bits_above_log2 in H by order. Qed.a, n:tH:a.[n] = trueH':forall m : t, n < m -> a.[m] = falseHa:0 < aLT:log2 a < nFalseforall a n : t, log2 (a >> n) == log2 a - nforall a n : t, log2 (a >> n) == log2 a - na, n:tlog2 (a >> n) == log2 a - na, n:tHa:a == 0log2 (a >> n) == log2 a - na, n:tHa:0 < alog2 (a >> n) == log2 a - na, n:tHa:0 < alog2 (a >> n) == log2 a - na, n:tHa:0 < aH:log2 a < nlog2 (a >> n) == log2 a - na, n:tHa:0 < aH:n <= log2 alog2 (a >> n) == log2 a - na, n:tHa:0 < aH:log2 a < n0 == log2 a - na, n:tHa:0 < aH:n <= log2 alog2 (a >> n) == log2 a - na, n:tHa:0 < aH:log2 a < nlog2 a - n == 0a, n:tHa:0 < aH:n <= log2 alog2 (a >> n) == log2 a - na, n:tHa:0 < aH:n <= log2 alog2 (a >> n) == log2 a - na, n:tHa:0 < aH:n <= log2 a(a >> n).[log2 a - n] = truea, n:tHa:0 < aH:n <= log2 aforall m : t, log2 a - n < m -> (a >> n).[m] = falsea, n:tHa:0 < aH:n <= log2 aforall m : t, log2 a - n < m -> (a >> n).[m] = falsea, n:tHa:0 < aH:n <= log2 am:tHm:log2 a - n < m(a >> n).[m] = falsea, n:tHa:0 < aH:n <= log2 am:tHm:log2 a - n < ma.[m + n] = falsenow apply lt_sub_lt_add_r. Qed.a, n:tHa:0 < aH:n <= log2 am:tHm:log2 a - n < mlog2 a < m + nforall a n : t, a ~= 0 -> log2 (a << n) == log2 a + nforall a n : t, a ~= 0 -> log2 (a << n) == log2 a + na, n:tHa:a ~= 0log2 (a << n) == log2 a + na, n:tHa:a ~= 0log2 (a * 2 ^ n) == n + log2 aa, n:tHa:a ~= 00 < aa, n:tHa:a ~= 00 <= napply le_0_l. Qed.a, n:tHa:a ~= 00 <= nforall 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 bAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= blog2 (lor a b) == log2 bAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:a == 0log2 (lor a b) == log2 ba, b:tH:a <= bHa:0 < alog2 (lor a b) == log2 bAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:0 < alog2 (lor a b) == log2 bAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:0 < a(lor a b).[log2 b] = truea, b:tH:a <= bHa:0 < aforall m : t, log2 b < m -> (lor a b).[m] = falseAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:0 < aforall m : t, log2 b < m -> (lor a b).[m] = falseAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:0 < am:tHm:log2 b < m(lor a b).[m] = falseAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)a, b:tH:a <= bHa:0 < am:tHm:log2 b < mH':log2 a <= log2 b(lor a b).[m] = falseAUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)(* main *)AUX:forall a b : t, a <= b -> log2 (lor a b) == log2 bforall a b : t, log2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tlog2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:a <= blog2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:b <= alog2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:a <= blog2 (lor a b) == log2 bAUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:b <= alog2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:b <= alog2 (lor a b) == max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:b <= alog2 (lor a b) == log2 anow apply AUX. Qed.AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lor a0 b0) == log2 b0a, b:tH:b <= alog2 (lor b a) == log2 aforall 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 aAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= blog2 (land a b) <= log2 aAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= b~ log2 a < log2 (land a b)AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':log2 a < log2 (land a b)FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':log2 a < log2 (land a b)EQ:land a b == 0Falsea, b:tH:a <= bH':log2 a < log2 (land a b)NEQ:land a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':log2 a < log2 0EQ:land a b == 0Falsea, b:tH:a <= bH':log2 a < log2 (land a b)NEQ:land a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':a < 0EQ:land a b == 0Falsea, b:tH:a <= bH':log2 a < log2 (land a b)NEQ:land a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':log2 a < log2 (land a b)NEQ:land a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)a, b:tH:a <= bH':log2 a < log2 (land a b)NEQ:land a b ~= 0(land a b).[log2 (land a b)] = true -> FalseAUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)(* main *)AUX:forall a b : t, a <= b -> log2 (land a b) <= log2 aforall a b : t, log2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tlog2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:a <= blog2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:b <= alog2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:a <= blog2 (land a b) <= log2 aAUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:b <= alog2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:b <= alog2 (land a b) <= min (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:b <= alog2 (land a b) <= log2 bnow apply AUX. Qed.AUX:forall a0 b0 : t, a0 <= b0 -> log2 (land a0 b0) <= log2 a0a, b:tH:b <= alog2 (land b a) <= log2 bforall 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 bAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= blog2 (lxor a b) <= log2 bAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= b~ log2 b < log2 (lxor a b)AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)EQ:lxor a b == 0Falsea, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 0EQ:lxor a b == 0Falsea, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':b < 0EQ:lxor a b == 0Falsea, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0(lxor a b).[log2 (lxor a b)] = true -> FalseAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0xorb false false = true -> Falsea, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0log2 a < log2 (lxor a b)AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0log2 a < log2 (lxor a b)AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)a, b:tH:a <= bH':log2 b < log2 (lxor a b)NEQ:lxor a b ~= 0log2 a <= log2 bAUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)(* main *)AUX:forall a b : t, a <= b -> log2 (lxor a b) <= log2 bforall a b : t, log2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tlog2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:a <= blog2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:b <= alog2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:a <= blog2 (lxor a b) <= log2 bAUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:b <= alog2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:b <= alog2 (lxor a b) <= max (log2 a) (log2 b)AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:b <= alog2 (lxor a b) <= log2 anow apply AUX. Qed.AUX:forall a0 b0 : t, a0 <= b0 -> log2 (lxor a0 b0) <= log2 b0a, b:tH:b <= alog2 (lxor b a) <= log2 a
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]now rewrite !bit0_odd, odd_add. Qed.a, b:t(a + b).[0] = xorb a.[0] b.[0]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]now rewrite !add_bit0. Qed.a, b, c:t(a + b + c).[0] = xor3 a.[0] b.[0] c.[0]forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0H:1 + 1 == 2forall a0 b0 c0 : bool, (a0 + b0 + c0) / 2 == nextcarry a0 b0 c0H:1 + 1 == 2(2 + 1) / 2 == 1H:1 + 1 == 21 == (2 + 1) / 2H:1 + 1 == 21 < 2H:1 + 1 == 22 + 1 == 2 * 1 + 1now nzsimpl'. Qed.H:1 + 1 == 22 + 1 == 2 * 1 + 1forall (a b : t) (c0 : bool), (a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0forall (a b : t) (c0 : bool), (a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0a, b:tc0:bool(a + b + c0) / 2 == a / 2 + b / 2 + nextcarry a.[0] b.[0] c0a, b:tc0:bool(a + b + c0) / 2 == a / 2 + b / 2 + (a.[0] + b.[0] + c0) / 2a, b:tc0:bool(a + b + c0) / 2 == (a.[0] + b.[0] + c0) / 2 + (a / 2 + b / 2)a, b:tc0:bool(a + b + c0) / 2 == (a.[0] + b.[0] + c0 + (a / 2 + b / 2) * 2) / 2a, b:tc0:boola + b + c0 == a.[0] + b.[0] + c0 + (a / 2 + b / 2) * 2a, b:tc0:boola + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)a, b:tc0:bool2 * div2 a + a.[0] + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)a, b:tc0:bool2 * div2 a + a.[0] + b + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)a, b:tc0:bool2 * div2 a + a.[0] + (2 * div2 b + b.[0]) + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)a, b:tc0:bool2 * div2 a + a.[0] + (2 * div2 b + b.[0]) + c0 == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)a, b:tc0:bool2 * 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.a, b:tc0:bool2 * div2 a + 2 * div2 b + (a.[0] + b.[0] + c0) == a.[0] + b.[0] + c0 + (2 * div2 a + 2 * div2 b)
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] = c0forall (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:tc0:boolexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:texists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:ta < 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:ta < 2 ^ aa, b:tc0:booln:=max a b:t2 ^ a <= 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:t2 ^ a <= 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:t2 ~= 0a, b:tc0:booln:=max a b:ta <= na, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:ta <= na, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:ta <= max a ba, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nb < 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nb < 2 ^ ba, b:tc0:booln:=max a b:tHa:a < 2 ^ n2 ^ b <= 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ n2 ^ b <= 2 ^ na, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ n2 ~= 0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nb <= na, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nb <= na, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nb <= max a ba, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:=max a b:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0a, b:tc0:booln:tHa:a < 2 ^ nHb:b < 2 ^ nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0n:tforall (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(*base*)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] = c0forall 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] = c0a, b:tc0:boola < 2 ^ 0 -> b < 2 ^ 0 -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0forall 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] = c0a, b:tc0:boola <= 0 -> b <= 0 -> exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0forall 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] = c0a, b:tc0:boolHa:a <= 0Hb:b <= 0exists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0forall 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] = c0a, b:tc0:boolHa:a <= 0Hb:b <= 0a + b + c0 == lxor3 a b c0 /\ c0 / 2 == lnextcarry a b c0 /\ c0.[0] = c0forall 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] = c0a, b:tc0:boolHa:a <= 0Hb:b <= 00 + b + c0 == lxor3 0 b c0 /\ c0 / 2 == lnextcarry 0 b c0 /\ c0.[0] = c0forall 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] = c0a, b:tc0:boolHa:a <= 0Hb:b <= 00 + 0 + c0 == lxor3 0 0 c0 /\ c0 / 2 == lnextcarry 0 0 c0 /\ c0.[0] = c0forall 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] = c0a, b:tc0:boolHa:a <= 0Hb:b <= 0c0 == c0 /\ c0 / 2 == 0 /\ c0.[0] = c0forall 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*)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] = c0n:tIH: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] = c1a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0n:tIH: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] = c2a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolexists c : t, a + b + c0 == lxor3 a b c /\ c / 2 == lnextcarry a b c /\ c.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boola / 2 < 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb / 2 < 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:bool2 ~= 0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boola < 2 * 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb / 2 < 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boola < 2 * 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb / 2 < 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb / 2 < 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:bool2 ~= 0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb < 2 * 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolb < 2 * 2 ^ nn, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1exists c2 : t, a + b + c0 == lxor3 a b c2 /\ c2 / 2 == lnextcarry a b c2 /\ c2.[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1a + b + c0 == lxor3 a b (c0 + 2 * c) /\ (c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c) /\ (c0 + 2 * c).[0] = c0(* - add *)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1a + b + c0 == lxor3 a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m:t(a + b + c0).[m] = xor3 a.[m] b.[m] (c0 + 2 * c).[m]n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m:t(a + b + c0).[0] = xor3 a.[0] b.[0] (c0 + 2 * c).[0]n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t(a + b + c0).[S m'] = xor3 a.[S m'] b.[S m'] (c0 + 2 * c).[S m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t(a + b + c0).[S m'] = xor3 a.[S m'] b.[S m'] (c0 + 2 * c).[S m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t((a + b + c0) / 2).[m'] = (lxor3 (a / 2) (b / 2) ((c0 + 2 * c) / 2)).[m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t(a + b + c0) / 2 == lxor3 (a / 2) (b / 2) ((c0 + 2 * c) / 2)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t(a + b + c0) / 2 == a / 2 + b / 2 + c1n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0(* - carry *)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c) / 2 == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1c == lnextcarry a b (c0 + 2 * c)n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m:tc.[m] = nextcarry a.[m] b.[m] (c0 + 2 * c).[m]n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m:tc.[0] = nextcarry a.[0] b.[0] (c0 + 2 * c).[0]n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':tc.[S m'] = nextcarry a.[S m'] b.[S m'] (c0 + 2 * c).[S m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':tc.[S m'] = nextcarry a.[S m'] b.[S m'] (c0 + 2 * c).[S m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':t(lnextcarry (a / 2) (b / 2) c).[m'] = nextcarry (a / 2).[m'] (b / 2).[m'] ((c0 + 2 * c) / 2).[m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1m, m':tnextcarry (a / 2).[m'] (b / 2).[m'] c.[m'] = nextcarry (a / 2).[m'] (b / 2).[m'] ((c0 + 2 * c) / 2).[m']n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0(* - carry0 *) apply add_b2n_double_bit0. Qed.n, a, b:tc0:boolHa:a < 2 ^ S nHb:b < 2 ^ S nc1:=nextcarry a.[0] b.[0] c0:boolc:tIH1:a / 2 + b / 2 + c1 == lxor3 (a / 2) (b / 2) cIH2:c / 2 == lnextcarry (a / 2) (b / 2) cHc:c.[0] = c1(c0 + 2 * c).[0] = c0
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:tEQ1:a + b + false == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = false(a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = false(a + b).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = false(lxor3 a b c).[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsexor3 a.[1] b.[1] c.[1] = xor3 a.[1] b.[1] (a.[0] && b.[0])a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsec.[1] = a.[0] && b.[0]a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = false(lnextcarry a b c).[0] = a.[0] && b.[0]a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsenextcarry a.[0] b.[0] c.[0] = a.[0] && b.[0]a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsenextcarry a.[0] b.[0] false = a.[0] && b.[0]apply orb_false_r. Qed.a, b, c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsea.[0] && b.[0] || false = a.[0] && b.[0]
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 == 0forall a b c : t, c / 2 == lnextcarry a b c -> c.[0] = false -> c == 0 <-> land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falsec == 0 <-> land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falsec == 0 -> land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseland a b == 0 -> c == 0a, b, c:tH:0 / 2 == lnextcarry a b 0H':0.[0] = falseEQ:c == 0land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseland a b == 0 -> c == 0a, b, c:tH:0 == lnextcarry a b 0H':0.[0] = falseEQ:c == 0land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseland a b == 0 -> c == 0a, b, c:tH:lnextcarry a b 0 == 0H':0.[0] = falseEQ:c == 0land a b == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseland a b == 0 -> c == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseland a b == 0 -> c == 0a, b, c:tH:c / 2 == lnextcarry a b cH':c.[0] = falseEQ:land a b == 0c == 0a, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0c == 0a, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0forall n : t, c.[n] = falsea, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0c.[0] = falsea, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0forall n : t, c.[n] = false -> c.[S n] = falsea, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0forall n : t, c.[n] = false -> c.[S n] = falsea, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0n:tIH:c.[n] = falsec.[S n] = falsea, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0n:tIH:c.[n] = false(land c (lor a b)).[n] = falsenow rewrite IH. Qed.a, b, c:tH:c / 2 == land c (lor a b)H':c.[0] = falseEQ:land a b == 0n:tIH:c.[n] = falsec.[n] && (a.[n] || b.[n]) = false
When there is no common bits, the addition is just a xor
forall a b : t, land a b == 0 -> a + b == lxor a bforall a b : t, land a b == 0 -> a + b == lxor a ba, b:tH:land a b == 0a + b == lxor a ba, b:tH:land a b == 0c:tEQ1:a + b + false == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsea + b == lxor a ba, b:tH:land a b == 0c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falsea + b == lxor a ba, b:tH:land a b == 0c:tEQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falselxor3 a b c == lxor a ba, b, c:tH:c == 0EQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falselxor3 a b c == lxor a bnow rewrite lxor_0_r. Qed.a, b, c:tH:c == 0EQ1:a + b == lxor3 a b cEQ2:c / 2 == lnextcarry a b cHc:c.[0] = falselxor3 a b 0 == lxor a b
A null ldiff implies being smaller
forall a b : t, ldiff a b == 0 -> a <= bforall 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 <= bforall n a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= bH:forall n a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tldiff a b == 0 -> a <= bforall n a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= bforall n a b : t, a < 2 ^ n -> ldiff a b == 0 -> a <= bforall a b : t, a < 2 ^ 0 -> ldiff a b == 0 -> a <= bforall 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 <= ba, b:tHa:a < 2 ^ 0a <= bforall 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 <= ba, b:tHa:a <= 0a <= bforall 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 <= ba, b:tHa:a <= 0Ha':a == 0a <= bforall 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 <= ba, b:tHa:a <= 0Ha':a == 00 <= bforall 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 <= bforall 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 <= bn:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0a <= bn:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a <= bn:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 02 * (a / 2) + a mod 2 <= 2 * (b / 2) + b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 02 * (a / 2) <= 2 * (b / 2)n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a / 2 <= b / 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a / 2 < 2 ^ nn:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0ldiff (a / 2) (b / 2) == 0n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a < 2 * 2 ^ nn:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0ldiff (a / 2) (b / 2) == 0n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0ldiff (a / 2) (b / 2) == 0n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0ldiff (a >> 1) (b >> 1) == 0n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a mod 2 <= b mod 2n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:ldiff a b == 0NEQ:2 ~= 0a.[0] <= b.[0]n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:testbit (ldiff a b) === testbit 0NEQ:2 ~= 0a.[0] <= b.[0]n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:(ldiff a b).[0] = 0.[0]NEQ:2 ~= 0a.[0] <= b.[0]destruct a.[0], b.[0]; try discriminate; simpl; order'. Qed.n:tIH:forall a0 b0 : t, a0 < 2 ^ n -> ldiff a0 b0 == 0 -> a0 <= b0a, b:tHa:a < 2 ^ S nH:a.[0] && negb b.[0] = falseNEQ:2 ~= 0a.[0] <= b.[0]
Subtraction can be a ldiff when the opposite ldiff is null.
forall a b : t, ldiff b a == 0 -> a - b == ldiff a bforall a b : t, ldiff b a == 0 -> a - b == ldiff a ba, b:tH:ldiff b a == 0a - b == ldiff a ba, b:tH:ldiff b a == 0a - b + b == ldiff a b + ba, b:tH:ldiff b a == 0a == ldiff a b + ba, b:tH:ldiff b a == 0b <= aa, b:tH:ldiff b a == 0ldiff a b + b == aa, b:tH:ldiff b a == 0b <= aa, b:tH:ldiff b a == 0lxor (ldiff a b) b == aa, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= aa, b:tH:ldiff b a == 0m:txorb (a.[m] && negb b.[m]) b.[m] = a.[m]a, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= aa, b:tH:testbit (ldiff b a) === testbit 0m:txorb (a.[m] && negb b.[m]) b.[m] = a.[m]a, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= aa, b, m:tH:(ldiff b a).[m] = 0.[m]xorb (a.[m] && negb b.[m]) b.[m] = a.[m]a, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= aa, b, m:tH:b.[m] && negb a.[m] = falsexorb (a.[m] && negb b.[m]) b.[m] = a.[m]a, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= aa, b:tH:ldiff b a == 0land (ldiff a b) b == 0a, b:tH:ldiff b a == 0b <= anow apply ldiff_le. Qed.a, b:tH:ldiff b a == 0b <= a
We can express lnot in term of subtraction
forall a n : t, log2 a < n -> a + lnot a n == ones nforall a n : t, log2 a < n -> a + lnot a n == ones na, n:tH:log2 a < na + lnot a n == ones na, n:tH:log2 a < nH':land a (lnot a n) == 0a + lnot a n == ones nnow apply lor_lnot_diag_low. Qed.a, n:tH:log2 a < nH':land a (lnot a n) == 0lor a (lnot a n) == ones nforall a n : t, log2 a < n -> lnot a n == ones n - aforall a n : t, log2 a < n -> lnot a n == ones n - anow rewrite <- (add_lnot_diag_low a n H), add_comm, add_sub. Qed.a, n:tH:log2 a < nlnot a n == ones n - a
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 ^ nforall a b n : t, land a b == 0 -> a < 2 ^ n -> b < 2 ^ n -> a + b < 2 ^ na, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ na + b < 2 ^ na, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ nlxor a b < 2 ^ na, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ n2 ^ n ~= 0a, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ nlxor a b / 2 ^ n == 0a, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ nlxor a b / 2 ^ n == 0a, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ nlxor (a / 2 ^ n) (b / 2 ^ n) == 0apply lxor_0_l. Qed.a, b, n:tH:land a b == 0Ha:a < 2 ^ nHb:b < 2 ^ nlxor 0 0 == 0forall a b n : t, land a b == 0 -> a mod 2 ^ n + b mod 2 ^ n < 2 ^ nforall a b n : t, land a b == 0 -> a mod 2 ^ n + b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0a mod 2 ^ n + b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0land (a mod 2 ^ n) (b mod 2 ^ n) == 0a, b, n:tH:land a b == 0a mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0m:t(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = falsea, b, n:tH:land a b == 0a mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0m:tH0:n <= m(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = falsea, b, n:tH:land a b == 0m:tH0:m < n(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = falsea, b, n:tH:land a b == 0a mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0m:tH0:m < n(a mod 2 ^ n).[m] && (b mod 2 ^ n).[m] = falsea, b, n:tH:land a b == 0a mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0a mod 2 ^ n < 2 ^ na, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ napply mod_upper_bound; order_nz. Qed. End NBitsProp.a, b, n:tH:land a b == 0b mod 2 ^ n < 2 ^ n