Skip to main content

moc/ranges/
mod.rs

1//! Very generic ranges operations
2
3use std::{
4  cmp::{self, Ordering},
5  collections::VecDeque,
6  mem,
7  ops::{Index, Range},
8  ptr::slice_from_raw_parts,
9  slice::Iter,
10};
11
12use num::{Integer, One, PrimInt, Zero};
13#[cfg(not(target_arch = "wasm32"))]
14use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
15#[cfg(not(target_arch = "wasm32"))]
16use rayon::prelude::*;
17
18use crate::{idx::Idx, utils};
19
20pub mod ranges2d;
21
22/// Generic operations on a set of Sorted and Non-Overlapping ranges.
23/// SNO = Sorted Non-Overlapping
24pub trait SNORanges<'a, T: Idx>: Sized {
25  type OwnedRanges: SNORanges<'a, T>;
26
27  type Iter: Iterator<Item = &'a Range<T>>;
28  #[cfg(not(target_arch = "wasm32"))]
29  type ParIter: ParallelIterator<Item = &'a Range<T>>;
30
31  fn is_empty(&self) -> bool;
32
33  /// The iterator **MUST** return sorted and non-overlapping ranges
34  fn iter(&'a self) -> Self::Iter;
35
36  #[cfg(not(target_arch = "wasm32"))]
37  fn par_iter(&'a self) -> Self::ParIter;
38
39  fn intersects_range(&self, x: &Range<T>) -> bool;
40  #[cfg(not(target_arch = "wasm32"))]
41  fn par_intersects_range(&'a self, x: &Range<T>) -> bool {
42    self
43      .par_iter()
44      .map(|r| !(x.start >= r.end || x.end <= r.start))
45      .any(|a| a)
46  }
47
48  fn contains_val(&self, x: &T) -> bool;
49
50  fn contains_range(&self, x: &Range<T>) -> bool;
51  #[cfg(not(target_arch = "wasm32"))]
52  fn par_contains_range(&'a self, x: &Range<T>) -> bool {
53    self
54      .par_iter()
55      .map(|r| x.start >= r.start && x.end <= r.end)
56      .any(|a| a)
57  }
58
59  /// Returns the fraction of the given range `x` covered by this (`self`) set of ranges.
60  /// So:
61  /// * if the given range `x` if fully covered, the result is 1.0.
62  /// * if half of the given range `x` is covered, the result is 0.5.
63  /// * if the given range is **not** covered, the result is 0.0.
64  fn range_fraction(&self, x: &Range<T>) -> f64;
65
66  fn contains(&self, rhs: &'a Self) -> bool {
67    // TODO: implement a more efficient algo, avoiding to re-explore the sub-part of self
68    // already explored (since rhs ranges are also ordered!)
69    for range in rhs.iter() {
70      if !self.contains_range(range) {
71        return false;
72      }
73    }
74    true
75  }
76
77  /// Returns the sum of the ranges lengths
78  fn range_sum(&'a self) -> T {
79    let mut sum = T::zero();
80    for Range { start, end } in self.iter() {
81      sum += *end - *start;
82    }
83    sum
84  }
85
86  fn intersects(&self, rhs: &Self) -> bool;
87
88  fn merge(&self, other: &Self, op: impl Fn(bool, bool) -> bool) -> Self::OwnedRanges;
89
90  fn union(&self, other: &Self) -> Self::OwnedRanges;
91  /*fn union(&self, other: &Self) -> Self {
92      self.merge(other, |a, b| a || b)
93  }*/
94
95  fn intersection(&self, other: &Self) -> Self::OwnedRanges;
96  /*fn intersection(&self, other: &Self) -> Self {
97      self.merge(other, |a, b| a && b)
98  }*/
99
100  //  = minus
101  // != (symmtric difference = xor)
102  fn difference(&self, other: &Self) -> Self::OwnedRanges {
103    self.merge(other, |a, b| a && !b)
104  }
105
106  /// Returns the complement assuming that the possible values are
107  /// in `[0, upper_bound_exclusive[`.
108  fn complement_with_upper_bound(&self, upper_bound_exclusive: T) -> Self::OwnedRanges;
109
110  /// Performs a logical OR between all the bounds of all ranges,
111  /// and returns the number of trailing zeros.
112  fn trailing_zeros(&'a self) -> u8 {
113    let all_vals_or: T = self
114      .iter()
115      .fold(Zero::zero(), |res, x| res | x.start | x.end);
116    all_vals_or.trailing_zeros() as u8
117  }
118
119  /// Performs a logical OR between all the bounds of all ranges,
120  /// and returns the number of trailing zeros.
121  #[cfg(not(target_arch = "wasm32"))]
122  fn par_trailing_zeros(&'a self) -> u8 {
123    let all_vals_or: T = self
124      .par_iter()
125      .fold(T::zero, |res, x| res | x.start | x.end)
126      .reduce(T::zero, |a, b| a | b);
127    all_vals_or.trailing_zeros() as u8
128  }
129}
130
131/// Generic Range operations
132/// We use a `Boxed array` instead of `Vec` because we use possibly a lot of them in
133/// 2D-MOCs, so in may because not negligible to spare the capacity info.
134#[derive(Clone, Debug)]
135pub struct Ranges<T: Idx>(pub Box<[Range<T>]>);
136
137impl<T: Idx> Default for Ranges<T> {
138  fn default() -> Self {
139    Ranges(Default::default())
140  }
141}
142
143impl<T: Idx> Ranges<T> {
144  /// Assumes (without checking!) that the input vector of range is already sorted and do not
145  /// contains overlapping (or consecutive) ranges
146  pub fn new_unchecked(data: Vec<Range<T>>) -> Self {
147    Ranges(data.into_boxed_slice())
148  }
149
150  /// Assumes (without checking!) that the input vector of range is already sorted **BUT**
151  /// may contains overlapping (or consecutive) ranges.
152  pub fn new_from_sorted(data: Vec<Range<T>>) -> Self {
153    Self::new_unchecked(MergeOverlappingRangesIter::new(data.iter(), None).collect::<Vec<_>>())
154  }
155
156  /// Internally sorts the input vector and ensures there is no overlapping (or consecutive) ranges.
157  pub fn new_from(mut data: Vec<Range<T>>) -> Self {
158    #[cfg(not(target_arch = "wasm32"))]
159    data.par_sort_unstable_by(|left, right| left.start.cmp(&right.start));
160    #[cfg(target_arch = "wasm32")]
161    (&mut data).sort_unstable_by(|left, right| left.start.cmp(&right.start));
162    Self::new_from_sorted(data)
163  }
164
165  pub fn as_bytes(&self) -> &[u8] {
166    let offset = self.0.as_ptr().align_offset(mem::align_of::<u8>());
167    // I suppose that align with u8 is never a problem.
168    assert_eq!(offset, 0);
169    unsafe {
170      std::slice::from_raw_parts(
171        self.0.as_ptr() as *const u8,
172        (self.0.len() << 1) * std::mem::size_of::<T>(),
173      )
174    }
175  }
176
177  /*/// Make the `Ranges<T>` consistent
178  ///
179  /// # Info
180  ///
181  /// By construction, the data are sorted so that it is possible (see the new
182  /// method definition above) to merge the overlapping ranges.
183  pub fn make_consistent(mut self) -> Self {
184      self.0 = MergeOverlappingRangesIter::new(self.iter(), None).collect::<Vec<_>>();
185      self
186  }*/
187}
188
189impl<T: Idx> PartialEq for Ranges<T> {
190  fn eq(&self, other: &Self) -> bool {
191    self.0 == other.0
192  }
193}
194
195impl<T: Idx> Index<usize> for Ranges<T> {
196  type Output = Range<T>;
197
198  fn index(&self, index: usize) -> &Range<T> {
199    &self.0[index]
200  }
201}
202
203impl<'a, T: Idx> SNORanges<'a, T> for Ranges<T> {
204  type OwnedRanges = Self;
205
206  type Iter = Iter<'a, Range<T>>;
207  #[cfg(not(target_arch = "wasm32"))]
208  type ParIter = rayon::slice::Iter<'a, Range<T>>;
209
210  fn is_empty(&self) -> bool {
211    self.0.is_empty()
212  }
213
214  fn iter(&'a self) -> Self::Iter {
215    self.0.iter()
216  }
217
218  #[cfg(not(target_arch = "wasm32"))]
219  fn par_iter(&'a self) -> Self::ParIter {
220    self.0.par_iter()
221  }
222
223  fn intersects_range(&self, x: &Range<T>) -> bool {
224    BorrowedRanges(&self.0).intersects_range(x)
225  }
226
227  fn contains_val(&self, x: &T) -> bool {
228    BorrowedRanges(&self.0).contains_val(x)
229  }
230
231  fn contains_range(&self, x: &Range<T>) -> bool {
232    BorrowedRanges(&self.0).contains_range(x)
233  }
234
235  fn range_fraction(&self, x: &Range<T>) -> f64 {
236    BorrowedRanges(&self.0).range_fraction(x)
237  }
238
239  fn intersects(&self, rhs: &Self) -> bool {
240    BorrowedRanges(&self.0).intersects(&BorrowedRanges(&rhs.0))
241  }
242
243  fn union(&self, other: &Self) -> Self {
244    BorrowedRanges(&self.0).union(&BorrowedRanges(&other.0))
245  }
246
247  fn intersection(&self, other: &Self) -> Self {
248    BorrowedRanges(&self.0).intersection(&BorrowedRanges(&other.0))
249  }
250
251  #[allow(clippy::many_single_char_names)]
252  fn merge(&self, other: &Self, op: impl Fn(bool, bool) -> bool) -> Self {
253    BorrowedRanges(&self.0).merge(&BorrowedRanges(&other.0), op)
254  }
255
256  fn complement_with_upper_bound(&self, upper_bound_exclusive: T) -> Self {
257    BorrowedRanges(&self.0).complement_with_upper_bound(upper_bound_exclusive)
258  }
259}
260
261/// To perform operations on e.g. a buffer without having to own the ranges
262pub struct BorrowedRanges<'a, T: Idx>(pub &'a [Range<T>]);
263
264impl<'a, T: Idx> From<&'a Ranges<T>> for BorrowedRanges<'a, T> {
265  fn from(ranges: &'a Ranges<T>) -> Self {
266    BorrowedRanges(&ranges.0)
267  }
268}
269
270impl<'a, T: Idx> From<&'a [u8]> for BorrowedRanges<'a, T> {
271  fn from(blob: &'a [u8]) -> Self {
272    let offset = blob.as_ptr().align_offset(mem::align_of::<Range<T>>());
273    if offset != 0 {
274      panic!("Not aligned array!!");
275    }
276    let len = blob.len() / std::mem::size_of::<Range<T>>();
277    debug_assert_eq!(blob.len(), len * std::mem::size_of::<Range<T>>());
278    BorrowedRanges(unsafe { &*slice_from_raw_parts(blob.as_ptr() as *const Range<T>, len) })
279  }
280}
281
282impl<'a, T: Idx> BorrowedRanges<'a, T> {
283  pub fn as_bytes(&self) -> &[u8] {
284    let offset = self.0.as_ptr().align_offset(mem::align_of::<u8>());
285    // I suppose that align with u8 is never a problem.
286    assert_eq!(offset, 0);
287    unsafe {
288      std::slice::from_raw_parts(
289        self.0.as_ptr() as *const u8,
290        (self.0.len() << 1) * std::mem::size_of::<T>(),
291      )
292    }
293  }
294}
295
296impl<'a, T: Idx> SNORanges<'a, T> for BorrowedRanges<'a, T> {
297  type OwnedRanges = Ranges<T>;
298
299  type Iter = Iter<'a, Range<T>>;
300  #[cfg(not(target_arch = "wasm32"))]
301  type ParIter = rayon::slice::Iter<'a, Range<T>>;
302
303  fn is_empty(&self) -> bool {
304    self.0.is_empty()
305  }
306
307  fn iter(&'a self) -> Self::Iter {
308    self.0.iter()
309  }
310
311  #[cfg(not(target_arch = "wasm32"))]
312  fn par_iter(&'a self) -> Self::ParIter {
313    self.0.par_iter()
314  }
315
316  // The MOC **MUST BE** consistent!
317  fn intersects_range(&self, x: &Range<T>) -> bool {
318    let len = self.0.len();
319    // Quick rejection test
320    if len == 0 || x.end <= self.0[0].start || self.0[len - 1].end <= x.start {
321      return false;
322    }
323    let len = len << 1;
324    let ptr = self.0.as_ptr();
325    // It is ok because (see test test_alignment()):
326    // * T is a primitive type in practice, and size_of(T) << 1 == size_of(Range<T>)
327    // * the alignment of Range<T> is the same as the alignment of T (see test_alignment)
328    // But: https://rust-lang.github.io/unsafe-code-guidelines/layout/structs-and-tuples.html
329    let result: &[T] = unsafe { &*slice_from_raw_parts(ptr as *const T, len) };
330    match result.binary_search(&x.start) {
331      Ok(i) => {
332        i & 1 == 0 // even index => x.start = range.start => Ok
333                  || (i + 1 < len && x.end > result[i + 1]) // else (odd index) => upper bound => Check x.end > next range.start
334      }
335      Err(i) => {
336        i & 1 == 1 // index is odd => x.start inside the range
337                  || (i < len && x.end > result[i]) // else (even index) => Check x.end > range.start
338      }
339    }
340  }
341
342  // The MOC **MUST BE** consistent!
343  fn contains_val(&self, x: &T) -> bool {
344    let len = self.0.len();
345    // Quick rejection test
346    if len == 0 || *x < self.0[0].start || self.0[len - 1].end <= *x {
347      return false;
348    }
349    let len = len << 1;
350    let ptr = self.0.as_ptr();
351    // It is ok because (see test test_alignment()):
352    // * T is a primitive type in practice, and size_of(T) << 1 == size_of(Range<T>)
353    // * the alignment of Range<T> is the same as the alignment of T (see test_alignment)
354    // But: https://rust-lang.github.io/unsafe-code-guidelines/layout/structs-and-tuples.html
355    let result: &[T] = unsafe { &*slice_from_raw_parts(ptr as *const T, len) };
356    // Performs a binary search in it
357    match result.binary_search(x) {
358      Ok(i) => i & 1 == 0,  // index must be even (lower bound of a range)
359      Err(i) => i & 1 == 1, // index must be odd (inside a range)
360    }
361  }
362
363  // The MOC **MUST BE** consistent!
364  fn contains_range(&self, x: &Range<T>) -> bool {
365    let len = self.0.len();
366    // Quick rejection test
367    if len == 0 || x.end <= self.0[0].start || self.0[len - 1].end <= x.start {
368      return false;
369    }
370    let len = len << 1;
371    let ptr = self.0.as_ptr();
372    // It is ok because (see test test_alignment()):
373    // * T is a primitive type in practice, and size_of(T) << 1 == size_of(Range<T>)
374    // * the alignment of Range<T> is the same as the alignment of T (see test_alignment)
375    // But: https://rust-lang.github.io/unsafe-code-guidelines/layout/structs-and-tuples.html
376    let result: &[T] = unsafe { &*slice_from_raw_parts(ptr as *const T, len) };
377    // Performs a binary search in it
378    match result.binary_search(&x.start) {
379      Ok(i) => i & 1 == 0 && x.end <= result[i | 1], // index must be even (lower bound of a range)
380      Err(i) => i & 1 == 1 && x.end <= result[i],    // index must be odd (inside a range)
381    }
382  }
383
384  // The MOC **MUST BE** consistent!
385  /// Warning: if the order difference is larger that 26, the result may be approximate (52 bit
386  /// in a f64 mantissa!)
387  fn range_fraction(&self, x: &Range<T>) -> f64 {
388    let mut width = T::zero();
389    let ranges = self.0;
390    if ranges.is_empty() || x.end <= ranges[0].start || ranges[ranges.len() - 1].end <= x.start {
391      // quick rejection test
392      0.0
393    } else {
394      // Find the starting range
395      let i = match ranges.binary_search_by(|range| range.start.cmp(&x.start)) {
396        Ok(i) => i,
397        Err(i) => {
398          if i > 0 && ranges[i - 1].end > x.start {
399            i - 1
400          } else {
401            i
402          }
403        }
404      };
405      // Iterate from the starting element
406      for range in ranges[i..].iter() {
407        if x.end <= range.start {
408          // |--x--| |--range--|
409          break;
410        } else {
411          let start = range.start.max(x.start);
412          let end = range.end.min(x.end);
413          width += end - start;
414        }
415      }
416      // Compute fraction
417      let mut tot = x.end - x.start;
418      if width == T::zero() {
419        0.0
420      } else if width == tot {
421        1.0
422      } else {
423        // Deal with numerical precision...
424        if tot.unsigned_shr(52) > T::zero() {
425          // 52 = n mantissa bits in a f64
426          // Divide by the same power of 2, dropping the LSBs
427          // Shift chosen so that 'tot' leading 1 is lower than 1^52
428          let shift = T::N_BITS as u32 - tot.unsigned_shr(52).leading_zeros();
429          width = width.unsigned_shr(shift);
430          tot = tot.unsigned_shr(shift);
431        }
432        width.cast_to_f64() / tot.cast_to_f64()
433      }
434    }
435  }
436
437  fn intersects(&self, rhs: &Self) -> bool {
438    // Quickly adapted from "intersection", we may find a better option
439    let l = &self.0;
440    let r = &rhs.0;
441    // Quick rejection test
442    if l.is_empty()
443      || r.is_empty()
444      || l[0].start >= r[r.len() - 1].end
445      || l[l.len() - 1].end <= r[0].start
446    {
447      return false;
448    }
449    // Use binary search to find the starting indices
450    let (il, ir) = match l[0].start.cmp(&r[0].start) {
451      Ordering::Less => {
452        let il = match l.binary_search_by(|l_range| l_range.start.cmp(&r[0].start)) {
453          Ok(i) => i,
454          Err(i) => i - 1,
455        };
456        (il, 0)
457      }
458      Ordering::Greater => {
459        let ir = match r.binary_search_by(|r_range| r_range.start.cmp(&l[0].start)) {
460          Ok(i) => i,
461          Err(i) => i - 1,
462        };
463        (0, ir)
464      }
465      Ordering::Equal => (0, 0),
466    };
467    // Now simple sequential algo
468    let mut left_it = l[il..].iter();
469    let mut right_it = r[ir..].iter();
470    let mut left = left_it.next();
471    let mut right = right_it.next();
472    while let (Some(el), Some(er)) = (&left, &right) {
473      if el.end <= er.start {
474        // |--l--| |--r--|
475        left = left_it.next();
476        while let Some(el) = &left {
477          if el.end <= er.start {
478            left = left_it.next();
479          } else {
480            break;
481          }
482        }
483      } else if er.end <= el.start {
484        // |--r--| |--l--|
485        right = right_it.next();
486        while let Some(er) = &right {
487          if er.end <= el.start {
488            right = right_it.next();
489          } else {
490            break;
491          }
492        }
493      } else {
494        return true;
495      }
496    }
497    false
498  }
499
500  #[allow(clippy::many_single_char_names)]
501  fn merge(&self, other: &Self, op: impl Fn(bool, bool) -> bool) -> Self::OwnedRanges {
502    let l = &self.0;
503    let ll = l.len() << 1;
504
505    let r = &other.0;
506    let rl = r.len() << 1;
507
508    let mut i = 0;
509    let mut j = 0;
510
511    let mut result = Vec::with_capacity(ll + rl);
512
513    while i < ll || j < rl {
514      let (in_l, in_r, c) = if i == ll {
515        let rv = if j & 0x1 != 0 {
516          r[j >> 1].end
517        } else {
518          r[j >> 1].start
519        };
520
521        let on_rising_edge_t2 = (j & 0x1) == 0;
522
523        let in_l = false;
524        let in_r = on_rising_edge_t2;
525
526        j += 1;
527
528        (in_l, in_r, rv)
529      } else if j == rl {
530        let lv = if i & 0x1 != 0 {
531          l[i >> 1].end
532        } else {
533          l[i >> 1].start
534        };
535
536        let on_rising_edge_t1 = (i & 0x1) == 0;
537
538        let in_l = on_rising_edge_t1;
539        let in_r = false;
540
541        i += 1;
542
543        (in_l, in_r, lv)
544      } else {
545        let lv = if i & 0x1 != 0 {
546          l[i >> 1].end
547        } else {
548          l[i >> 1].start
549        };
550        let rv = if j & 0x1 != 0 {
551          r[j >> 1].end
552        } else {
553          r[j >> 1].start
554        };
555
556        let on_rising_edge_t1 = (i & 0x1) == 0;
557        let on_rising_edge_t2 = (j & 0x1) == 0;
558
559        let c = cmp::min(lv, rv);
560
561        let in_l = (on_rising_edge_t1 && c == lv) | (!on_rising_edge_t1 && c < lv);
562        let in_r = (on_rising_edge_t2 && c == rv) | (!on_rising_edge_t2 && c < rv);
563
564        if c == lv {
565          i += 1;
566        }
567        if c == rv {
568          j += 1;
569        }
570
571        (in_l, in_r, c)
572      };
573
574      let closed = (result.len() & 0x1) == 0;
575
576      let add = !(closed ^ op(in_l, in_r));
577      if add {
578        result.push(c);
579      }
580    }
581    result.shrink_to_fit();
582    Ranges::new_unchecked(utils::unflatten(&mut result))
583  }
584
585  fn union(&self, other: &Self) -> Self::OwnedRanges {
586    let l = self.0;
587    let r = other.0;
588    // Deal with cases in which one of the two ranges (or both) is empty
589    if l.is_empty() {
590      return Ranges(r.to_vec().into_boxed_slice());
591    } else if r.is_empty() {
592      return Ranges(l.to_vec().into_boxed_slice());
593    }
594    // Trivial case (simple concatenation)
595    // - unwrap is safe here, because we test l.is_empty() and r.ie_empty() before
596    if l.last().unwrap().end < r.first().unwrap().start {
597      return Ranges::new_unchecked(l.iter().cloned().chain(r.iter().cloned()).collect());
598    } else if r.last().unwrap().end < l.first().unwrap().start {
599      return Ranges::new_unchecked(r.iter().cloned().chain(l.iter().cloned()).collect());
600    }
601    // Init result
602    let mut res = Vec::with_capacity(l.len() + r.len());
603    // Else, Use binary search to find the starting indices (and starts with a simple array copy)
604    let (il, ir) = if l[0].end < r[0].start {
605      let il = match l.binary_search_by(|l_range| l_range.end.cmp(&r[0].start)) {
606        Ok(i) => i,
607        Err(i) => i,
608      };
609      res.extend_from_slice(&l[..il]);
610      (il, 0)
611    } else if l[0].start > r[0].end {
612      let ir = match r.binary_search_by(|r_range| r_range.end.cmp(&l[0].start)) {
613        Ok(i) => i,
614        Err(i) => i,
615      };
616      res.extend_from_slice(&r[..ir]);
617      (0, ir)
618    } else {
619      (0, 0)
620    };
621    // Now regular work
622    let mut left_it = l[il..].iter();
623    let mut right_it = r[ir..].iter();
624    let mut left = left_it.next().cloned();
625    let mut right = right_it.next().cloned();
626
627    fn consume_while_end_lower_than<'a, T, I>(it: &mut I, to: T) -> Option<&'a Range<T>>
628    where
629      T: Idx,
630      I: Iterator<Item = &'a Range<T>>,
631    {
632      let mut curr = it.next();
633      while let Some(c) = &curr {
634        if c.end > to {
635          break;
636        } else {
637          curr = it.next();
638        }
639      }
640      curr
641    }
642
643    loop {
644      match (&mut left, &mut right) {
645        (Some(ref mut l), Some(ref mut r)) => {
646          if l.end < r.start {
647            // L--L R--R
648            res.push(mem::replace(&mut left, left_it.next().cloned()).unwrap());
649          } else if r.end < l.start {
650            // R--R L--L
651            res.push(mem::replace(&mut right, right_it.next().cloned()).unwrap());
652          } else if l.end <= r.end {
653            //    R--L--L--R
654            if l.start < r.start {
655              // or L--R--L--R
656              r.start = l.start;
657            }
658            left = consume_while_end_lower_than(&mut left_it, r.end).cloned();
659          } else {
660            //    L--R--R--L
661            if r.start < l.start {
662              // or R--L--R--L
663              l.start = r.start;
664            }
665            right = consume_while_end_lower_than(&mut right_it, l.end).cloned();
666          }
667        }
668        (Some(ref l), None) => {
669          res.push(l.clone());
670          for l in left_it {
671            res.push(l.clone());
672          }
673          break;
674        }
675        (None, Some(ref r)) => {
676          res.push(r.clone());
677          for r in right_it {
678            res.push(r.clone());
679          }
680          break;
681        }
682        (None, None) => break,
683      };
684    }
685    res.shrink_to_fit();
686    Ranges::new_unchecked(res)
687  }
688
689  fn intersection(&self, other: &Self) -> Self::OwnedRanges {
690    // utils.flatten()/unflaten()
691    let l = &self.0;
692    let r = &other.0;
693    // Quick rejection test
694    if l.is_empty()
695      || r.is_empty()
696      || l[0].start >= r[r.len() - 1].end
697      || l[l.len() - 1].end <= r[0].start
698    {
699      return Ranges(Default::default());
700    }
701    // Use binary search to find the starting indices
702    let (il, ir) = match l[0].start.cmp(&r[0].start) {
703      Ordering::Less => {
704        let il = match l.binary_search_by(|l_range| l_range.start.cmp(&r[0].start)) {
705          Ok(i) => i,
706          Err(i) => i - 1,
707        };
708        (il, 0)
709      }
710      Ordering::Greater => {
711        let ir = match r.binary_search_by(|r_range| r_range.start.cmp(&l[0].start)) {
712          Ok(i) => i,
713          Err(i) => i - 1,
714        };
715        (0, ir)
716      }
717      Ordering::Equal => (0, 0),
718    };
719    // Now simple sequential algo
720    let mut res = Vec::with_capacity(l.len() + r.len() - (il + ir));
721    let mut left_it = l[il..].iter();
722    let mut right_it = r[ir..].iter();
723    let mut left = left_it.next();
724    let mut right = right_it.next();
725    while let (Some(el), Some(er)) = (&left, &right) {
726      if el.end <= er.start {
727        // |--l--| |--r--|
728        left = left_it.next();
729        while let Some(el) = &left {
730          if el.end <= er.start {
731            left = left_it.next();
732          } else {
733            break;
734          }
735        }
736      } else if er.end <= el.start {
737        // |--r--| |--l--|
738        right = right_it.next();
739        while let Some(er) = &right {
740          if er.end <= el.start {
741            right = right_it.next();
742          } else {
743            break;
744          }
745        }
746      } else {
747        let from = el.start.max(er.start);
748        match el.end.cmp(&er.end) {
749          Ordering::Less => {
750            res.push(from..el.end);
751            left = left_it.next();
752          }
753          Ordering::Greater => {
754            res.push(from..er.end);
755            right = right_it.next();
756          }
757          Ordering::Equal => {
758            res.push(from..el.end);
759            left = left_it.next();
760            right = right_it.next();
761          }
762        }
763      }
764    }
765    res.shrink_to_fit();
766    Ranges::new_unchecked(res)
767  }
768
769  fn complement_with_upper_bound(&self, upper_bound_exclusive: T) -> Self::OwnedRanges {
770    let ranges = &self.0;
771    let mut result = Vec::<Range<T>>::with_capacity(ranges.len() + 1);
772
773    if self.is_empty() {
774      result.push(T::zero()..upper_bound_exclusive);
775    } else {
776      let mut s = 0;
777      let mut last = if ranges[0].start == T::zero() {
778        s = 1;
779        ranges[0].end
780      } else {
781        T::zero()
782      };
783
784      result = ranges
785        .iter()
786        .skip(s)
787        .map(|range| {
788          let r = last..range.start;
789          last = range.end;
790          r
791        })
792        .collect::<Vec<_>>();
793
794      if last < upper_bound_exclusive {
795        result.push(last..upper_bound_exclusive);
796      }
797    }
798    Ranges::new_unchecked(result)
799  }
800}
801
802#[derive(Debug)]
803pub struct MergeOverlappingRangesIter<'a, T>
804where
805  T: Integer,
806{
807  last: Option<Range<T>>,
808  ranges: Iter<'a, Range<T>>,
809  split_ranges: VecDeque<Range<T>>,
810  shift: Option<u32>,
811}
812
813impl<'a, T> MergeOverlappingRangesIter<'a, T>
814where
815  T: Integer + PrimInt,
816{
817  pub fn new(
818    mut ranges: Iter<'a, Range<T>>,
819    shift: Option<u32>,
820  ) -> MergeOverlappingRangesIter<'a, T> {
821    let last = ranges.next().cloned();
822    let split_ranges = VecDeque::<Range<T>>::new();
823    MergeOverlappingRangesIter {
824      last,
825      ranges,
826      split_ranges,
827      shift,
828    }
829  }
830
831  fn split_range(&self, range: Range<T>) -> VecDeque<Range<T>> {
832    let mut ranges = VecDeque::<Range<T>>::new();
833    match self.shift {
834      None => {
835        ranges.push_back(range);
836      }
837      Some(shift) => {
838        let mut mask: T = One::one();
839        mask = mask.unsigned_shl(shift) - One::one();
840
841        if range.end - range.start < mask {
842          ranges.push_back(range);
843        } else {
844          let offset = range.start & mask;
845          let mut s = range.start;
846          if offset > Zero::zero() {
847            s = (range.start - offset) + mask + One::one();
848            ranges.push_back(range.start..s);
849          }
850
851          while s + mask + One::one() < range.end {
852            let next = s + mask + One::one();
853            ranges.push_back(s..next);
854            s = next;
855          }
856
857          ranges.push_back(s..range.end);
858        }
859      }
860    }
861    ranges
862  }
863}
864
865impl<'a, T> Iterator for MergeOverlappingRangesIter<'a, T>
866where
867  T: Integer + PrimInt,
868{
869  type Item = Range<T>;
870
871  fn next(&mut self) -> Option<Self::Item> {
872    if !self.split_ranges.is_empty() {
873      return self.split_ranges.pop_front();
874    }
875
876    while let Some(curr) = self.ranges.next() {
877      let prev = self.last.as_mut().unwrap();
878      if curr.start <= prev.end {
879        prev.end = cmp::max(curr.end, prev.end);
880      } else {
881        let range = self.last.clone();
882        self.last = Some(curr.clone());
883
884        self.split_ranges = self.split_range(range.unwrap());
885        return self.split_ranges.pop_front();
886      }
887    }
888
889    if self.last.is_some() {
890      let range = self.last.clone();
891      self.last = None;
892
893      self.split_ranges = self.split_range(range.unwrap());
894      self.split_ranges.pop_front()
895    } else {
896      None
897    }
898  }
899}
900
901#[cfg(test)]
902mod tests {
903
904  use std::{
905    mem::{align_of, size_of},
906    ops::Range,
907  };
908
909  use num::PrimInt;
910  use rand::Rng;
911
912  use crate::{
913    qty::{Hpx, MocQty},
914    ranges::{Ranges, SNORanges},
915  };
916
917  #[test]
918  fn test_alignment() {
919    // Ensure alignement for unsafe code in contains
920    assert_eq!(align_of::<u32>(), align_of::<Range<u32>>());
921    assert_eq!(align_of::<u64>(), align_of::<Range<u64>>());
922    assert_eq!(align_of::<i32>(), align_of::<Range<i32>>());
923    assert_eq!(align_of::<i64>(), align_of::<Range<i64>>());
924
925    assert_eq!(size_of::<u32>() << 1, size_of::<Range<u32>>());
926    assert_eq!(size_of::<u64>() << 1, size_of::<Range<u64>>());
927    assert_eq!(size_of::<i32>() << 1, size_of::<Range<i32>>());
928    assert_eq!(size_of::<i64>() << 1, size_of::<Range<i64>>());
929  }
930
931  #[test]
932  fn merge_range() {
933    fn assert_merge(a: Vec<Range<u64>>, expected: Vec<Range<u64>>) {
934      let ranges = Ranges::<u64>::new_from(a);
935      let expected_ranges = Ranges::<u64>::new_unchecked(expected);
936
937      assert_eq!(ranges, expected_ranges);
938    }
939
940    assert_merge(vec![12..17, 3..5, 5..7, 6..8], vec![3..8, 12..17]);
941    assert_merge(vec![0..1, 2..5], vec![0..1, 2..5]);
942    assert_merge(vec![], vec![]);
943    assert_merge(vec![0..6, 7..9, 8..13], vec![0..6, 7..13]);
944  }
945
946  #[test]
947  fn test_union() {
948    fn assert_union(a: Vec<Range<u64>>, b: Vec<Range<u64>>, expected: Vec<Range<u64>>) {
949      let a = Ranges::<u64>::new_from(a);
950      let b = Ranges::<u64>::new_from(b);
951
952      let expected_ranges = Ranges::<u64>::new_unchecked(expected);
953      let ranges = a.union(&b);
954      assert_eq!(ranges, expected_ranges);
955    }
956
957    assert_union(
958      vec![12..17, 3..5, 5..7, 6..8],
959      vec![0..1, 2..5],
960      vec![0..1, 2..8, 12..17],
961    );
962    assert_union(
963      vec![12..17, 3..5, 5..7, 6..8],
964      vec![12..17, 3..5, 5..7, 6..8],
965      vec![3..8, 12..17],
966    );
967    assert_union(vec![], vec![], vec![]);
968    assert_union(vec![12..17], vec![], vec![12..17]);
969    assert_union(vec![], vec![12..17], vec![12..17]);
970    assert_union(vec![0..1, 2..3, 4..5], vec![1..22], vec![0..22]);
971    assert_union(vec![0..10], vec![15..22], vec![0..10, 15..22]);
972  }
973
974  #[test]
975  fn test_intersection() {
976    fn assert_intersection(a: Vec<Range<u64>>, b: Vec<Range<u64>>, expected: Vec<Range<u64>>) {
977      let a = Ranges::<u64>::new_from(a);
978      let b = Ranges::<u64>::new_from(b);
979
980      let expected_ranges = Ranges::<u64>::new_unchecked(expected);
981      let ranges = a.intersection(&b);
982      assert_eq!(ranges, expected_ranges);
983    }
984
985    assert_intersection(vec![12..17, 3..5, 5..7, 6..8], vec![0..1, 2..5], vec![3..5]);
986    assert_intersection(vec![], vec![0..1, 2..5], vec![]);
987    assert_intersection(vec![], vec![], vec![]);
988    assert_intersection(vec![2..6], vec![0..3, 4..8], vec![2..3, 4..6]);
989    assert_intersection(vec![2..6], vec![2..6, 7..8], vec![2..6]);
990    assert_intersection(vec![10..11], vec![10..11], vec![10..11]);
991  }
992
993  #[test]
994  fn test_difference() {
995    fn assert_difference(a: Vec<Range<u64>>, b: Vec<Range<u64>>, expected: Vec<Range<u64>>) {
996      let a = Ranges::<u64>::new_from(a);
997      let b = Ranges::<u64>::new_from(b);
998
999      let expected_ranges = Ranges::<u64>::new_unchecked(expected);
1000      let ranges = a.difference(&b);
1001      assert_eq!(ranges, expected_ranges);
1002    }
1003
1004    assert_difference(vec![0..20], vec![5..7], vec![0..5, 7..20]);
1005    assert_difference(vec![0..20], vec![0..20], vec![]);
1006    assert_difference(vec![0..20], vec![], vec![0..20]);
1007    assert_difference(vec![], vec![0..5], vec![]);
1008    assert_difference(vec![0..20], vec![19..22], vec![0..19]);
1009    assert_difference(vec![0..20], vec![25..27], vec![0..20]);
1010    assert_difference(
1011      vec![0..20],
1012      vec![1..2, 3..4, 5..6],
1013      vec![0..1, 2..3, 4..5, 6..20],
1014    );
1015  }
1016
1017  #[test]
1018  fn test_uniq_decompose() {
1019    macro_rules! uniq_to_pix_depth {
1020      ($t:ty, $size:expr) => {
1021        let mut rng = rand::rng();
1022        (0..$size).for_each(|_| {
1023          let depth = rng.random_range(Range {
1024            start: 0,
1025            end: Hpx::<$t>::MAX_DEPTH,
1026          });
1027
1028          let npix = 12 * 4.pow(depth as u32);
1029          let pix = rng.random_range(Range {
1030            start: 0,
1031            end: npix,
1032          });
1033
1034          let uniq = 4 * 4.pow(depth as u32) + pix;
1035          assert_eq!(Hpx::<$t>::from_uniq_hpx(uniq), (depth, pix));
1036        });
1037      };
1038    }
1039
1040    uniq_to_pix_depth!(u128, 10000);
1041    uniq_to_pix_depth!(u64, 10000);
1042    uniq_to_pix_depth!(u32, 10000);
1043    uniq_to_pix_depth!(u8, 10000);
1044  }
1045
1046  /*use test::Bencher;
1047
1048  #[bench]
1049  fn bench_uniq_to_depth_pix(b: &mut Bencher) {
1050      let mut rng = rand::thread_rng();
1051      let n = test::black_box(100000);
1052
1053      let uniq: Vec<u64> = (0..n)
1054          .map(|_| {
1055              let depth = rng.gen_range(0, 30);
1056
1057              let npix = 12 * 4.pow(depth);
1058              let pix = rng.gen_range(0, npix);
1059
1060              let u = 4 * 4.pow(depth) + pix;
1061              u
1062          })
1063          .collect();
1064
1065      b.iter(|| {
1066          uniq.iter()
1067              .fold(0, |a, b| a + (u64::pix_depth(*b).0 as u64))
1068      });
1069  }*/
1070}