rewrite Zmult_assoc. rewrite Zmod_km_plus. rewrite Zmod_km_plus. rewrite modred with (x := l mod 2 ^ p mod M).
rewrite <- Zmult_assoc. rewrite <- Zpower_exp. replace (w - p + p) with w.
elim (mod_plus (h mod M * 2 ^ w + l - l mod 2 ^ p) (l mod 2 ^ p) M). intro H0; rewrite H0;
replace (h mod M * 2 ^ w + l - l mod 2 ^ p + l mod 2 ^ p) with (h mod M * 2 ^ w + l). rewrite Zmod_plus_distr_l.
rewrite <- Zmod_mult_distr_l. rewrite <- Zmod_plus_distr_l. tauto. omega. omega. omega. ring.
intro H0; rewrite H0; replace (h mod M * 2 ^ w + l - l mod 2 ^ p + l mod 2 ^ p) with (h mod M * 2 ^ w + l).
rewrite Zmod_plus_distr_l. rewrite <- Zmod_mult_distr_l. rewrite <- Zmod_plus_distr_l. tauto. omega. omega. omega. ring. omega.
ring. cut (p < w). omega. auto with a. apply Zle_ge. auto with a. apply Zmod_le_0_z. omega. apply Zlt_le_trans with M.
apply Zmod_lt_z_m. omega. exact le_M_2pp. apply lt_0_Zpow. auto with a. apply lt_0_Zpow. auto with a. cut (p < w). omega.
auto with a. apply Zle_ge. auto with a. ring. apply lt_0_Zpow. auto with a. right.
cut (((h mod M * 2 ^ w + l) / 2 ^ p * 2 ^ p) mod M + (h mod M * 2 ^ w + (l mod 2 ^ p) mod M) mod 2 ^ p = x mod M \/
((h mod M * 2 ^ w + l) / 2 ^ p * 2 ^ p) mod M + (h mod M * 2 ^ w + (l mod 2 ^ p) mod M) mod 2 ^ p = x mod M + M).
omega.
rewrite Zdiv_a_b_b_Zmod. replace w with (w - p + p). rewrite Zpower_exp.
rewrite Zmult_assoc. rewrite Zmod_km_plus. rewrite Zmod_km_plus. rewrite modred with (x := l mod 2 ^ p mod M).
rewrite <- Zmult_assoc. rewrite <- Zpower_exp. replace (w - p + p) with w.
elim (mod_plus (h mod M * 2 ^ w + l - l mod 2 ^ p) (l mod 2 ^ p) M).
intro H0; rewrite H0; replace (h mod M * 2 ^ w + l - l mod 2 ^ p + l mod 2 ^ p) with (h mod M * 2 ^ w + l).
rewrite Zmod_plus_distr_l. rewrite <- Zmod_mult_distr_l. rewrite <- Zmod_plus_distr_l. tauto. omega. omega. omega. ring.
intro H0; rewrite H0; replace (h mod M * 2 ^ w + l - l mod 2 ^ p + l mod 2 ^ p) with (h mod M * 2 ^ w + l).
rewrite Zmod_plus_distr_l. rewrite <- Zmod_mult_distr_l. rewrite <- Zmod_plus_distr_l. tauto. omega. omega. omega. ring. omega.
ring. cut (p < w). omega. auto with a. apply Zle_ge. auto with a. apply Zmod_le_0_z. omega. apply Zlt_le_trans with M.
apply Zmod_lt_z_m. omega. exact le_M_2pp. apply lt_0_Zpow. auto with a. apply lt_0_Zpow. auto with a. cut (p < w). omega.
auto with a. apply Zle_ge. auto with a. ring. apply lt_0_Zpow. auto with a. Qed.

(* Specifications: *)
Lemma d_Si_small : d_Si < M + M.
elim d_Si_eq; intro H. apply Zlt_trans with M. rewrite H. apply Zmod_lt_z_m. omega. omega. elim H; intro H0. rewrite H0.