Library compcert.lib.Intv


Definitions and theorems about semi-open integer intervals

Require Import Coqlib.
Require Import Zwf.
Require Coq.Program.Wf.
Require Recdef.

Definition interv : Type := (Z × Z)%type.

Membership


Definition In (x: Z) (i: interv) : Prop := fst i x < snd i.

Lemma In_dec:
   x i, {In x i} + {¬In x i}.
Proof.
  unfold In; intros.
  case (zle (fst i) x); intros.
  case (zlt x (snd i)); intros.
  left; auto.
  right; intuition.
  right; intuition.
Qed.

Lemma notin_range:
   x i,
  x < fst i x snd i ¬In x i.
Proof.
  unfold In; intros; omega.
Qed.

Lemma range_notin:
   x i,
  ¬In x i fst i < snd i x < fst i x snd i.
Proof.
  unfold In; intros; omega.
Qed.

Emptyness


Definition empty (i: interv) : Prop := fst i snd i.

Lemma empty_dec:
   i, {empty i} + {¬empty i}.
Proof.
  unfold empty; intros.
  case (zle (snd i) (fst i)); intros.
  left; omega.
  right; omega.
Qed.

Lemma is_notempty:
   i, fst i < snd i ¬empty i.
Proof.
  unfold empty; intros; omega.
Qed.

Lemma empty_notin:
   x i, empty i ¬In x i.
Proof.
  unfold empty, In; intros. omega.
Qed.

Lemma in_notempty:
   x i, In x i ¬empty i.
Proof.
  unfold empty, In; intros. omega.
Qed.

Disjointness


Definition disjoint (i j: interv) : Prop :=
   x, In x i ¬In x j.

Lemma disjoint_sym:
   i j, disjoint i j disjoint j i.
Proof.
  unfold disjoint; intros; red; intros. elim (H x); auto.
Qed.

Lemma empty_disjoint_r:
   i j, empty j disjoint i j.
Proof.
  unfold disjoint; intros. apply empty_notin; auto.
Qed.

Lemma empty_disjoint_l:
   i j, empty i disjoint i j.
Proof.
  intros. apply disjoint_sym. apply empty_disjoint_r; auto.
Qed.

Lemma disjoint_range:
   i j,
  snd i fst j snd j fst i disjoint i j.
Proof.
  unfold disjoint, In; intros. omega.
Qed.

Lemma range_disjoint:
   i j,
  disjoint i j
  empty i empty j snd i fst j snd j fst i.
Proof.
  unfold disjoint, empty; intros.
  destruct (zlt (fst i) (snd i)); auto.
  destruct (zlt (fst j) (snd j)); auto.
  right; right.
  destruct (zlt (fst i) (fst j)).
  destruct (zle (snd i) (fst j)).
  auto.
  elim (H (fst j)). red; omega. red; omega.
  destruct (zle (snd j) (fst i)).
  auto.
  elim (H (fst i)). red; omega. red; omega.
Qed.

Lemma range_disjoint':
   i j,
  disjoint i j fst i < snd i fst j < snd j
  snd i fst j snd j fst i.
Proof.
  intros. exploit range_disjoint; eauto. unfold empty; intuition omega.
Qed.

Lemma disjoint_dec:
   i j, {disjoint i j} + {¬disjoint i j}.
Proof.
  intros.
  destruct (empty_dec i). left; apply empty_disjoint_l; auto.
  destruct (empty_dec j). left; apply empty_disjoint_r; auto.
  destruct (zle (snd i) (fst j)). left; apply disjoint_range; auto.
  destruct (zle (snd j) (fst i)). left; apply disjoint_range; auto.
  right; red; intro. exploit range_disjoint; eauto. intuition.
Qed.

Shifting an interval by some amount


Definition shift (i: interv) (delta: Z) : interv := (fst i + delta, snd i + delta).

Lemma in_shift:
   x i delta,
  In x i In (x + delta) (shift i delta).
Proof.
  unfold shift, In; intros. simpl. omega.
Qed.

Lemma in_shift_inv:
   x i delta,
  In x (shift i delta) In (x - delta) i.
Proof.
  unfold shift, In; simpl; intros. omega.
Qed.

Enumerating the elements of an interval


Section ELEMENTS.

Variable lo: Z.

Function elements_rec (hi: Z) {wf (Zwf lo) hi} : list Z :=
  if zlt lo hi then (hi-1) :: elements_rec (hi-1) else nil.
Proof.
  intros. red. omega.
  apply Zwf_well_founded.
Qed.

Lemma In_elements_rec:
   hi x,
  List.In x (elements_rec hi) lo x < hi.
Proof.
  intros. functional induction (elements_rec hi).
  simpl; split; intros.
  destruct H. clear IHl. omega. rewrite IHl in H. clear IHl. omega.
  destruct (zeq (hi - 1) x); auto. right. rewrite IHl. clear IHl. omega.
  simpl; intuition.
Qed.

End ELEMENTS.

Definition elements (i: interv) : list Z :=
  elements_rec (fst i) (snd i).

Lemma in_elements:
   x i,
  In x i List.In x (elements i).
Proof.
  intros. unfold elements. rewrite In_elements_rec. auto.
Qed.

Lemma elements_in:
   x i,
  List.In x (elements i) In x i.
Proof.
  unfold elements; intros.
  rewrite In_elements_rec in H. auto.
Qed.

Checking properties on all elements of an interval


Section FORALL.

Variables P Q: Z Prop.
Variable f: (x: Z), {P x} + {Q x}.
Variable lo: Z.

Program Fixpoint forall_rec (hi: Z) {wf (Zwf lo) hi}:
                 { x, lo x < hi P x}
                 + { x, lo x < hi Q x} :=
  if zlt lo hi then
    match f (hi - 1) with
    | left _
        match forall_rec (hi - 1) with
        | left _left _ _
        | right _right _ _
        end
    | right _right _ _
    end
  else
    left _ _
.
Next Obligation.
  red. omega.
Qed.
Next Obligation.
  assert (x = hi - 1 x < hi - 1) by omega.
  destruct H2. congruence. auto.
Qed.
Next Obligation.
   wildcard'; split; auto. omega.
Qed.
Next Obligation.
   (hi - 1); split; auto. omega.
Qed.
Next Obligation.
  omegaContradiction.
Defined.

End FORALL.

Definition forall_dec
       (P Q: Z Prop) (f: (x: Z), {P x} + {Q x}) (i: interv) :
       { x, In x i P x} + { x, In x i Q x} :=
 forall_rec P Q f (fst i) (snd i).

Folding a function over all elements of an interval


Section FOLD.

Variable A: Type.
Variable f: Z A A.
Variable lo: Z.
Variable a: A.

Function fold_rec (hi: Z) {wf (Zwf lo) hi} : A :=
  if zlt lo hi then f (hi - 1) (fold_rec (hi - 1)) else a.
Proof.
  intros. red. omega.
  apply Zwf_well_founded.
Qed.

Lemma fold_rec_elements:
   hi, fold_rec hi = List.fold_right f a (elements_rec lo hi).
Proof.
  intros. functional induction (fold_rec hi).
  rewrite elements_rec_equation. rewrite zlt_true; auto.
  simpl. congruence.
  rewrite elements_rec_equation. rewrite zlt_false; auto.
Qed.

End FOLD.

Definition fold {A: Type} (f: Z A A) (a: A) (i: interv) : A :=
  fold_rec A f (fst i) a (snd i).

Lemma fold_elements:
   (A: Type) (f: Z A A) a i,
  fold f a i = List.fold_right f a (elements i).
Proof.
  intros. unfold fold, elements. apply fold_rec_elements.
Qed.

Hints

Hint Resolve
  notin_range range_notin
  is_notempty empty_notin in_notempty
  disjoint_sym empty_disjoint_r empty_disjoint_l
  disjoint_range
  in_shift in_shift_inv
  in_elements elements_in : intv.