(** 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 lnot a n := lxor a (ones n).
#[global]
Instance ones_wd : Proper (eq==>eq) ones.

(* Specifications: *)
Lemma ones_0 : ones 0 == 0.
Lemma ones_add : forall n m, ones (m+n) == 2^m * ones n + ones m.
Lemma ones_div_pow2 : forall n m, m<=n -> ones n / 2^m == ones (n-m).
Lemma ones_mod_pow2 : forall n m, m<=n -> (ones n) mod (2^m) == ones m.
Lemma ones_spec_low : forall n m, m<n -> (ones n).[m] = true.
Lemma ones_spec_high : forall n m, n<=m -> (ones n).[m] = false.
Lemma ones_spec_iff : forall n m, (ones n).[m] = true <-> m<n.
Lemma lnot_spec_low : forall a n m, m<n ->
(lnot a n).[m] = negb a.[m].
Lemma lnot_spec_high : forall a n m, n<=m ->
(lnot a n).[m] = a.[m].
Lemma lnot_involutive : forall a n, lnot (lnot a n) n == a.
Lemma lnot_0_l : forall n, lnot 0 n == ones n.
Lemma lnot_ones : forall n, lnot (ones n) n == 0.
Lemma ones_succ : forall n, ones (S n) == 2 * (ones n) + 1.
(** Bounded complement and other operations *)
Lemma lor_ones_low : forall a n, log2 a < n ->
lor a (ones n) == ones n.
Lemma land_ones : forall a n, land a (ones n) == a mod 2^n.
Lemma land_ones_low : forall a n, log2 a < n ->
land a (ones n) == a.
Lemma ldiff_ones_r : forall a n,
ldiff a (ones n) == (a >> n) << n.
Lemma ldiff_ones_r_low : forall a n, log2 a < n ->
ldiff a (ones n) == 0.
Lemma ldiff_ones_l_low : forall a n, log2 a < n ->
ldiff (ones n) a == lnot a n.
Lemma lor_lnot_diag : forall a n,
lor a (lnot a n) == lor a (ones n).
Lemma lor_lnot_diag_low : forall a n, log2 a < n ->
lor a (lnot a n) == ones n.
Lemma land_lnot_diag : forall a n,
land a (lnot a n) == ldiff a (ones n).
Lemma land_lnot_diag_low : forall a n, log2 a < n ->
land a (lnot a n) == 0.
Lemma lnot_lor_low : forall a b n, log2 a < n -> log2 b < n ->
lnot (lor a b) n == land (lnot a n) (lnot b n).
Lemma lnot_land_low : forall a b n, log2 a < n -> log2 b < n ->
lnot (land a b) n == lor (lnot a n) (lnot b n).
Lemma ldiff_land_low : forall a b n, log2 a < n ->
ldiff a b == land a (lnot b n).
Lemma lnot_ldiff_low : forall a b n, log2 a < n -> log2 b < n ->
lnot (ldiff a b) n == lor (lnot a n) b.
Lemma lxor_lnot_lnot : forall a b n,
lxor (lnot a n) (lnot b n) == lxor a b.
Lemma lnot_lxor_l : forall a b n,
lnot (lxor a b) n == lxor (lnot a n) b.
Lemma lnot_lxor_r : forall a b n,
lnot (lxor a b) n == lxor a (lnot b n).
Lemma lxor_lor : forall a b, land a b == 0 ->
lxor a b == lor a b.