(* Copyright 2012-2015 by Adam Petcher.				* * Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
Set Implicit Arguments.
Fixpoint splitVector(A : Set)(n m : nat) : Vector.t A (n + m) -> (Vector.t A n * Vector.t A m) :=
match n with
| 0 =>
fun (v : Vector.t A (O + m)) => (@Vector.nil A, v)
| S n' =>
fun (v : Vector.t A (S n' + m)) =>
let (v1, v2) := splitVector _ _ (Vector.tl v) in
(Vector.cons _ (Vector.hd v) _ v1, v2)
end.
induction v1; intuition; simpl in *.
remember ( splitVector n n2 (Vector.append v1 v2)) as z.
destruct z.
rewrite IHv1 in Heqz.
inversion Heqz; subst.
trivial.
Qed.
induction n1; intuition; simpl in *.
destruct (vector_S x).
destruct H.
subst.
simpl.
remember (splitVector n1 n2 x1) as z.
destruct z.
simpl.
f_equal.
specialize (IHn1 n2 x1).
rewrite <- Heqz in IHn1.
simpl in *.
trivial.
Qed.
intuition.
specialize (append_splitVector_h _ _ x); intuition.
rewrite <- H in H0.
simpl in *.
trivial.
Qed.
induction n1; intuition; simpl in *.
rewrite shiftOut_0.
econstructor.
econstructor.
econstructor.
intuition.
trivial.
destruct s; simpl in *.
discriminate.
case_eq (shiftOut s (n1 + n2)); intuition.
rewrite H0 in H.
destruct p.
inversion H; clear H; subst.
edestruct IHn1.
eauto.
destruct H.
destruct H.
intuition.
rewrite H1.
econstructor.
econstructor.
econstructor.
intuition.
eauto.
simpl.
rewrite H3.
trivial.
rewrite H0 in H.
discriminate.
Qed.
induction n1; intuition; simpl in *.
rewrite shiftOut_0.
right.
econstructor.
econstructor.
intuition.
destruct s; simpl in *.
intuition.
case_eq (shiftOut s (n1 + n2)); intuition.
rewrite H0 in H.
destruct p.
discriminate.
edestruct IHn1.
eauto.
rewrite H1.
intuition.
destruct H1.
destruct H1.
intuition.
rewrite H2.
right.
econstructor.
econstructor.
intuition.
Qed.
induction n1; intuition; simpl in *.
Qed.
induction n1; intuition; simpl in *.
rewrite shiftOut_0 in H.
inversion H; clear H; subst.
simpl in *.
trivial.
destruct s; simpl in *.
discriminate.
case_eq (shiftOut s n1); intuition.
rewrite H1 in H.
destruct p.
inversion H; clear H; subst.
erewrite IHn1; eauto.
rewrite Vector_cons_app_assoc.
trivial.
rewrite H1 in H.
discriminate.
Qed.
induction n1; intuition; simpl in *.
rewrite shiftOut_0 in H0.
discriminate.
destruct H0.
destruct H.
intuition.
rewrite shiftOut_0 in H0.
inversion H0; clear H0; subst.
trivial.
destruct s; simpl in *.
trivial.
case_eq (shiftOut s n1); intuition.
rewrite H in H0.
destruct p.
discriminate.
rewrite H in H0.
erewrite IHn1.
trivial.
intuition.
destruct H0.
destruct H.
intuition.
destruct s; simpl in *.
discriminate.
case_eq (shiftOut s n1); intuition.
rewrite H in H0.
destruct p.
inversion H0; clear H0; subst.
erewrite IHn1.
trivial.
right.
econstructor.
econstructor.
intuition.
eauto.
trivial.
rewrite H in H0.
discriminate.
Qed.

Theorem Rnd_split_equiv :
forall n1 n2 z ,
evalDist
(x <-$ {0, 1}^(n1 + n2);
ret (splitVector n1 n2 x)) z ==
evalDist
(x1 <-$ {0, 1}^n1;
x2 <-$ {0, 1}^n2;
ret (x1, x2)) z.