Section EQ_MODULO.
Variable modul: Z.
Hypothesis modul_pos: modul > 0.
Definition eqmod (x y: Z) : Prop := exists k, x = k * modul + y.
End EQ_MODULO.
(** ** Fast normalization modulo [2^n] *)
Fixpoint P_mod_two_p (p: positive) (n: nat) {struct n} : Z :=
match n with
| O => 0
| S m =>
match p with
| xH => 1
| xO q => Z.double (P_mod_two_p q m)
| xI q => Z.succ_double (P_mod_two_p q m)
end
end.
Definition Z_mod_two_p (x: Z) (n: nat) : Z :=
match x with
| Z0 => 0
| Zpos p => P_mod_two_p p n
| Zneg p => let r := P_mod_two_p p n in if zeq r 0 then 0 else two_power_nat n - r
end.
(** ** Bit-level operations and properties *)
(** Shift [x] left by one and insert [b] as the low bit of the result. *)
Definition Zshiftin (b: bool) (x: Z) : Z :=
if b then Z.succ_double x else Z.double x.
Remark Ztestbit_0: forall n, Z.testbit 0 n = false.
Proof Z.testbit_0_l.
Remark Ztestbit_1: forall n, Z.testbit 1 n = zeq n 0.
Remark Ztestbit_m1: forall n, 0 <= n -> Z.testbit (-1) n = true.
Remark Zshiftin_spec:
forall b x, Zshiftin b x = 2 * x + (if b then 1 else 0).
Remark Zshiftin_inj:
forall b1 x1 b2 x2,
Zshiftin b1 x1 = Zshiftin b2 x2 -> b1 = b2 /\ x1 = x2.
Remark Zdecomp:
forall x, x = Zshiftin (Z.odd x) (Z.div2 x).
Remark Ztestbit_shiftin:
forall b x n,
0 <= n ->
Z.testbit (Zshiftin b x) n = if zeq n 0 then b else Z.testbit x (Z.pred n).
Remark Ztestbit_shiftin_base:
forall b x, Z.testbit (Zshiftin b x) 0 = b.
Remark Ztestbit_shiftin_succ:
forall b x n, 0 <= n -> Z.testbit (Zshiftin b x) (Z.succ n) = Z.testbit x n.
(** ** Bit-wise decomposition ([Z.testbit]) *)
Remark Ztestbit_eq:
forall n x, 0 <= n ->
Z.testbit x n = if zeq n 0 then Z.odd x else Z.testbit (Z.div2 x) (Z.pred n).
Remark Ztestbit_base:
forall x, Z.testbit x 0 = Z.odd x.
Remark Ztestbit_succ:
forall n x, 0 <= n -> Z.testbit x (Z.succ n) = Z.testbit (Z.div2 x) n.
Proof Z.bits_inj'.
(** ** Zero and sign extensions *)
(** In pseudo-code: << Fixpoint Zzero_ext (n: Z) (x: Z) : Z := if zle n 0 then 0 else Zshiftin (Z.odd x) (Zzero_ext (Z.pred n) (Z.div2 x)). Fixpoint Zsign_ext (n: Z) (x: Z) : Z := if zle n 1 then if Z.odd x then -1 else 0 else Zshiftin (Z.odd x) (Zzero_ext (Z.pred n) (Z.div2 x)). >> We encode this [nat]-like recursion using the [Z.iter] iteration function, in order to make the [Zzero_ext] and [Zsign_ext] functions efficiently executable within Coq. *)
Definition Zzero_ext (n: Z) (x: Z) : Z :=
Z.iter n
(fun rec x => Zshiftin (Z.odd x) (rec (Z.div2 x)))
(fun x => 0)
x.
Definition Zsign_ext (n: Z) (x: Z) : Z :=
Z.iter (Z.pred n)
(fun rec x => Zshiftin (Z.odd x) (rec (Z.div2 x)))
(fun x => if Z.odd x && zlt 0 n then -1 else 0)
x.
(** [Zzero_ext n x] is [x modulo 2^n] *)
(** [Zzero_ext n x] is the unique integer congruent to [x] modulo [2^n] in the range [0...2^n-1]. *)
(** Relation between [Zsign_ext n x] and (Zzero_ext n x] *)
(** [Zsign_ext n x] is the unique integer congruent to [x] modulo [2^n] in the range [-2^(n-1)...2^(n-1) - 1]. *)

Lemma Zsign_ext_range:
forall n x, 0 < n -> -two_p (n-1) <= Zsign_ext n x < two_p (n-1).