Library Coq.Numbers.Integer.Abstract.ZBits
Derived properties of bitwise operations
Some properties of power and division
An injection from bits true and false to numbers 1 and 0.
We declare it as a (local) coercion for shorter statements.
We can compact testbit_odd_0 testbit_even_0
testbit_even_succ testbit_odd_succ in only two lemmas.
Alternative caracterisations 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
This caracterisation 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 caracterisation
is moderatly complex to implement, but also moderately
usable...
Results about the injection b2z
The specification of testbit by low and high parts is complete
All bits of number 0 are 0
For negative numbers, we are actually doing two's complement
All bits of number (-1) are 1
Various ways to refer to the lowest bit of a number
Hence testing a bit is equivalent to shifting and testing parity
log2 gives the highest nonzero bit of positive numbers
Hence the number of bits of
a is
1+log2 a
(see
Pos.size_nat and
Pos.size).
For negative numbers, things are the other ways around:
log2 gives the highest zero bit (for numbers below -1).
Accesing a high enough bit of a number gives its sign
Lemma bits_iff_nonneg :
forall a n,
log2 (
abs a)
< n ->
(0
<=a <-> a.[n] = false).
Lemma bits_iff_nonneg´ :
forall a,
0
<=a <-> a.[S (
log2 (
abs a))
] = false.
Lemma bits_iff_nonneg_ex :
forall a,
0
<=a <-> (exists k, forall m,
k<m ->
a.[m] = false).
Lemma bits_iff_neg :
forall a n,
log2 (
abs a)
< n ->
(
a<0
<-> a.[n] = true).
Lemma bits_iff_neg´ :
forall a,
a<0
<-> a.[S (
log2 (
abs a))
] = true.
Lemma bits_iff_neg_ex :
forall a,
a<0
<-> (exists k, forall m,
k<m ->
a.[m] = true).
Testing bits after division or multiplication by a power of two
Selecting the low part of a number can be done by a modulo
We now prove that having the same bits implies equality.
For that we use a notion of equality over functional
streams of bits.
Only zero corresponds to the always-false stream.
If two numbers produce the same stream of bits, they are equal.
In fact, checking the bits at positive indexes is enough.
The streams of bits that correspond to a numbers are
exactly the ones which are stationary after some point.
Properties of shifts
First, a unified specification for
shiftl : the
shiftl_spec
below (combined with
testbit_neg_r) is equivalent to
shiftl_spec_low and
shiftl_spec_high.
A shiftl by a negative number is a shiftr, and vice-versa
Shifts correspond to multiplication or division by a power of two
Shifts are morphisms
We could also have specified shiftl with an addition on the left.
Chaining several shifts. The only case for which
there isn't any simple expression is a true shiftr
followed by a true shiftl.
shifts and constants
Properties of div2.
Properties of lxor and others, directly deduced
from properties of xorb and others.
Instance lxor_wd :
Proper (
eq ==> eq ==> eq)
lxor.
Instance land_wd :
Proper (
eq ==> eq ==> eq)
land.
Instance lor_wd :
Proper (
eq ==> eq ==> eq)
lor.
Instance ldiff_wd :
Proper (
eq ==> eq ==> eq)
ldiff.
Lemma lxor_eq :
forall a a´,
lxor a a´ == 0 ->
a == a´.
Lemma lxor_nilpotent :
forall a,
lxor a a == 0.
Lemma lxor_eq_0_iff :
forall a a´,
lxor a a´ == 0
<-> a == a´.
Lemma lxor_0_l :
forall a,
lxor 0
a == a.
Lemma lxor_0_r :
forall a,
lxor a 0
== a.
Lemma lxor_comm :
forall a b,
lxor a b == lxor b a.
Lemma lxor_assoc :
forall a b c,
lxor (
lxor a b)
c == lxor a (
lxor b c).
Lemma lor_0_l :
forall a,
lor 0
a == a.
Lemma lor_0_r :
forall a,
lor a 0
== a.
Lemma lor_comm :
forall a b,
lor a b == lor b a.
Lemma lor_assoc :
forall a b c,
lor a (
lor b c)
== lor (
lor a b)
c.
Lemma lor_diag :
forall a,
lor a a == a.
Lemma lor_eq_0_l :
forall a b,
lor a b == 0 ->
a == 0.
Lemma lor_eq_0_iff :
forall a b,
lor a b == 0
<-> a == 0
/\ b == 0.
Lemma land_0_l :
forall a,
land 0
a == 0.
Lemma land_0_r :
forall a,
land a 0
== 0.
Lemma land_comm :
forall a b,
land a b == land b a.
Lemma land_assoc :
forall a b c,
land a (
land b c)
== land (
land a b)
c.
Lemma land_diag :
forall a,
land a a == a.
Lemma ldiff_0_l :
forall a,
ldiff 0
a == 0.
Lemma ldiff_0_r :
forall a,
ldiff a 0
== a.
Lemma ldiff_diag :
forall a,
ldiff a a == 0.
Lemma lor_land_distr_l :
forall a b c,
lor (
land a b)
c == land (
lor a c) (
lor b c).
Lemma lor_land_distr_r :
forall a b c,
lor a (
land b c)
== land (
lor a b) (
lor a c).
Lemma land_lor_distr_l :
forall a b c,
land (
lor a b)
c == lor (
land a c) (
land b c).
Lemma land_lor_distr_r :
forall a b c,
land a (
lor b c)
== lor (
land a b) (
land a c).
Lemma ldiff_ldiff_l :
forall a b c,
ldiff (
ldiff a b)
c == ldiff a (
lor b c).
Lemma lor_ldiff_and :
forall a b,
lor (
ldiff a b) (
land a b)
== a.
Lemma land_ldiff :
forall a b,
land (
ldiff a b)
b == 0.
Properties of setbit and clearbit
Definition setbit a n :=
lor a (1
<< n).
Definition clearbit a n :=
ldiff a (1
<< n).
Lemma setbit_spec´ :
forall a n,
setbit a n == lor a (2
^n).
Lemma clearbit_spec´ :
forall a n,
clearbit a n == ldiff a (2
^n).
Instance setbit_wd :
Proper (
eq==>eq==>eq)
setbit.
Instance clearbit_wd :
Proper (
eq==>eq==>eq)
clearbit.
Lemma pow2_bits_true :
forall n, 0
<=n ->
(2
^n).[n] = true.
Lemma pow2_bits_false :
forall n m,
n~=m ->
(2
^n).[m] = false.
Lemma pow2_bits_eqb :
forall n m, 0
<=n ->
(2
^n).[m] = eqb n m.
Lemma setbit_eqb :
forall a n m, 0
<=n ->
(setbit a n).[m] = eqb n m || a.[m].
Lemma setbit_iff :
forall a n m, 0
<=n ->
(
(setbit a n).[m] = true <-> n==m \/ a.[m] = true).
Lemma setbit_eq :
forall a n, 0
<=n ->
(setbit a n).[n] = true.
Lemma setbit_neq :
forall a n m, 0
<=n ->
n~=m ->
(setbit a n).[m] = a.[m].
Lemma clearbit_eqb :
forall a n m,
(clearbit a n).[m] = a.[m] && negb (
eqb n m).
Lemma clearbit_iff :
forall a n m,
(clearbit a n).[m] = true <-> a.[m] = true /\ n~=m.
Lemma clearbit_eq :
forall a n,
(clearbit a n).[n] = false.
Lemma clearbit_neq :
forall a n m,
n~=m ->
(clearbit a n).[m] = a.[m].
Shifts of bitwise operations
For integers, we do have a binary complement function
Complement and other operations
Lemma lor_m1_r :
forall a,
lor a (-1)
== -1.
Lemma lor_m1_l :
forall a,
lor (-1)
a == -1.
Lemma land_m1_r :
forall a,
land a (-1)
== a.
Lemma land_m1_l :
forall a,
land (-1)
a == a.
Lemma ldiff_m1_r :
forall a,
ldiff a (-1)
== 0.
Lemma ldiff_m1_l :
forall a,
ldiff (-1)
a == lnot a.
Lemma lor_lnot_diag :
forall a,
lor a (
lnot a)
== -1.
Lemma add_lnot_diag :
forall a,
a + lnot a == -1.
Lemma ldiff_land :
forall a b,
ldiff a b == land a (
lnot b).
Lemma land_lnot_diag :
forall a,
land a (
lnot a)
== 0.
Lemma lnot_lor :
forall a b,
lnot (
lor a b)
== land (
lnot a) (
lnot b).
Lemma lnot_land :
forall a b,
lnot (
land a b)
== lor (
lnot a) (
lnot b).
Lemma lnot_ldiff :
forall a b,
lnot (
ldiff a b)
== lor (
lnot a)
b.
Lemma lxor_lnot_lnot :
forall a b,
lxor (
lnot a) (
lnot b)
== lxor a b.
Lemma lnot_lxor_l :
forall a b,
lnot (
lxor a b)
== lxor (
lnot a)
b.
Lemma lnot_lxor_r :
forall a b,
lnot (
lxor a b)
== lxor a (
lnot b).
Lemma lxor_m1_r :
forall a,
lxor a (-1)
== lnot a.
Lemma lxor_m1_l :
forall a,
lxor (-1)
a == lnot a.
Lemma lxor_lor :
forall a b,
land a b == 0 ->
lxor a b == lor a b.
Lemma lnot_shiftr :
forall a n, 0
<=n ->
lnot (
a >> n)
== (lnot a) >> n.
(ones n) is 2^n-1, the number with n digits 1
Definition ones n :=
P (1
<<n).
Instance ones_wd :
Proper (
eq==>eq)
ones.
Lemma ones_equiv :
forall n,
ones n == P (2
^n).
Lemma ones_add :
forall n m, 0
<=n -> 0
<=m ->
ones (
m+n)
== 2
^m * ones n + ones m.
Lemma ones_div_pow2 :
forall n m, 0
<=m<=n ->
ones n / 2
^m == ones (
n-m).
Lemma ones_mod_pow2 :
forall n m, 0
<=m<=n ->
(ones n) mod (2
^m) == ones m.
Lemma ones_spec_low :
forall n m, 0
<=m<n ->
(ones n).[m] = true.
Lemma ones_spec_high :
forall n m, 0
<=n<=m ->
(ones n).[m] = false.
Lemma ones_spec_iff :
forall n m, 0
<=n ->
(
(ones n).[m] = true <-> 0
<=m<n).
Lemma lor_ones_low :
forall a n, 0
<=a ->
log2 a < n ->
lor a (
ones n)
== ones n.
Lemma land_ones :
forall a n, 0
<=n ->
land a (
ones n)
== a mod 2
^n.
Lemma land_ones_low :
forall a n, 0
<=a ->
log2 a < n ->
land a (
ones n)
== a.
Lemma ldiff_ones_r :
forall a n, 0
<=n ->
ldiff a (
ones n)
== (a >> n) << n.
Lemma ldiff_ones_r_low :
forall a n, 0
<=a ->
log2 a < n ->
ldiff a (
ones n)
== 0.
Lemma ldiff_ones_l_low :
forall a n, 0
<=a ->
log2 a < n ->
ldiff (
ones n)
a == lxor a (
ones n).
Bitwise operations and sign
Lemma shiftl_nonneg :
forall a n, 0
<= (a << n) <-> 0
<= a.
Lemma shiftl_neg :
forall a n,
(a << n) < 0
<-> a < 0.
Lemma shiftr_nonneg :
forall a n, 0
<= (a >> n) <-> 0
<= a.
Lemma shiftr_neg :
forall a n,
(a >> n) < 0
<-> a < 0.
Lemma div2_nonneg :
forall a, 0
<= div2 a <-> 0
<= a.
Lemma div2_neg :
forall a,
div2 a < 0
<-> a < 0.
Lemma lor_nonneg :
forall a b, 0
<= lor a b <-> 0
<=a /\ 0
<=b.
Lemma lor_neg :
forall a b,
lor a b < 0
<-> a < 0
\/ b < 0.
Lemma lnot_nonneg :
forall a, 0
<= lnot a <-> a < 0.
Lemma lnot_neg :
forall a,
lnot a < 0
<-> 0
<= a.
Lemma land_nonneg :
forall a b, 0
<= land a b <-> 0
<=a \/ 0
<=b.
Lemma land_neg :
forall a b,
land a b < 0
<-> a < 0
/\ b < 0.
Lemma ldiff_nonneg :
forall a b, 0
<= ldiff a b <-> 0
<=a \/ b<0.
Lemma ldiff_neg :
forall a b,
ldiff a b < 0
<-> a<0
/\ 0
<=b.
Lemma lxor_nonneg :
forall a b, 0
<= lxor a b <-> (0
<=a <-> 0
<=b).
Bitwise operations and log2
Bitwise operations and arithmetical operations
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.
Particular case : the second bit of an addition
In an addition, there will be no carries iff there is
no common bits in the numbers to add
When there is no common bits, the addition is just a xor
A null ldiff implies being smaller
Subtraction can be a ldiff when the opposite ldiff is null.
Adding numbers with no common bits cannot lead to a much bigger number