(* <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.

Lemma lt_0_p : 0 < p \/ M = 1.