1use std::cell::RefCell;
7use std::rc::Rc;
8
9use timely::progress::Timestamp;
10
11use crate::difference::{Multiply, Semigroup};
12use crate::lattice::Lattice;
13use super::{KeyPosition, ProxyBridge};
14use crate::operators::join::{Fresh, JoinTactic};
15use crate::operators::history::ValueHistory;
16
17use super::history::IdHistory;
18
19pub trait ProxyJoinBackend<T, B0, B1> {
24 type Key: Copy + Ord;
26 type V0: Copy + Ord;
28 type V1: Copy + Ord;
30 type R0: Semigroup + Multiply<Self::R1, Output = Self::ROut>;
32 type R1: Semigroup;
34 type ROut: Semigroup;
36 type Output;
38
39 fn advance(
47 &mut self,
48 instance: &JoinInstance<T, B0, B1>,
49 from: &mut KeyPosition<Self::Key>,
50 bridge0: &mut ProxyBridge<T, Self::R0, Self::Key, Self::V0>,
51 bridge1: &mut ProxyBridge<T, Self::R1, Self::Key, Self::V1>,
52 );
53
54 fn cross(
59 &mut self,
60 instance: &JoinInstance<T, B0, B1>,
61 matches: &mut JoinMatches<T, Self::ROut, Self::Key, Self::V0, Self::V1>,
62 output: &mut Vec<Self::Output>,
63 );
64}
65
66pub struct JoinInstance<T, B0, B1> {
68 pub batches0: Vec<B0>,
70 pub batches1: Vec<B1>,
72 pub lower: T,
76}
77
78pub struct JoinMatches<T, R, K = u64, V0 = u64, V1 = u64> {
82 pub ids: Vec<(K, (V0, V1))>,
84 pub times: Vec<T>,
86 pub diffs: Vec<R>,
88}
89
90impl<T, R, K, V0, V1> Default for JoinMatches<T, R, K, V0, V1> {
91 fn default() -> Self { Self { ids: vec![], times: vec![], diffs: vec![] } }
92}
93
94pub struct ProxyJoinTactic<B0, B1, Bk> {
98 backend: Rc<RefCell<Bk>>,
99 _marker: std::marker::PhantomData<(B0, B1)>,
100}
101
102impl<B0, B1, Bk> ProxyJoinTactic<B0, B1, Bk> {
103 pub fn new(backend: Bk) -> Self {
105 ProxyJoinTactic { backend: Rc::new(RefCell::new(backend)), _marker: std::marker::PhantomData }
106 }
107}
108
109impl<T, B0, B1, Bk> JoinTactic<T, B0, B1, Bk::Output> for ProxyJoinTactic<B0, B1, Bk>
110where
111 T: Timestamp + Lattice + 'static,
112 B0: 'static,
113 B1: 'static,
114 Bk: ProxyJoinBackend<T, B0, B1> + 'static,
115 Bk::Output: 'static,
116 Bk::Key: 'static,
117 Bk::V0: 'static,
118 Bk::V1: 'static,
119{
120 fn prep(&mut self, input0: Vec<B0>, input1: Vec<B1>, _fresh: Fresh, meet: T) -> Box<dyn Iterator<Item = Bk::Output>> {
121 Box::new(ProxyJoinIter {
122 backend: Rc::clone(&self.backend),
123 instance: JoinInstance { batches0: input0, batches1: input1, lower: meet },
124 from: KeyPosition::Start,
125 p0: Vec::new(),
126 p1: Vec::new(),
127 h0: IdHistory::new(),
128 h1: IdHistory::new(),
129 matches: JoinMatches::default(),
130 ready: Vec::new(),
131 })
132 }
133}
134
135struct ProxyJoinIter<T, B0, B1, Bk>
141where
142 Bk: ProxyJoinBackend<T, B0, B1>,
143{
144 backend: Rc<RefCell<Bk>>,
146 instance: JoinInstance<T, B0, B1>,
148 from: KeyPosition<Bk::Key>,
150 p0: ProxyBridge<T, Bk::R0, Bk::Key, Bk::V0>,
152 p1: ProxyBridge<T, Bk::R1, Bk::Key, Bk::V1>,
153 h0: IdHistory<T, Bk::R0, Bk::V0>,
155 h1: IdHistory<T, Bk::R1, Bk::V1>,
156 matches: JoinMatches<T, Bk::ROut, Bk::Key, Bk::V0, Bk::V1>,
158 ready: Vec<Bk::Output>,
160}
161
162impl<T, B0, B1, Bk> Iterator for ProxyJoinIter<T, B0, B1, Bk>
163where
164 T: Timestamp + Lattice,
165 Bk: ProxyJoinBackend<T, B0, B1>,
166{
167 type Item = Bk::Output;
168
169 fn next(&mut self) -> Option<Bk::Output> {
171 while self.ready.is_empty() && self.from != KeyPosition::End {
172 self.refill();
173 self.work();
174 if !self.matches.ids.is_empty() { self.cross(); }
175 }
176 self.ready.pop()
177 }
178}
179
180impl<T, B0, B1, Bk> ProxyJoinIter<T, B0, B1, Bk>
181where
182 T: Timestamp + Lattice,
183 Bk: ProxyJoinBackend<T, B0, B1>,
184{
185 fn refill(&mut self) {
187 self.p0.clear();
188 self.p1.clear();
189 let before = self.from;
190 self.backend.borrow_mut().advance(&self.instance, &mut self.from, &mut self.p0, &mut self.p1);
191 debug_assert!(
193 self.from > before,
194 "advance must either strictly increase `from` or report the iteration complete",
195 );
196 super::debug_assert_sorted_bridge(&self.p0, "advance (bridge0)");
197 super::debug_assert_sorted_bridge(&self.p1, "advance (bridge1)");
198 debug_assert!(
201 {
202 let mut keys = self.p0.iter().map(|r| r.0.0).chain(self.p1.iter().map(|r| r.0.0));
203 keys.all(|k| before <= KeyPosition::At(k) && KeyPosition::At(k) < self.from)
204 },
205 "advance must report a key entirely within the block that first mentions it",
206 );
207 }
208
209 fn work(&mut self) {
211 let (p0, p1) = (&self.p0, &self.p1);
213 let (h0, h1) = (&mut self.h0, &mut self.h1);
214
215 let (mut i, mut j) = (0usize, 0usize);
216 while i < p0.len() && j < p1.len() {
217 let ki = p0[i].0.0;
218 debug_assert!(ki == p1[j].0.0, "advance must report common keys");
219 let mut e0 = i;
220 while e0 < p0.len() && p0[e0].0.0 == ki { e0 += 1; }
221 let mut e1 = j;
222 while e1 < p1.len() && p1[e1].0.0 == ki { e1 += 1; }
223 join_key(ki, p0, i..e0, p1, j..e1, h0, h1, &mut self.matches);
224 i = e0;
225 j = e1;
226 }
227 debug_assert!(i == p0.len() && j == p1.len(), "both bridges must drain together");
228 }
229
230 fn cross(&mut self) {
232 self.backend.borrow_mut().cross(
233 &self.instance,
234 &mut self.matches,
235 &mut self.ready,
236 );
237 self.ready.reverse();
239 self.matches.ids.clear();
240 self.matches.times.clear();
241 self.matches.diffs.clear();
242 }
243}
244
245fn join_key<T, R0, R1, RO, K: Copy + Ord, V0: Copy + Ord, V1: Copy + Ord>(
251 kh: K,
252 p0: &ProxyBridge<T, R0, K, V0>,
253 r0: std::ops::Range<usize>,
254 p1: &ProxyBridge<T, R1, K, V1>,
255 r1: std::ops::Range<usize>,
256 h0: &mut IdHistory<T, R0, V0>,
257 h1: &mut IdHistory<T, R1, V1>,
258 matches: &mut JoinMatches<T, RO, K, V0, V1>,
259) where
260 T: Lattice + Timestamp,
261 R0: Semigroup + Multiply<R1, Output = RO> + Clone,
262 R1: Semigroup + Clone,
263{
264 if r0.len() < 16 || r1.len() < 16 {
265 for a in r0 {
266 for b in r1.clone() {
267 matches.ids.push((kh, (p0[a].0.1, p1[b].0.1)));
268 let mut time = p0[a].1.clone();
269 time.join_assign(&p1[b].1);
270 matches.times.push(time);
271 matches.diffs.push(p0[a].2.clone().multiply(&p1[b].2));
272 }
273 }
274 }
275 else {
276 h0.load_iter(r0.map(|i| (p0[i].0.1, p0[i].1.clone(), p0[i].2.clone())), None);
277 h1.load_iter(r1.map(|i| (p1[i].0.1, p1[i].1.clone(), p1[i].2.clone())), None);
278 bilinear_wave(h0, h1, |v0, v1, t, d| {
279 matches.ids.push((kh, (v0, v1)));
280 matches.times.push(t);
281 matches.diffs.push(d);
282 });
283 }
284}
285
286fn bilinear_wave<V0, V1, T, R0, R1, RO>(
296 h0: &mut ValueHistory<V0, T, R0>,
297 h1: &mut ValueHistory<V1, T, R1>,
298 mut emit: impl FnMut(V0, V1, T, RO),
299) where
300 V0: Copy + Ord,
301 V1: Copy + Ord,
302 T: Ord + Clone + Lattice,
303 R0: Semigroup + Multiply<R1, Output = RO> + Clone,
304 R1: Semigroup + Clone,
305{
306 while h0.time().is_some() && h1.time().is_some() {
307 if h0.time().unwrap() < h1.time().unwrap() {
308 h1.advance_buffer_by(h0.meet().unwrap());
309 let (v0, t0, d0) = h0.edit().unwrap();
310 for ((v1, t1), d1) in h1.buffer() {
311 let mut time = t0.clone();
312 time.join_assign(t1);
313 emit(v0, *v1, time, d0.clone().multiply(d1));
314 }
315 h0.step();
316 } else {
317 h0.advance_buffer_by(h1.meet().unwrap());
318 let (v1, t1, d1) = h1.edit().unwrap();
319 for ((v0, t0), d0) in h0.buffer() {
320 let mut time = t0.clone();
321 time.join_assign(t1);
322 emit(*v0, v1, time, d0.clone().multiply(d1));
323 }
324 h1.step();
325 }
326 }
327 while h0.time().is_some() {
328 h1.advance_buffer_by(h0.meet().unwrap());
329 let (v0, t0, d0) = h0.edit().unwrap();
330 for ((v1, t1), d1) in h1.buffer() {
331 let mut time = t0.clone();
332 time.join_assign(t1);
333 emit(v0, *v1, time, d0.clone().multiply(d1));
334 }
335 h0.step();
336 }
337 while h1.time().is_some() {
338 h0.advance_buffer_by(h1.meet().unwrap());
339 let (v1, t1, d1) = h1.edit().unwrap();
340 for ((v0, t0), d0) in h0.buffer() {
341 let mut time = t0.clone();
342 time.join_assign(t1);
343 emit(*v0, v1, time, d0.clone().multiply(d1));
344 }
345 h1.step();
346 }
347}