replace ((h mod M + M) * 2 ^ w) with (0 + (h mod M + M) * 2 ^ (w - p + p)). rewrite Zpower_exp. rewrite Zmult_assoc.
rewrite Zmod_plus_distr_l with (m := 2 ^ p). rewrite Z_mod_plus. rewrite modred with (x := 0).
replace (0 + l mod 2 ^ p mod M) with (l mod 2 ^ p mod M). rewrite modred with (m := 2 ^ p). exact r_Si_eq_lit.
apply Zmod_le_0_z. omega. apply Zlt_le_trans with M. apply Zmod_lt_z_m. omega. exact le_M_2pp. ring. omega. apply lt_0_Zpow.
auto with a. apply Zlt_gt. apply Zlt_le_trans with M. omega. auto with a. apply lt_0_Zpow. auto with a. cut (p < w). omega.
auto with a. apply Zle_ge. auto with a. replace (w - p + p) with w. ring. ring. Qed.

(* Specifications: *)
Lemma p2wp : 2 ^ w = 2 ^ (w - p) * 2 ^ p.
rewrite <- Zpower_exp. replace (w - p + p) with w. trivial. ring. cut (p < w). omega. auto with a. apply Zle_ge. auto with a.