range_set_blaze/
not_iter.rs

1use core::{
2    iter::FusedIterator,
3    ops::{self, RangeInclusive},
4};
5
6use crate::{BitAndMerge, BitOrMerge, BitSubMerge, BitXOrTee, Integer, SortedDisjoint};
7
8/// Turns a [`SortedDisjoint`] iterator into a [`SortedDisjoint`] iterator of its complement,
9/// i.e., all the integers not in the original iterator, as sorted & disjoint ranges.
10///
11/// # Example
12///
13/// ```
14/// use range_set_blaze::{NotIter, SortedDisjoint, CheckSortedDisjoint};
15///
16/// let a = CheckSortedDisjoint::from([1u8..=2, 5..=100]);
17/// let b = NotIter::new(a);
18/// assert_eq!(b.to_string(), "0..=0, 3..=4, 101..=255");
19///
20/// // Or, equivalently:
21/// let b = !CheckSortedDisjoint::from([1u8..=2, 5..=100]);
22/// assert_eq!(b.to_string(), "0..=0, 3..=4, 101..=255");
23/// ```
24#[derive(Clone, Debug)]
25#[must_use = "iterators are lazy and do nothing unless consumed"]
26pub struct NotIter<T, I>
27where
28    T: Integer,
29    I: SortedDisjoint<T>,
30{
31    iter: I,
32    start_not: T,
33    next_time_return_none: bool,
34}
35
36impl<T, I> NotIter<T, I>
37where
38    T: Integer,
39    I: SortedDisjoint<T>,
40{
41    /// Create a new [`NotIter`] from a [`SortedDisjoint`] iterator. See [`NotIter`] for an example.
42    pub fn new<J>(iter: J) -> Self
43    where
44        J: IntoIterator<Item = RangeInclusive<T>, IntoIter = I>,
45    {
46        NotIter {
47            iter: iter.into_iter(),
48            start_not: T::min_value(),
49            next_time_return_none: false,
50        }
51    }
52}
53
54impl<T, I> FusedIterator for NotIter<T, I>
55where
56    T: Integer,
57    I: SortedDisjoint<T> + FusedIterator,
58{
59}
60
61impl<T, I> Iterator for NotIter<T, I>
62where
63    T: Integer,
64    I: SortedDisjoint<T>,
65{
66    type Item = RangeInclusive<T>;
67    fn next(&mut self) -> Option<RangeInclusive<T>> {
68        debug_assert!(T::min_value() <= T::safe_max_value()); // real assert
69        if self.next_time_return_none {
70            return None;
71        }
72        let next_item = self.iter.next();
73        if let Some(range) = next_item {
74            let (start, end) = range.into_inner();
75            debug_assert!(start <= end && end <= T::safe_max_value());
76            if self.start_not < start {
77                // We can subtract with underflow worry because
78                // we know that start > start_not and so not min_value
79                let result = Some(self.start_not..=start - T::one());
80                if end < T::safe_max_value() {
81                    self.start_not = end + T::one();
82                } else {
83                    self.next_time_return_none = true;
84                }
85                result
86            } else if end < T::safe_max_value() {
87                self.start_not = end + T::one();
88                self.next() // will recurse at most once
89            } else {
90                self.next_time_return_none = true;
91                None
92            }
93        } else {
94            self.next_time_return_none = true;
95            Some(self.start_not..=T::safe_max_value())
96        }
97    }
98
99    // We could have one less or one more than the iter.
100    fn size_hint(&self) -> (usize, Option<usize>) {
101        let (low, high) = self.iter.size_hint();
102        let low = if low > 0 { low - 1 } else { 0 };
103        let high = high.map(|high| {
104            if high < usize::MAX {
105                high + 1
106            } else {
107                usize::MAX
108            }
109        });
110        (low, high)
111    }
112}
113
114impl<T: Integer, I> ops::Not for NotIter<T, I>
115where
116    I: SortedDisjoint<T>,
117{
118    type Output = NotIter<T, Self>;
119
120    fn not(self) -> Self::Output {
121        // It would be fun to optimize to self.iter, but that would require
122        // also considering fields 'start_not' and 'next_time_return_none'.
123        self.complement()
124    }
125}
126
127impl<T: Integer, R, L> ops::BitOr<R> for NotIter<T, L>
128where
129    L: SortedDisjoint<T>,
130    R: SortedDisjoint<T>,
131{
132    type Output = BitOrMerge<T, Self, R>;
133
134    fn bitor(self, other: R) -> Self::Output {
135        SortedDisjoint::union(self, other)
136    }
137}
138
139impl<T: Integer, R, L> ops::Sub<R> for NotIter<T, L>
140where
141    L: SortedDisjoint<T>,
142    R: SortedDisjoint<T>,
143{
144    type Output = BitSubMerge<T, Self, R>;
145
146    fn sub(self, other: R) -> Self::Output {
147        // It would be fun to optimize !!self.iter into self.iter
148        // but that would require also considering fields 'start_not' and 'next_time_return_none'.
149        SortedDisjoint::difference(self, other)
150    }
151}
152
153impl<T: Integer, R, L> ops::BitXor<R> for NotIter<T, L>
154where
155    L: SortedDisjoint<T>,
156    R: SortedDisjoint<T>,
157{
158    type Output = BitXOrTee<T, Self, R>;
159
160    #[allow(clippy::suspicious_arithmetic_impl)]
161    fn bitxor(self, other: R) -> Self::Output {
162        // It would be fine optimize !!self.iter into self.iter, ala
163        // ¬(¬n ∨ ¬r) ∨ ¬(n ∨ r) // https://www.wolframalpha.com/input?i=%28not+n%29+xor+r
164        // but that would require also considering fields 'start_not' and 'next_time_return_none'.
165        SortedDisjoint::symmetric_difference(self, other)
166    }
167}
168
169impl<T: Integer, R, L> ops::BitAnd<R> for NotIter<T, L>
170where
171    L: SortedDisjoint<T>,
172    R: SortedDisjoint<T>,
173{
174    type Output = BitAndMerge<T, Self, R>;
175
176    fn bitand(self, other: R) -> Self::Output {
177        // It would be fun to optimize !!self.iter into self.iter
178        // but that would require also considering fields 'start_not' and 'next_time_return_none'.
179        SortedDisjoint::intersection(self, other)
180    }
181}
182
183// FUTURE define Not, etc on DynSortedDisjoint