1
use crate::ast::domains::Int;
2
use num_traits::Num;
3
use polyquine::Quine;
4
use serde::{Deserialize, Serialize};
5
use std::fmt::Display;
6

            
7
#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize, Quine)]
8
#[path_prefix(conjure_cp::ast)]
9
pub enum Range<A = Int> {
10
    Single(A),
11
    Bounded(A, A),
12
    UnboundedL(A),
13
    UnboundedR(A),
14
    Unbounded,
15
}
16

            
17
impl<A> Range<A> {
18
    /// Whether the range is **bounded** on either side. A bounded range may still be infinite.
19
    /// See also: [Range::is_finite].
20
243988635
    pub fn is_lower_or_upper_bounded(&self) -> bool {
21
243988635
        match &self {
22
            Range::Single(_)
23
            | Range::Bounded(_, _)
24
            | Range::UnboundedL(_)
25
243988632
            | Range::UnboundedR(_) => true,
26
3
            Range::Unbounded => false,
27
        }
28
243988635
    }
29

            
30
    /// Whether the range is **unbounded** on both sides.
31
    pub fn is_unbounded(&self) -> bool {
32
        !self.is_lower_or_upper_bounded()
33
    }
34

            
35
    /// Whether the range is **finite**. See also: [Range::is_lower_or_upper_bounded].
36
15
    pub fn is_finite(&self) -> bool {
37
15
        match &self {
38
6
            Range::Single(_) | Range::Bounded(_, _) => true,
39
9
            Range::Unbounded | Range::UnboundedL(_) | Range::UnboundedR(_) => false,
40
        }
41
15
    }
42
}
43

            
44
impl<A: Ord> Range<A> {
45
29355
    pub fn contains(&self, val: &A) -> bool {
46
29355
        match self {
47
186
            Range::Single(x) => x == val,
48
29166
            Range::Bounded(x, y) => x <= val && val <= y,
49
            Range::UnboundedR(x) => x <= val,
50
            Range::UnboundedL(x) => val <= x,
51
3
            Range::Unbounded => true,
52
        }
53
29355
    }
54

            
55
    /// Returns the lower bound of the range, if it has one
56
4965506
    pub fn low(&self) -> Option<&A> {
57
4965506
        match self {
58
3674299
            Range::Single(a) => Some(a),
59
1291147
            Range::Bounded(a, _) => Some(a),
60
21
            Range::UnboundedR(a) => Some(a),
61
39
            Range::UnboundedL(_) | Range::Unbounded => None,
62
        }
63
4965506
    }
64

            
65
    /// Returns the upper bound of the range, if it has one
66
4965500
    pub fn high(&self) -> Option<&A> {
67
4965500
        match self {
68
3651130
            Range::Single(a) => Some(a),
69
1314310
            Range::Bounded(_, a) => Some(a),
70
36
            Range::UnboundedL(a) => Some(a),
71
24
            Range::UnboundedR(_) | Range::Unbounded => None,
72
        }
73
4965500
    }
74
}
75

            
76
impl<A: Ord + Clone> Range<A> {
77
    /// Create a new range with a lower and upper bound
78
459118
    pub fn new(lo: Option<A>, hi: Option<A>) -> Range<A> {
79
459118
        match (lo, hi) {
80
3
            (None, None) => Range::Unbounded,
81
3
            (Some(l), None) => Range::UnboundedR(l),
82
6
            (None, Some(r)) => Range::UnboundedL(r),
83
459106
            (Some(l), Some(r)) => {
84
459106
                if l == r {
85
27860
                    Range::Single(l)
86
                } else {
87
431246
                    let min = Ord::min(&l, &r).clone();
88
431246
                    let max = Ord::max(l, r);
89
431246
                    Range::Bounded(min, max)
90
                }
91
            }
92
        }
93
459118
    }
94

            
95
    /// Given a slice of ranges, create a single range that spans from the start
96
    /// of the leftmost range to the end of the rightmost range.
97
    /// An empty slice is considered equivalent to `Range::unbounded`.
98
236095
    pub fn spanning(rngs: &[Range<A>]) -> Range<A> {
99
236095
        if rngs.is_empty() {
100
3
            return Range::Unbounded;
101
236092
        }
102

            
103
236092
        let mut lo = rngs[0].low();
104
236092
        let mut hi = rngs[0].high();
105
246547
        for rng in rngs {
106
246547
            lo = match (lo, rng.low()) {
107
246535
                (Some(curr), Some(new)) => Some(curr.min(new)),
108
12
                _ => None,
109
            };
110
246547
            hi = match (hi, rng.high()) {
111
246541
                (Some(curr), Some(new)) => Some(curr.max(new)),
112
6
                _ => None,
113
            };
114
        }
115
236092
        Range::new(lo.cloned(), hi.cloned())
116
236095
    }
117
}
118

            
119
impl<A: Num + Ord + Clone> Range<A> {
120
1764
    pub fn length(&self) -> Option<A> {
121
1764
        match self {
122
6
            Range::Single(_) => Some(A::one()),
123
1743
            Range::Bounded(i, j) => Some(j.clone() - i.clone() + A::one()),
124
15
            Range::UnboundedR(_) | Range::UnboundedL(_) | Range::Unbounded => None,
125
        }
126
1764
    }
127

            
128
    /// Returns true if this interval overlaps another one, i.e. at least one
129
    /// number is part of both `self` and `other`
130
    /// E.g:
131
    /// - [0, 2] overlaps [2, 4]
132
    /// - [1, 3] overlaps [2, 4]
133
    /// - [4, 6] overlaps [2, 4]
134
1036573
    pub fn overlaps(&self, other: &Range<A>) -> bool {
135
1036573
        self.low()
136
1036573
            .is_none_or(|la| other.high().is_none_or(|rb| la <= rb))
137
1033750
            && self
138
1033750
                .high()
139
1033750
                .is_none_or(|ra| other.low().is_none_or(|lb| ra >= lb))
140
1036573
    }
141

            
142
    /// Returns true if this interval touches another one on the left
143
    /// E.g: [1, 2] touches_left  [3, 4]
144
1080602
    pub fn touches_left(&self, other: &Range<A>) -> bool {
145
1080602
        self.high().is_some_and(|ra| {
146
1080602
            let ra = ra.clone() + A::one();
147
1080602
            other.low().is_some_and(|lb| ra.eq(lb))
148
1080602
        })
149
1080602
    }
150

            
151
    /// Returns true if this interval touches another one on the right
152
    /// E.g: [3, 4] touches_right  [1, 2]
153
860099
    pub fn touches_right(&self, other: &Range<A>) -> bool {
154
860099
        self.low().is_some_and(|la| {
155
860096
            let la = la.clone() - A::one();
156
860096
            other.high().is_some_and(|rb| la.eq(rb))
157
860096
        })
158
860099
    }
159

            
160
    /// Returns true if this interval overlaps or touches another one
161
    /// E.g:
162
    /// - [1, 3] joins [4, 6]
163
    /// - [2, 4] joins [4, 6]
164
    /// - [3, 5] joins [4, 6]
165
    /// - [6, 8] joins [4, 6]
166
    /// - [7, 8] joins [4, 6]
167
1080584
    pub fn joins(&self, other: &Range<A>) -> bool {
168
1080584
        self.touches_left(other) || self.overlaps(other) || self.touches_right(other)
169
1080584
    }
170

            
171
    /// Returns true if this interval is strictly before another one
172
21
    pub fn is_before(&self, other: &Range<A>) -> bool {
173
21
        self.high()
174
21
            .is_some_and(|ra| other.low().is_some_and(|lb| ra < &(lb.clone() - A::one())))
175
21
    }
176

            
177
    /// Returns true if this interval is strictly after another one
178
18
    pub fn is_after(&self, other: &Range<A>) -> bool {
179
18
        self.low()
180
18
            .is_some_and(|la| other.high().is_some_and(|rb| la > &(rb.clone() + A::one())))
181
18
    }
182

            
183
    /// If the two ranges join, return a new range which spans both
184
1080584
    pub fn join(&self, other: &Range<A>) -> Option<Range<A>> {
185
1080584
        if self.joins(other) {
186
222366
            let lo = Ord::min(self.low(), other.low());
187
222366
            let hi = Ord::max(self.high(), other.high());
188
222366
            return Some(Range::new(lo.cloned(), hi.cloned()));
189
858218
        }
190
858218
        None
191
1080584
    }
192

            
193
    /// Merge all joining ranges in the list, and return a new vec of disjoint ranges.
194
    /// E.g:
195
    /// ```ignore
196
    /// [(2..3), (4), (..1), (6..8)] -> [(..4), (6..8)]
197
    /// ```
198
    ///
199
    /// # Performance
200
    /// Currently uses a naive O(n^2) algorithm.
201
    /// A more optimal approach based on interval trees is planned.
202
2152669
    pub fn squeeze(rngs: &[Range<A>]) -> Vec<Range<A>> {
203
2152669
        let mut ans = Vec::from(rngs);
204

            
205
2152669
        if ans.is_empty() {
206
40
            return ans;
207
2152629
        }
208

            
209
        loop {
210
2374995
            let mut merged = false;
211

            
212
            // Check every pair of ranges and join them if possible
213
2464830
            'outer: for i in 0..ans.len() {
214
2464830
                for j in (i + 1)..ans.len() {
215
1080584
                    if let Some(joined) = ans[i].join(&ans[j]) {
216
222366
                        ans[i] = joined;
217
                        // Safe to delete here because we restart the outer loop immediately
218
222366
                        ans.remove(j);
219
222366
                        merged = true;
220
222366
                        break 'outer;
221
858218
                    }
222
                }
223
            }
224

            
225
            // If no merges occurred, we're done
226
2374995
            if !merged {
227
2152629
                break;
228
222366
            }
229
        }
230

            
231
2152629
        ans
232
2152669
    }
233

            
234
    /// If this range is bounded, returns a lazy iterator over all values within the range.
235
    /// Otherwise, returns None.
236
312980
    pub fn iter(&self) -> Option<RangeIterator<A>> {
237
312980
        match self {
238
12240
            Range::Single(val) => Some(RangeIterator::Single(Some(val.clone()))),
239
300740
            Range::Bounded(start, end) => Some(RangeIterator::Bounded {
240
300740
                current: start.clone(),
241
300740
                end: end.clone(),
242
300740
            }),
243
            Range::UnboundedL(_) | Range::UnboundedR(_) | Range::Unbounded => None,
244
        }
245
312980
    }
246

            
247
720
    pub fn values(rngs: &[Range<A>]) -> Option<impl Iterator<Item = A>> {
248
720
        let itrs = rngs
249
720
            .iter()
250
720
            .map(Range::iter)
251
720
            .collect::<Option<Vec<RangeIterator<A>>>>()?;
252
720
        Some(itrs.into_iter().flatten())
253
720
    }
254
}
255

            
256
/// Iterator for Range<A> that yields values lazily
257
pub enum RangeIterator<A> {
258
    Single(Option<A>),
259
    Bounded { current: A, end: A },
260
}
261

            
262
impl<A: Num + Ord + Clone> Iterator for RangeIterator<A> {
263
    type Item = A;
264

            
265
1988460
    fn next(&mut self) -> Option<Self::Item> {
266
1988460
        match self {
267
24480
            RangeIterator::Single(val) => val.take(),
268
1963980
            RangeIterator::Bounded { current, end } => {
269
1963980
                if current > end {
270
300740
                    return None;
271
1663240
                }
272

            
273
1663240
                let result = current.clone();
274
1663240
                *current = current.clone() + A::one();
275

            
276
1663240
                Some(result)
277
            }
278
        }
279
1988460
    }
280
}
281

            
282
impl<A: Display> Display for Range<A> {
283
243988620
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
284
243988620
        match self {
285
3644900
            Range::Single(i) => write!(f, "{i}"),
286
238911780
            Range::Bounded(i, j) => write!(f, "{i}..{j}"),
287
1431940
            Range::UnboundedR(i) => write!(f, "{i}.."),
288
            Range::UnboundedL(i) => write!(f, "..{i}"),
289
            Range::Unbounded => write!(f, ""),
290
        }
291
243988620
    }
292
}
293

            
294
#[allow(unused_imports)]
295
mod test {
296
    use super::*;
297
    use crate::range;
298

            
299
    #[test]
300
3
    pub fn test_range_macros() {
301
3
        assert_eq!(range!(1..3), Range::Bounded(1, 3));
302
3
        assert_eq!(range!(1..), Range::UnboundedR(1));
303
3
        assert_eq!(range!(..3), Range::UnboundedL(3));
304
3
        assert_eq!(range!(1), Range::Single(1));
305
3
    }
306

            
307
    #[test]
308
3
    pub fn test_range_low() {
309
3
        assert_eq!(range!(1..3).low(), Some(&1));
310
3
        assert_eq!(range!(1..).low(), Some(&1));
311
3
        assert_eq!(range!(1).low(), Some(&1));
312
3
        assert_eq!(range!(..3).low(), None);
313
3
        assert_eq!(Range::<Int>::Unbounded.low(), None);
314
3
    }
315

            
316
    #[test]
317
3
    pub fn test_range_high() {
318
3
        assert_eq!(range!(1..3).high(), Some(&3));
319
3
        assert_eq!(range!(1..).high(), None);
320
3
        assert_eq!(range!(1).high(), Some(&1));
321
3
        assert_eq!(range!(..3).high(), Some(&3));
322
3
        assert_eq!(Range::<Int>::Unbounded.high(), None);
323
3
    }
324

            
325
    #[test]
326
3
    pub fn test_range_is_finite() {
327
3
        assert!(range!(1..3).is_finite());
328
3
        assert!(range!(1).is_finite());
329
3
        assert!(!range!(1..).is_finite());
330
3
        assert!(!range!(..3).is_finite());
331
3
        assert!(!Range::<Int>::Unbounded.is_finite());
332
3
    }
333

            
334
    #[test]
335
3
    pub fn test_range_bounded() {
336
3
        assert!(range!(1..3).is_lower_or_upper_bounded());
337
3
        assert!(range!(1).is_lower_or_upper_bounded());
338
3
        assert!(range!(1..).is_lower_or_upper_bounded());
339
3
        assert!(range!(..3).is_lower_or_upper_bounded());
340
3
        assert!(!Range::<Int>::Unbounded.is_lower_or_upper_bounded());
341
3
    }
342

            
343
    #[test]
344
3
    pub fn test_range_length() {
345
3
        assert_eq!(range!(1..3).length(), Some(3));
346
3
        assert_eq!(range!(1).length(), Some(1));
347
3
        assert_eq!(range!(1..).length(), None);
348
3
        assert_eq!(range!(..3).length(), None);
349
3
        assert_eq!(Range::<Int>::Unbounded.length(), None);
350
3
    }
351

            
352
    #[test]
353
3
    pub fn test_range_contains_value() {
354
3
        assert!(range!(1..3).contains(&2));
355
3
        assert!(!range!(1..3).contains(&4));
356
3
        assert!(range!(1).contains(&1));
357
3
        assert!(!range!(1).contains(&2));
358
3
        assert!(Range::Unbounded.contains(&42));
359
3
    }
360

            
361
    #[test]
362
3
    pub fn test_range_overlaps() {
363
3
        assert!(range!(1..3).overlaps(&range!(2..4)));
364
3
        assert!(range!(1..3).overlaps(&range!(3..5)));
365
3
        assert!(!range!(1..3).overlaps(&range!(4..6)));
366
3
        assert!(Range::Unbounded.overlaps(&range!(1..3)));
367
3
    }
368

            
369
    #[test]
370
3
    pub fn test_range_touches_left() {
371
3
        assert!(range!(1..2).touches_left(&range!(3..4)));
372
3
        assert!(range!(1..2).touches_left(&range!(3)));
373
3
        assert!(range!(-5..-4).touches_left(&range!(-3..2)));
374
3
        assert!(!range!(1..2).touches_left(&range!(4..5)));
375
3
        assert!(!range!(1..2).touches_left(&range!(2..3)));
376
3
        assert!(!range!(3..4).touches_left(&range!(1..2)));
377
3
    }
378

            
379
    #[test]
380
3
    pub fn test_range_touches_right() {
381
3
        assert!(range!(3..4).touches_right(&range!(1..2)));
382
3
        assert!(range!(3).touches_right(&range!(1..2)));
383
3
        assert!(range!(0..1).touches_right(&range!(-2..-1)));
384
3
        assert!(!range!(1..2).touches_right(&range!(3..4)));
385
3
        assert!(!range!(2..3).touches_right(&range!(1..2)));
386
3
        assert!(!range!(1..2).touches_right(&range!(1..2)));
387
3
    }
388

            
389
    #[test]
390
3
    pub fn test_range_is_before() {
391
3
        assert!(range!(1..2).is_before(&range!(4..5)));
392
3
        assert!(range!(1..2).is_before(&range!(4..)));
393
3
        assert!(!range!(1..2).is_before(&range!(3..)));
394
3
        assert!(!range!(1..2).is_before(&range!(..4)));
395
3
        assert!(!range!(1..2).is_before(&range!(2..4)));
396
3
        assert!(!range!(3..4).is_before(&range!(1..2)));
397
3
        assert!(!range!(1..2).is_before(&Range::Unbounded));
398
3
    }
399

            
400
    #[test]
401
3
    pub fn test_range_is_after() {
402
3
        assert!(range!(5..6).is_after(&range!(1..2)));
403
3
        assert!(range!(4..5).is_after(&range!(..2)));
404
3
        assert!(!range!(4..5).is_after(&range!(..3)));
405
3
        assert!(!range!(2..3).is_after(&range!(1..2)));
406
3
        assert!(!range!(1..2).is_after(&range!(3..4)));
407
3
        assert!(!range!(1..2).is_after(&Range::Unbounded));
408
3
    }
409

            
410
    #[test]
411
3
    pub fn test_range_squeeze() {
412
3
        let input = vec![range!(2..3), range!(4), range!(..1), range!(6..8)];
413
3
        let squeezed = Range::squeeze(&input);
414
3
        assert_eq!(squeezed, vec![range!(..4), range!(6..8)]);
415
3
    }
416

            
417
    #[test]
418
3
    pub fn test_range_spanning() {
419
3
        assert_eq!(Range::<Int>::spanning(&[]), Range::Unbounded);
420
3
        assert_eq!(Range::spanning(&[range!(1..2), range!(4..5)]), range!(1..5));
421
3
        assert_eq!(
422
3
            Range::spanning(&[range!(..0), range!(2..4)]),
423
            Range::UnboundedL(4)
424
        );
425
3
        assert_eq!(
426
3
            Range::spanning(&[range!(0), range!(2..3), range!(5..)]),
427
            Range::UnboundedR(0)
428
        );
429
3
        assert_eq!(
430
3
            Range::spanning(&[range!(..0), range!(2..)]),
431
            Range::Unbounded
432
        );
433
3
    }
434
}