differential_dataflow/operators/
common.rs1use timely::progress::{Antichain, Timestamp};
16
17use crate::difference::{Multiply, Semigroup};
18use crate::lattice::Lattice;
19use crate::trace::Description;
20use crate::operators::reduce::sort_dedup;
21
22pub use crate::operators::ValueHistory;
23
24pub struct TimeHistory<T> {
28 history: Vec<(T, T)>,
31 buffer: Vec<T>,
33}
34
35impl<T> Default for TimeHistory<T> {
36 fn default() -> Self { TimeHistory { history: Vec::new(), buffer: Vec::new() } }
37}
38
39impl<T: Lattice + Clone + Ord> TimeHistory<T> {
40 pub fn new() -> Self { TimeHistory { history: Vec::new(), buffer: Vec::new() } }
42
43 pub fn load(&mut self, times: impl Iterator<Item = T>, advance_by: Option<&T>) {
46 self.history.clear();
47 self.buffer.clear();
48 for mut time in times {
49 if let Some(m) = advance_by {
50 time = time.join(m);
51 }
52 self.history.push((time.clone(), time));
53 }
54 self.history.sort_by(|x, y| y.0.cmp(&x.0));
55 self.history.iter_mut().reduce(|prev, cur| {
56 cur.1.meet_assign(&prev.1);
57 cur
58 });
59 }
60
61 pub fn time(&self) -> Option<&T> {
63 self.history.last().map(|x| &x.0)
64 }
65 pub fn meet(&self) -> Option<&T> {
67 self.history.last().map(|x| &x.1)
68 }
69
70 pub fn step_while_time_is(&mut self, time: &T) -> bool {
72 let mut found = false;
73 while self.time() == Some(time) {
74 found = true;
75 let (t, _) = self.history.pop().unwrap();
76 self.buffer.push(t);
77 }
78 found
79 }
80
81 pub fn advance_buffer_by(&mut self, meet: &T) {
84 for time in self.buffer.iter_mut() {
85 *time = time.join(meet);
86 }
87 self.buffer.sort();
88 self.buffer.dedup();
89 }
90
91 pub fn buffer(&self) -> &[T] {
93 &self.buffer
94 }
95}
96
97pub fn bilinear_wave<V, T, R0, R1, RO>(
107 h0: &mut ValueHistory<V, T, R0>,
108 h1: &mut ValueHistory<V, T, R1>,
109 mut emit: impl FnMut(V, V, T, RO),
110) where
111 V: Copy + Ord,
112 T: Ord + Clone + Lattice,
113 R0: Semigroup + Multiply<R1, Output = RO> + Clone,
114 R1: Semigroup + Clone,
115{
116 while h0.time().is_some() && h1.time().is_some() {
117 if h0.time().unwrap() < h1.time().unwrap() {
118 h1.advance_buffer_by(h0.meet().unwrap());
119 let (v0, t0, d0) = h0.edit().unwrap();
120 for ((v1, t1), d1) in h1.buffer() {
121 emit(v0, *v1, t0.join(t1), d0.clone().multiply(d1));
122 }
123 h0.step();
124 } else {
125 h0.advance_buffer_by(h1.meet().unwrap());
126 let (v1, t1, d1) = h1.edit().unwrap();
127 for ((v0, t0), d0) in h0.buffer() {
128 emit(*v0, v1, t0.join(t1), d0.clone().multiply(d1));
129 }
130 h1.step();
131 }
132 }
133 while h0.time().is_some() {
134 h1.advance_buffer_by(h0.meet().unwrap());
135 let (v0, t0, d0) = h0.edit().unwrap();
136 for ((v1, t1), d1) in h1.buffer() {
137 emit(v0, *v1, t0.join(t1), d0.clone().multiply(d1));
138 }
139 h0.step();
140 }
141 while h1.time().is_some() {
142 h0.advance_buffer_by(h1.meet().unwrap());
143 let (v1, t1, d1) = h1.edit().unwrap();
144 for ((v0, t0), d0) in h0.buffer() {
145 emit(*v0, v1, t0.join(t1), d0.clone().multiply(d1));
146 }
147 h1.step();
148 }
149}
150
151pub fn tile_descriptions<T: Timestamp + Lattice>(
159 lower: &Antichain<T>,
160 upper: &Antichain<T>,
161 held: &[T],
162) -> (Vec<Description<T>>, Vec<T>, Vec<Option<usize>>) {
163 let mut tile_descs: Vec<Description<T>> = Vec::new();
164 let mut tile_held: Vec<T> = Vec::new();
165 let mut tile_of: Vec<Option<usize>> = vec![None; held.len()];
166 let mut out_lower = lower.clone();
167 for index in 0..held.len() {
168 let mut out_upper = upper.clone();
169 for t in &held[index + 1..] {
170 out_upper.insert(t.clone());
171 }
172 if out_upper != out_lower {
173 tile_of[index] = Some(tile_descs.len());
174 tile_descs.push(Description::new(out_lower.clone(), out_upper.clone(), Antichain::from_elem(T::minimum())));
175 tile_held.push(held[index].clone());
176 out_lower = out_upper;
177 }
178 }
179 (tile_descs, tile_held, tile_of)
180}
181
182pub struct KeyView<'a, T, RIn> {
186 pub p_in: &'a [((u64, u64), T, RIn)],
188 pub i0: usize,
190 pub i1: usize,
192 pub pending: &'a [T],
194}
195
196fn update_meet<T: Lattice + Clone>(meet: &mut Option<T>, other: Option<&T>) {
198 if let Some(time) = other {
199 match meet.as_mut() {
200 Some(m) => m.meet_assign(time),
201 None => *meet = Some(time.clone()),
202 }
203 }
204}
205
206pub struct DiscoverScratch<T, RIn> {
209 batch_replay: TimeHistory<T>,
210 input_replay: ValueHistory<u64, T, RIn>,
211 output_replay: TimeHistory<T>,
212 synth: Vec<T>,
213 times_current: Vec<T>,
214 temporary: Vec<T>,
215 meets: Vec<T>,
216}
217
218impl<T: Timestamp + Lattice, RIn: Semigroup + Clone> DiscoverScratch<T, RIn> {
219 pub fn new() -> Self {
221 DiscoverScratch {
222 batch_replay: TimeHistory::new(),
223 input_replay: ValueHistory::new(),
224 output_replay: TimeHistory::new(),
225 synth: Vec::new(),
226 times_current: Vec::new(),
227 temporary: Vec::new(),
228 meets: Vec::new(),
229 }
230 }
231}
232
233impl<T: Timestamp + Lattice, RIn: Semigroup + Clone> Default for DiscoverScratch<T, RIn> {
234 fn default() -> Self { Self::new() }
235}
236
237#[allow(clippy::too_many_arguments)]
249pub fn discover_times<T, RIn>(
250 key: KeyView<'_, T, RIn>,
251 seed_times: impl Iterator<Item = T>,
252 out_times: impl Iterator<Item = T>,
253 upper: &Antichain<T>,
254 scratch: &mut DiscoverScratch<T, RIn>,
255 moments: &mut Vec<T>,
256 pended: &mut Vec<T>,
257) where
258 T: Timestamp + Lattice,
259 RIn: Semigroup + Clone,
260{
261 let DiscoverScratch { batch_replay, input_replay, output_replay, synth, times_current, temporary, meets } = scratch;
264 synth.clear();
265 times_current.clear();
266 temporary.clear();
267
268 batch_replay.load(seed_times, None);
269
270 meets.clear();
271 meets.extend(key.pending.iter().cloned());
272 for i in (1..meets.len()).rev() {
273 let m = meets[i].clone();
274 meets[i - 1].meet_assign(&m);
275 }
276
277 let mut meet: Option<T> = None;
278 update_meet(&mut meet, meets.first());
279 update_meet(&mut meet, batch_replay.meet());
280
281 input_replay.load_iter(
284 (key.i0..key.i1).map(|i| (key.p_in[i].0.1, key.p_in[i].1.clone(), key.p_in[i].2.clone())),
285 meet.as_ref(),
286 );
287 output_replay.load(out_times, meet.as_ref());
288
289 let mut times_slice = key.pending;
290 let mut meets_slice = &meets[..];
291
292 while let Some(next_time) = [batch_replay.time(), times_slice.first(), input_replay.time(), output_replay.time(), synth.last()]
293 .into_iter()
294 .flatten()
295 .min()
296 .cloned()
297 {
298 input_replay.step_while_time_is(&next_time);
299 output_replay.step_while_time_is(&next_time);
300 let mut interesting = batch_replay.step_while_time_is(&next_time);
301 if interesting {
302 if let Some(m) = meet.as_ref() {
303 batch_replay.advance_buffer_by(m);
304 }
305 }
306 while synth.last() == Some(&next_time) {
307 times_current.push(synth.pop().expect("nonempty"));
308 interesting = true;
309 }
310 while times_slice.first() == Some(&next_time) {
311 times_current.push(times_slice[0].clone());
312 times_slice = ×_slice[1..];
313 meets_slice = &meets_slice[1..];
314 interesting = true;
315 }
316 interesting = interesting || batch_replay.buffer().iter().any(|t| t.less_equal(&next_time));
317 interesting = interesting || times_current.iter().any(|t| t.less_equal(&next_time));
318
319 if !upper.less_equal(&next_time) {
320 if interesting {
321 if let Some(m) = meet.as_ref() {
324 input_replay.advance_buffer_by(m);
325 }
326 for ((_, t), _) in input_replay.buffer().iter() {
327 if !t.less_equal(&next_time) {
328 temporary.push(next_time.join(t));
329 }
330 }
331 if let Some(m) = meet.as_ref() {
332 output_replay.advance_buffer_by(m);
333 }
334 for t in output_replay.buffer().iter() {
335 if !t.less_equal(&next_time) {
336 temporary.push(next_time.join(t));
337 }
338 }
339 moments.push(next_time.clone());
340 }
341 temporary.extend(batch_replay.buffer().iter().filter(|t| !t.less_equal(&next_time)).map(|t| t.join(&next_time)));
342 temporary.extend(times_current.iter().filter(|t| !t.less_equal(&next_time)).map(|t| t.join(&next_time)));
343 sort_dedup(temporary);
344 let synth_len = synth.len();
345 for time in temporary.drain(..) {
346 if upper.less_equal(&time) {
347 pended.push(time);
348 } else {
349 synth.push(time);
350 }
351 }
352 if synth.len() > synth_len {
353 synth.sort_by(|x, y| y.cmp(x));
354 synth.dedup();
355 }
356 } else if interesting {
357 pended.push(next_time.clone());
358 }
359
360 meet = None;
361 update_meet(&mut meet, batch_replay.meet());
362 update_meet(&mut meet, input_replay.meet());
363 update_meet(&mut meet, output_replay.meet());
364 for t in synth.iter() {
365 update_meet(&mut meet, Some(t));
366 }
367 update_meet(&mut meet, meets_slice.first());
368 if let Some(m) = meet.as_ref() {
369 for t in times_current.iter_mut() {
370 *t = t.join(m);
371 }
372 }
373 sort_dedup(times_current);
374 }
375 sort_dedup(pended);
376}