Module Import ShiftNotations.
Notation "l ^<< r" := (@wlshift' _ l%word r) : word_scope.
Notation "l ^>> r" := (@wrshift' _ l%word r) : word_scope.
End ShiftNotations.
(** * Setting an individual bit *)
Definition wbit sz sz' (n : word sz') := natToWord sz (pow2 (wordToNat n)).
(*! Facts *)
Hint Rewrite div2_double div2_S_double: div2.
Local Hint Resolve mod2_S_double mod2_double.
induction w as [|b]; rewrite wordToNat_wordToNat'; intuition; f_equal; unfold natToWord, wordToNat'; fold natToWord; fold wordToNat';
destruct b; f_equal; autorewrite with div2; intuition.
Qed.
induction sz; simpl; intuition.
Qed.
Hint Rewrite roundTrip_0 : wordToNat.
induction sz as [|sz IHsz]; simpl; intro w; intuition; repeat rewrite untimes2.
exists w; intuition.
case_eq (mod2 w); intro Hmw.
specialize (IHsz (div2 w)); firstorder.
rewrite wordToNat_wordToNat' in *.
let x' := match goal with H : _ + ?x * _ = _ |- _ => x end in
rename x' into x. (* force non-auto-generated name *)
exists x; intuition.
rewrite mult_assoc.
rewrite (mult_comm x 2).
rewrite mult_comm. simpl mult at 1.
rewrite (plus_Sn_m (2 * wordToNat' (natToWord sz (div2 w)))).
rewrite <- mult_assoc.
rewrite <- mult_plus_distr_l.
rewrite H; clear H.
symmetry; apply div2_odd; auto.
specialize (IHsz (div2 w)); firstorder.
let x' := match goal with H : _ + ?x * _ = _ |- _ => x end in
rename x' into x. (* force non-auto-generated name *)
exists x; intuition.
rewrite mult_assoc.
rewrite (mult_comm x 2).
rewrite <- mult_assoc.
rewrite mult_comm.
rewrite <- mult_plus_distr_l.
match goal with H : _ |- _ => rewrite H; clear H end.
symmetry; apply div2_even; auto.
Qed.
intros b1 b2 sz w1 w2 ? H0; intuition.
apply (f_equal (@whd _)) in H0; tauto.
apply (f_equal (@wtl _)) in H0; tauto.
Qed.
Ltac shatterer := simpl; intuition;
match goal with
| [ w : _ |- _ ] => rewrite (shatter_word w); simpl
end; f_equal; auto.

Theorem combine_split : forall sz1 sz2 (w : word (sz1 + sz2)),
combine (split1 sz1 sz2 w) (split2 sz1 sz2 w) = w.