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 *)
(** 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.
Local Coercion b2n : bool >-> t.
Instance b2n_proper : Proper (Logic.eq ==> eq) b2n.
(** We can compact [testbit_odd_0] [testbit_even_0] [testbit_even_succ] [testbit_odd_succ] in only two lemmas. *)
(** 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 *)
(** 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... *)
(** Results about the injection [b2n] *)
(** The specification of testbit by low and high parts is complete *)
(** All bits of number 0 are 0 *)
(** 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 *)
(** 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 *)
(** 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. *)
Definition eqf (f g:t -> bool) := forall n:t, f n = g n.
Instance eqf_equiv : Equivalence eqf.
Local Infix "===" := eqf (at level 70, no associativity).
Instance testbit_eqf : Proper (eq==>eqf) testbit.
(** Only zero corresponds to the always-false stream. *)
(** If two numbers produce the same stream of bits, they are equal. *)
Hint Rewrite lxor_spec lor_spec land_spec ldiff_spec bits_0 : bitwise.
Ltac bitwise := apply bits_inj; intros ?m; autorewrite with bitwise.
(** The streams of bits that correspond to a natural numbers are exactly the ones that are always 0 after some point *)
(** Properties of shifts *)
Instance shiftr_wd : Proper (eq==>eq==>eq) shiftr.
Instance shiftl_wd : Proper (eq==>eq==>eq) shiftl.
(** shifts and constants *)
(** Properties of [div2]. *)
Instance div2_wd : Proper (eq==>eq) 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.
(** Properties of [setbit] and [clearbit] *)
Definition setbit a n := lor a (1<<n).
Definition clearbit a n := ldiff a (1<<n).
Instance setbit_wd : Proper (eq==>eq==>eq) setbit.
(** Shifts of bitwise operations *)
(** 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).
Instance ones_wd : Proper (eq==>eq) ones.
(** Bounded complement and other operations *)
(** Bitwise operations and log2 *)
(** Bitwise operations and arithmetical operations *)
Local Notation xor3 a b c := (xorb (xorb a b) c).
Local Notation lxor3 a b c := (lxor (lxor a b) c).
Local Notation nextcarry a b c := ((a&&b) || (c && (a||b))).
Local Notation lnextcarry a b c := (lor (land a b) (land c (lor a 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. *)
(** 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. *)
(** We can express lnot in term of subtraction *)

Lemma lnot_sub_low : forall a n, log2 a < n ->
lnot a n == ones n - a.