moc/moc2d/builder/
maxdepths_cell.rs

1//! Builder in which we add (Time, Hpx) cells at the MOC maximum given depths.
2
3use std::cmp::Ordering;
4
5use crate::{
6  moc::{builder::fixed_depth::FixedDepthMocBuilder, range::RangeMOC},
7  moc2d::{Idx, RangeMOC2, RangeMOC2Elem},
8  qty::MocQty,
9};
10
11pub struct FixedDepth2DMocBuilder<T: Idx, Q: MocQty<T>, U: Idx, R: MocQty<U>> {
12  depth_1: u8,
13  depth_2: u8,
14  buff: Vec<(T, U)>,
15  sorted: bool,
16  moc: Option<RangeMOC2<T, Q, U, R>>,
17}
18
19impl<T: Idx, Q: MocQty<T>, U: Idx, R: MocQty<U>> FixedDepth2DMocBuilder<T, Q, U, R> {
20  pub fn new(depth_1: u8, depth_2: u8, buf_capacity: Option<usize>) -> Self {
21    Self {
22      depth_1,
23      depth_2,
24      buff: Vec::with_capacity(buf_capacity.unwrap_or(100_000)),
25      sorted: true,
26      moc: None,
27    }
28  }
29
30  pub fn push(&mut self, idx_1: T, idx_2: U) {
31    if let Some((h1, h2)) = self.buff.last() {
32      if *h1 == idx_1 && *h2 == idx_2 {
33        return;
34      } else if self.sorted && *h1 > idx_1 {
35        self.sorted = false;
36      }
37    }
38    self.buff.push((idx_1, idx_2));
39    if self.buff.len() == self.buff.capacity() {
40      self.drain_buffer();
41    }
42  }
43
44  pub fn into_moc(mut self) -> RangeMOC2<T, Q, U, R> {
45    self.drain_buffer();
46    let depth_1 = self.depth_1;
47    let depth_2 = self.depth_2;
48    self
49      .moc
50      .unwrap_or_else(|| RangeMOC2::new(depth_1, depth_2, Default::default()))
51  }
52
53  fn drain_buffer(&mut self) {
54    if !self.sorted {
55      // Sort on the first dim
56      self
57        .buff
58        .sort_unstable_by(|(h1_a, _), (h1_b, _)| h1_a.cmp(h1_b));
59    }
60    let new_moc = self.buff_to_moc();
61    self.clear_buff();
62    let merged_moc = if let Some(prev_moc) = &self.moc {
63      prev_moc.or(&new_moc)
64    } else {
65      new_moc
66    };
67    self.moc.replace(merged_moc);
68  }
69
70  fn buff_to_moc(&self) -> RangeMOC2<T, Q, U, R> {
71    // Entering here, the buffer ( buff: Vec<(T, U)> ) is sorted on T
72    // Build first Vec<T, RangeMOC<U, R>>
73    // Then merge successive T having the same  RangeMOC<U, R>
74    let mut range_mocs: Vec<RangeMOC2Elem<T, Q, U, R>> = Vec::with_capacity(self.buff.len());
75
76    // We assume here that the buffer is ordered, but may contains duplicates
77    let mut it = self.buff.iter();
78    if let Some((from_1, from_2)) = it.next() {
79      let mut from_1 = *from_1;
80      let from_2 = *from_2;
81      let mut moc_builder_1 = FixedDepthMocBuilder::<T, Q>::new(self.depth_1, Some(64));
82      moc_builder_1.push(from_1);
83      let mut moc_builder_2 = FixedDepthMocBuilder::<U, R>::new(self.depth_2, Some(1000));
84      moc_builder_2.push(from_2);
85      let mut prev_moc_2: Option<RangeMOC<U, R>> = None;
86      for (curr_1, curr_2) in it {
87        match from_1.cmp(curr_1) {
88          Ordering::Equal => moc_builder_2.push(*curr_2), //  No change in time => update space
89          Ordering::Less => {
90            // There is a change in time, build moc_2
91            let moc_2 = moc_builder_2.into_moc();
92            debug_assert!(!moc_2.is_empty());
93            // Check whether or not the moc_2 is the same as the on in the current moc_1_builder
94            if let Some(p_moc_2) = prev_moc_2.as_ref() {
95              if !moc_2.eq(p_moc_2) {
96                // if not create a new entry
97                let p_moc_1 = moc_builder_1.into_moc();
98                let p_moc_2 = prev_moc_2.replace(moc_2).unwrap();
99                debug_assert!(!p_moc_1.is_empty());
100                debug_assert!(!p_moc_2.is_empty());
101                range_mocs.push(RangeMOC2Elem::new(p_moc_1, p_moc_2));
102                moc_builder_1 = FixedDepthMocBuilder::<T, Q>::new(self.depth_1, Some(64));
103                moc_builder_1.push(from_1);
104              } else {
105                moc_builder_1.push(from_1);
106              }
107            } else {
108              // First loop iteration, simply set prev_moc_2
109              // in such a case, the current moc_2 equals the prev_moc_2
110              // current moc_builder_1 contains the current moc_1 associated to prev_moc_2
111              prev_moc_2 = Some(moc_2);
112              // No need to push from_1, it is already in the builder
113            }
114            // Update tmp variables
115            moc_builder_2 = FixedDepthMocBuilder::<U, R>::new(self.depth_2, Some(1000));
116            moc_builder_2.push(*curr_2);
117            from_1 = *curr_1;
118          }
119          Ordering::Greater => unreachable!(), // self.buff supposed to be sorted!
120        }
121      }
122      let moc_2 = moc_builder_2.into_moc();
123      if let Some(p_moc_2) = prev_moc_2.as_ref() {
124        if !moc_2.eq(p_moc_2) {
125          // if not create a new entry
126          let p_moc_1 = moc_builder_1.into_moc();
127          let p_moc_2 = prev_moc_2.replace(moc_2).unwrap();
128          debug_assert!(!p_moc_1.is_empty());
129          debug_assert!(!p_moc_2.is_empty());
130          range_mocs.push(RangeMOC2Elem::new(p_moc_1, p_moc_2));
131          moc_builder_1 = FixedDepthMocBuilder::<T, Q>::new(self.depth_1, Some(64));
132          moc_builder_1.push(from_1);
133          let moc_1 = moc_builder_1.into_moc();
134          range_mocs.push(RangeMOC2Elem::new(moc_1, prev_moc_2.unwrap()));
135        } else {
136          moc_builder_1.push(from_1);
137          let moc_1 = moc_builder_1.into_moc();
138          debug_assert!(!moc_1.is_empty());
139          debug_assert!(!moc_2.is_empty());
140          range_mocs.push(RangeMOC2Elem::new(moc_1, moc_2));
141        }
142      } else {
143        let moc_1 = moc_builder_1.into_moc();
144        debug_assert!(!moc_1.is_empty());
145        debug_assert!(!moc_2.is_empty());
146        range_mocs.push(RangeMOC2Elem::new(moc_1, moc_2));
147      }
148    }
149    RangeMOC2::new(self.depth_1, self.depth_2, range_mocs)
150  }
151
152  fn clear_buff(&mut self) {
153    self.sorted = true;
154    self.buff.clear();
155  }
156}
157
158#[cfg(test)]
159mod tests {
160
161  use super::FixedDepth2DMocBuilder;
162  use crate::qty::{Frequency, Hpx};
163
164  #[test]
165  fn test_build2dmoc_fixeddepth() {
166    let mut builder =
167      FixedDepth2DMocBuilder::<u64, Frequency<u64>, u64, Hpx<u64>>::new(10, 11, None);
168    builder.push(1, 1);
169    builder.push(2, 3);
170    builder.push(4, 6);
171    let moc2d = builder.into_moc();
172    assert_eq!(moc2d.compute_n_ranges(), 6);
173    /*moc2d
174    .into_range_moc2_iter()
175    .into_cellcellrange_moc2_iter()
176    .to_ascii_ivoa(Some(80), false, io::stdout())
177    .map_err(|e| e.to_string())
178    .unwrap();*/
179  }
180}