1#[allow(unused_imports)]
4use vstd::prelude::*;
5
6verus! {
7
8pub open spec fn range_spec(len: nat, m: nat, from_end: bool, drop: bool) -> (nat, nat) {
12 if !from_end && !drop {
13 (0, m)
14 } else if from_end && !drop {
15 ((len - m) as nat, len)
16 } else if !from_end && drop {
17 (m, len)
18 } else {
19 (0, (len - m) as nat)
20 }
21}
22
23pub fn range(len: usize, m: usize, from_end: bool, drop: bool) -> (r: (usize, usize))
26 requires
27 m <= len,
28 ensures
29 r.0 <= r.1 <= len,
30 (r.0 as nat, r.1 as nat) == range_spec(len as nat, m as nat, from_end, drop),
31 r.1 - r.0 == if drop { len - m } else { m as int },
32{
33 match (from_end, drop) {
34 (false, false) => (0, m),
35 (true, false) => (len - m, len),
36 (false, true) => (m, len),
37 (true, true) => (0, len - m),
38 }
39}
40
41pub open spec fn within(r: (nat, nat), i: nat) -> bool {
43 r.0 <= i < r.1
44}
45
46pub proof fn lemma_take_drop_partition(len: nat, m: nat, from_end: bool)
49 requires
50 m <= len,
51 ensures
52 forall|i: nat|
53 i < len ==> (#[trigger] within(range_spec(len, m, from_end, false), i) != within(
54 range_spec(len, m, from_end, true),
55 i,
56 )),
57{
58}
59
60} #[cfg(test)]
63#[cfg_attr(coverage_nightly, coverage(off))]
64mod tests {
65 use super::*;
66
67 #[test]
68 fn take_and_drop_partition() {
69 for len in 0..6 {
70 for m in 0..=len {
71 for end in [false, true] {
72 let (a, b) = range(len, m, end, false);
73 let (c, d) = range(len, m, end, true);
74 assert_eq!(b - a, m);
75 let mut all: Vec<usize> = (a..b).chain(c..d).collect();
76 all.sort_unstable();
77 assert_eq!(all, (0..len).collect::<Vec<_>>());
78 }
79 }
80 }
81 }
82}