1use vstd::{prelude::*, set_lib::FiniteRange, std_specs::cmp::PartialOrdIs};
4
5use core::ops::Range;
6
7verus! {
8
9pub trait RangeExtraFns<T: FiniteRange> {
11 spec fn view_set(self) -> Set<T>;
13}
14
15impl<T: FiniteRange> RangeExtraFns<T> for Range<T> {
16 open spec fn view_set(self) -> Set<T> {
17 T::range_set(self.start, self.end)
18 }
19}
20
21pub open spec fn seq_range_union<T: FiniteRange>(s: Seq<Range<T>>) -> Set<T> {
23 s.map_values(|r: Range<T>| r.view_set()).to_set().flatten()
24}
25
26pub open spec fn finite_range_matches_ord<T: FiniteRange + Ord>() -> bool {
28 forall|x: T, lo: T, hi: T| T::in_range(x, lo, hi) <==> lo.is_le(&x) && x.is_lt(&hi)
29}
30
31pub proof fn lemma_seq_range_union_contains<T: FiniteRange>(s: Seq<Range<T>>, x: T)
34 ensures
35 seq_range_union(s).contains(x) <==> s.any(|r: Range<T>| r.view_set().contains(x)),
36{
37 broadcast use {Seq::to_set_ensures, Set::lemma_flatten_contains};
38
39 let pred = |r: Range<T>| r.view_set().contains(x);
40 let range_sets = s.map_values(|r: Range<T>| r.view_set());
41
42 if seq_range_union(s).contains(x) {
43 range_sets.to_set().lemma_flatten_contains(x);
44 let range_set = choose|range_set: Set<T>|
45 #![trigger range_sets.to_set().contains(range_set)]
46 range_sets.to_set().contains(range_set) && range_set.contains(x);
47 let i = choose|i: int| 0 <= i < range_sets.len() && range_sets[i] == range_set;
48
49 assert(pred(s[i]));
50 assert(s.any(pred));
51 } else if s.any(pred) {
52 let i = choose|i: int| #![auto] 0 <= i < s.len() && pred(s[i]);
53
54 assert(range_sets.to_set().contains(range_sets[i]));
55 range_sets.to_set().lemma_flatten_contains(x);
56 }
57}
58
59}