moc/moc/range/op/
not.rs

1use std::ops::Range;
2
3use crate::idx::Idx;
4use crate::moc::{HasMaxDepth, MOCProperties, NonOverlapping, RangeMOCIterator, ZSorted};
5use crate::qty::MocQty;
6
7/// Performs a logical `NOT` on the input iterator of ranges (i.e. returns its complement).
8pub fn not<T, Q, I>(it: I) -> NotRangeIter<T, Q, I>
9where
10  T: Idx,
11  Q: MocQty<T>,
12  I: RangeMOCIterator<T, Qty = Q>,
13{
14  NotRangeIter::new(it)
15}
16
17/// Performs a logical `NOT` on the input iterator of ranges (i.e. returns its complement).
18pub struct NotRangeIter<T, Q, I>
19where
20  T: Idx,
21  Q: MocQty<T>,
22  I: RangeMOCIterator<T, Qty = Q>,
23{
24  it: I,
25  curr: Option<Range<T>>,
26  start: T,
27  n_cells_max: T,
28}
29
30impl<T, Q, I> NotRangeIter<T, Q, I>
31where
32  T: Idx,
33  Q: MocQty<T>,
34  I: RangeMOCIterator<T, Qty = Q>,
35{
36  pub fn new(mut it: I) -> NotRangeIter<T, Q, I> {
37    let n_cells_max = Q::n_cells_max();
38    match it.next() {
39      Some(range) => {
40        if range.start == T::zero() {
41          if range.end == n_cells_max {
42            // input = all domain => Not is empty
43            NotRangeIter {
44              it,
45              curr: None,
46              start: n_cells_max,
47              n_cells_max,
48            }
49          } else {
50            // look at the second range
51            match it.next() {
52              Some(range2) => NotRangeIter {
53                it,
54                curr: Some(range.end..range2.start),
55                start: range2.end,
56                n_cells_max,
57              },
58              None => NotRangeIter {
59                it,
60                curr: Some(range.end..n_cells_max),
61                start: n_cells_max,
62                n_cells_max,
63              },
64            }
65          }
66        } else {
67          // Case in which we have to add a cell before the first input cell
68          NotRangeIter {
69            it,
70            curr: Some(T::zero()..range.start),
71            start: range.end,
72            n_cells_max,
73          }
74        }
75      }
76      None => {
77        // The input is empty => Not is the full domain
78        NotRangeIter {
79          it,
80          curr: Some(T::zero()..n_cells_max),
81          start: n_cells_max,
82          n_cells_max,
83        }
84      }
85    }
86  }
87}
88
89impl<T, Q, I> HasMaxDepth for NotRangeIter<T, Q, I>
90where
91  T: Idx,
92  Q: MocQty<T>,
93  I: RangeMOCIterator<T, Qty = Q>,
94{
95  fn depth_max(&self) -> u8 {
96    self.it.depth_max()
97  }
98}
99impl<T, Q, I> ZSorted for NotRangeIter<T, Q, I>
100where
101  T: Idx,
102  Q: MocQty<T>,
103  I: RangeMOCIterator<T, Qty = Q>,
104{
105}
106impl<T, Q, I> NonOverlapping for NotRangeIter<T, Q, I>
107where
108  T: Idx,
109  Q: MocQty<T>,
110  I: RangeMOCIterator<T, Qty = Q>,
111{
112}
113impl<T, Q, I> MOCProperties for NotRangeIter<T, Q, I>
114where
115  T: Idx,
116  Q: MocQty<T>,
117  I: RangeMOCIterator<T, Qty = Q>,
118{
119}
120impl<T, Q, I> Iterator for NotRangeIter<T, Q, I>
121where
122  T: Idx,
123  Q: MocQty<T>,
124  I: RangeMOCIterator<T, Qty = Q>,
125{
126  type Item = Range<T>;
127
128  fn next(&mut self) -> Option<Self::Item> {
129    let new = if let Some(r) = self.it.next() {
130      Some(Range {
131        start: std::mem::replace(&mut self.start, r.end),
132        end: r.start,
133      })
134    } else if self.start == self.n_cells_max {
135      None
136    } else {
137      Some(Range {
138        start: std::mem::replace(&mut self.start, self.n_cells_max),
139        end: self.n_cells_max,
140      })
141    };
142    std::mem::replace(&mut self.curr, new)
143  }
144
145  fn size_hint(&self) -> (usize, Option<usize>) {
146    let cur = if self.curr.is_some() { 0 } else { 1 };
147    let size_hint = self.it.size_hint();
148    if let Some(n) = size_hint.1 {
149      // +1 for cases in which the last range does not includes the upper bound
150      (size_hint.0 + cur, Some(n + cur + 1))
151    } else {
152      (size_hint.0 + cur, None)
153    }
154  }
155}
156
157impl<T, Q, I> RangeMOCIterator<T> for NotRangeIter<T, Q, I>
158where
159  T: Idx,
160  Q: MocQty<T>,
161  I: RangeMOCIterator<T, Qty = Q>,
162{
163  type Qty = Q;
164
165  fn peek_last(&self) -> Option<&Range<T>> {
166    // self.it.peek_last()
167    // if not upper bound, return range.end..upper_bound
168    // else return none
169    None
170  }
171}