Require Export VST.msl.eq_dec.
Hint Rewrite andb_true_iff: align.
Hint Rewrite <- Zle_is_le_bool: align.
Hint Rewrite Z.eqb_eq: align.
Hint Rewrite power_nat_divide_le using (auto with align): align.
Hint Rewrite Z.mod_divide using (apply two_power_nat_0; auto with align): align.
Hint Rewrite two_p_max_divide using (auto with align): align.
Hint Rewrite two_p_max_1 using (auto with align): align.
Hint Resolve Z_max_two_p: align.
Inductive sublist {A} : list A -> list A -> Prop :=
| sublist_nil : sublist nil nil
| sublist_cons a l1 l2 : sublist l1 l2 -> sublist (a :: l1) (a :: l2)
| sublist_drop a l1 l2 : sublist l1 l2 -> sublist l1 (a :: l2).
Definition Ensemble_join {A} (X Y Z: Ensemble A): Prop :=
(forall a, Z a <-> X a \/ Y a) /\ (forall a, X a -> Y a -> False).
Require Coq.Logic.ConstructiveEpsilon.
(** Additions to [if_tac]: when mature, move these upstream *)
Tactic Notation "if_tac" "eq:" simple_intropattern(E) :=
match goal with
|- context [if ?a then _ else _] =>
destruct a as [?H | ?H] eqn:E
end.
Tactic Notation "if_tac" simple_intropattern(H) "eq:" simple_intropattern(E):=
match goal with
|- context [if ?a then _ else _] =>
destruct a as H eqn:E
end.
Tactic Notation "if_tac" "in" hyp(H0) "eq:" simple_intropattern(E) :=
match type of H0 with
context [if ?a then _ else _] =>
destruct a as [?H  | ?H] eqn:E
end.
Tactic Notation "if_tac" simple_intropattern(H) "in" hyp(H1) "eq:" simple_intropattern(E) :=
match type of H1 with
context [if ?a then _ else _] =>
destruct a as H eqn:E
end.
(** Specializing a hypothesis with a newly created goal *)
Tactic Notation "assert_specialize" hyp(H) :=
match type of H with
forall x : ?P, _ =>
let Htemp := fresh "Htemp" in
assert P as Htemp; [ | specialize (H Htemp); try clear Htemp ]
end.
Tactic Notation "assert_specialize" hyp(H) "by" tactic1(tac) :=
match type of H with
forall x : ?P, _ =>
let Htemp := fresh "Htemp" in
assert P as Htemp by tac; specialize (H Htemp); try clear Htemp
end.
Tactic Notation "assert_specialize" hyp(H) "as" simple_intropattern(Hnew) :=
match type of H with
forall x : ?P, _ =>
assert P as Hnew; [ | specialize (H Hnew) ]
end.
Tactic Notation "assert_specialize" hyp(H) "as" simple_intropattern(Hnew) "by" tactic1(tac) :=
match type of H with
forall x : ?P, _ =>
assert P as Hnew by tac;
specialize (H Hnew)
end.
(** Auto-specializing a hypothesis *)
Ltac autospec H := specialize (H ltac:(solve [eauto])).
(** When a hypothesis/term is provably equal, but not convertible, to your goal *)
Ltac exact_eq H :=
revert H;
match goal with
|- ?p -> ?q => cut (p = q); [intros ->; auto | ]
end.
(** Auto rewriting of a term *)
Tactic Notation "rewr" :=
match goal with
| H : ?f = _ |- context [?f] => rewrite H
| H : ?f _ = ?f _ |- _ => try (injection H; repeat intros ->)
end.
Tactic Notation "rewr" constr(e) :=
match goal with
E : e = _ |- _ => rewrite E
| E : _ = e |- _ => rewrite <-E
end.
Tactic Notation "rewr" constr(e) "in" "*" :=
match goal with
E : e = _ |- _ => rewrite E in *
| E : _ = e |- _ => rewrite <-E in *
end.
Tactic Notation "rewr" constr(e) "in" hyp(H) :=
match goal with
E : e = _ |- _ => rewrite E in H
| E : _ = e |- _ => rewrite <-E in H
end.
Ltac solve_perm :=
(* solves goals of the form (R ++ ?i = S) where R and S are lists, and ?i is a unification variable *)
try match goal with
| |-  Permutation (?A ++ ?B) _ =>
is_evar A; first [is_evar B; fail 1| idtac];
apply Permutation_app_comm_trans
end;
repeat first [ apply Permutation_refl
| apply perm_skip
| eapply perm_search
].
Goal exists e, Permutation ((1::2::nil)++e) (3::2::1::5::nil).
eexists.
solve_perm.
Qed.
Definition eqb_list {A: Type} (eqb_A: A -> A -> bool): list A -> list A -> bool :=
fix eqb_list (l1 l2: list A): bool :=
match l1, l2 with
| nil, nil => true
| a1 :: l1, a2 :: l2 => eqb_A a1 a2 && eqb_list l1 l2
| _, _ => false
end.

Lemma eqb_list_spec: forall {A: Type} (eqb_A: A -> A -> bool),
(forall a1 a2, eqb_A a1 a2 = true <-> a1 = a2) ->
(forall l1 l2, eqb_list eqb_A l1 l2 = true <-> l1 = l2).