(* Use of this source code is governed by the license described	* * in the LICENSE file at the root of the source tree.		*)
(* Lists of booleans and related theory. *)
Set Implicit Arguments.
Require Export List.
Require Export Bvector.
Local Open Scope list_scope.
Definition Blist := list bool.
Definition Blist_eq_dec := (list_eq_dec bool_dec).
Definition Bvector_eq_dec(n : nat)(v1 v2 : Bvector n) : {v1 = v2} + {v1 <> v2}.
apply (EqDec_dec (Bvector_EqDec n)).
Defined.
(* shiftOut gets bits from the head of the list. *)
(* return None when we run out *)
Fixpoint shiftOut(s : Blist)(n : nat) : option (Bvector n * Blist) :=
match n with
| 0 => Some ((@Vector.nil bool), s)
| S n' =>
match s with
| nil => None
| b :: s' =>
match (shiftOut s' n') with
| Some (v', s'') => Some (Vector.cons _ b _ v', s'')
| None => None
end
end
end.
induction n; simpl in *; intuition.
destruct s1; simpl in *.
inversion H; clear H; subst.
destruct s2; simpl.
trivial.
trivial.
inversion H; clear H; subst.
rewrite app_comm_cons.
trivial.
destruct s1; simpl in *.
discriminate.
case_eq (shiftOut s1 n); intuition.
rewrite H0 in H.
destruct p.
inversion H; clear H; subst.
erewrite IHn; eauto.
rewrite H0 in H.
discriminate.
Qed.
induction ls; intuition; simpl in *.
destruct n.
omega.
trivial.
destruct n.
omega.
rewrite IHls.
trivial.
omega.
Qed.
induction ls; intuition; simpl in *.
assert (n = O).
omega.
subst.
exists ([], nil).
trivial.
destruct n.
exists ([], a :: ls).
trivial.
assert (length ls >= n).
omega.
destruct (IHls n).
trivial.
destruct x.
econstructor.
rewrite H1.
eauto.
Qed.
induction n; destruct ls; intuition; simpl in *; try discriminate.
apply gt_n_S.
eapply IHn.
case_eq (shiftOut ls n); intuition; trivial.
rewrite H0 in H.
destruct p.
discriminate.
Qed.
induction n; destruct ls; intuition; simpl in *; try discriminate.
apply le_n_S.
case_eq (shiftOut ls n); intuition.
destruct p.
eauto.
rewrite H0 in H.
discriminate.
Qed.

Theorem shiftOut_correct_inv : forall n ls ls' v,
shiftOut ls n = Some (v, ls') ->
ls = (Vector.to_list v) ++ ls'.