(* To avoid useless definitions of inductors in extracted code. *)
Local Unset Elimination Schemes.
Local Unset Case Analysis Schemes.
Module Make(WS: WORDSIZE).
Definition wordsize: nat := WS.wordsize.
Definition zwordsize: Z := Z.of_nat wordsize.
Definition modulus : Z := two_power_nat wordsize.
Definition half_modulus : Z := modulus / 2.
Definition max_unsigned : Z := modulus - 1.
Definition max_signed : Z := half_modulus - 1.
Definition min_signed : Z := - half_modulus.
Remark wordsize_pos: zwordsize > 0.
Remark modulus_power: modulus = two_p zwordsize.
Remark modulus_pos: modulus > 0.
(** * Representation of machine integers *)
(** A machine integer (type [int]) is represented as a Coq arbitrary-precision integer (type [Z]) plus a proof that it is in the range 0 (included) to [modulus] (excluded). *)
Record int: Type := mkint { intval: Z; intrange: -1 < intval < modulus }.
(** Fast normalization modulo [2^wordsize] *)
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_modulus (x: Z) : Z :=
match x with
| Z0 => 0
| Zpos p => P_mod_two_p p wordsize
| Zneg p => let r := P_mod_two_p p wordsize in if zeq r 0 then 0 else modulus - r
end.

(* Specifications: *)
Lemma P_mod_two_p_range:
forall n p, 0 <= P_mod_two_p p n < two_power_nat n.
Lemma P_mod_two_p_eq:
forall n p, P_mod_two_p p n = (Zpos p) mod (two_power_nat n).
Lemma Z_mod_modulus_range:
forall x, 0 <= Z_mod_modulus x < modulus.
Lemma Z_mod_modulus_range':
forall x, -1 < Z_mod_modulus x < modulus.
Lemma Z_mod_modulus_eq:
forall x, Z_mod_modulus x = x mod modulus.