(* <KEEP TOGETHER - loop_invariant *)
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 2 ^ w.Definition d_Si := fst d_Sir_Si.Definition r_Si := snd d_Sir_Si.

(* Specifications: *)
Lemma le_0_p : 0 <= p.
Lemma le02w : 0 <= 2 ^ w.
Lemma le_M_2pp : M <= 2 ^ p.
Lemma le_1_p : 1 <= p \/ M = 1.
Lemma lt_0_p : 0 < p \/ M = 1.
Lemma le_0_pm1 : 0 <= p - 1 \/ M = 1.
Lemma lt_2pm1_M : 2 ^ (p - 1) < M \/ M = 1.
Lemma div_M_1 : 2 ^ p / M = 1.
Lemma large_M'_eq : 2 ^ w + (2 ^ (p + w) / M) mod 2 ^ w = 2 ^ (p + w) / M.