(* Copyright 2001, 2009 Luc Rutten  This file is part of ModRed.  ModRed is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.  ModRed is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.  You should have received a copy of the GNU Lesser General Public License along with ModRed.  If not, see <http://www.gnu.org/licenses/>. *)
(* Fast reduction of nonnegative integers by moduli M such that 1 <= M <= 2 ^ (w - 1) where w denotes a processor's word size. *)
(* Faster than the version proposed in multired.v on some processors. *)
(* Coq 8.2 *)
Open Scope Z_scope.
(* <KEEP TOGETHER - loop_invariant_multired_x *)
Definition P' (M p : Z) (d r : Z_ (2 ^ w)) (h : Z) (l : Z_ (2 ^ w)) :=
(_Z d = (h mod M * 2 ^ w + l) / 2 ^ p * 2 ^ p mod M \/
_Z d = (h mod M * 2 ^ w + l) / 2 ^ p * 2 ^ p mod M + M \/
_Z d = ((h mod M + M) * 2 ^ w + l) / 2 ^ p * 2 ^ p mod M \/
_Z d = ((h mod M + M) * 2 ^ w + l) / 2 ^ p * 2 ^ p mod M + M
) /\
_Z r = (d + l mod 2 ^ p mod M) mod 2 ^ w.
(* KEEP TOGETHER> *)
Section parm_sec.
Variable M_in_Z_ : Z_ (2 ^ w).
Variable ptM'cM'' : Z_ w * Z_ w * Z_ (2 ^ w) * Z_ (2 ^ w) * Z_ (2 ^ w).
Variable d_Sir_Si : Z_ (2 ^ w) * Z_ (2 ^ w).
Variable l_in_Z_ : Z_ (2 ^ w).
Variable x_i_in_Z_ : Z_ (2 ^ w).
Variable h : Z.
Let p_in_Z_w := fst (fst (fst (fst ptM'cM''))).
Let t_in_Z_w := snd (fst (fst (fst ptM'cM''))).
Let M'_in_Z_ := snd (fst (fst ptM'cM'')).
Let c_in_Z_ := snd (fst ptM'cM'').
Let M''_in_Z_ := snd ptM'cM''.
Let M := _Z M_in_Z_.
Let p := _Z p_in_Z_w.
Let t := _Z t_in_Z_w.
Let c := _Z c_in_Z_.
Let M'' := _Z M''_in_Z_.
Let M' := _Z M'_in_Z_.
Let l := _Z l_in_Z_.
Let x_i := _Z x_i_in_Z_.
Definition d_Si := fst d_Sir_Si.
Definition r_Si := snd d_Sir_Si.
Hypothesis d_Si_eq_r_Si_eq : P' M p d_Si r_Si h l_in_Z_.
Hypothesis le_1_M : 1 <= M.
Hypothesis le_M_max : M <= 2 ^ (w - 1).
Hypothesis p_M : p = Zlog_sup M.
Hypothesis t_M : t = w - p \/ M = 1.
Hypothesis c_M : c = 2 ^ p.
Hypothesis M''_M : M'' = (2 ^ t * M) mod 2 ^ w.
Hypothesis M'_M : M' = 2 ^ (p + w) / M mod 2 ^ w.

(* Specifications: *)
Lemma le_0_p : 0 <= p.
unfold p. apply le_0__Z. Qed.
Lemma le02w : 0 <= 2 ^ w.
apply Zlt_le_weak. exact lt02w. Qed.