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_gt_one: modulus > 1.
Remark modulus_pos: modulus > 0.
Hint Resolve modulus_pos: ints.
(** * 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] *)
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.
Proof (Z_mod_two_p_range wordsize).

Lemma Z_mod_modulus_eq:
forall x, Z_mod_modulus x = x mod modulus.