1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
mod bimap;
mod intersection;
use std::hash::Hash;
use crate::core::{relation::RelationInner, CountMap, Op, Op_, Relation};
use self::{bimap::BiMap, intersection::intersection};
pub struct Triangles<X, Y, Z, C1: Op<D = (X, Y)>, C2: Op<D = (X, Z)>, C3: Op<D = (Y, Z)>> {
c1: RelationInner<C1>,
c2: RelationInner<C2>,
c3: RelationInner<C3>,
mapxy: BiMap<X, Y>,
mapxz: BiMap<X, Z>,
mapyz: BiMap<Y, Z>,
}
impl<
X: Eq + Hash + Clone,
Y: Eq + Hash + Clone,
Z: Eq + Hash + Clone,
C1: Op<D = (X, Y)>,
C2: Op<D = (X, Z)>,
C3: Op<D = (Y, Z)>,
> Op_ for Triangles<X, Y, Z, C1, C2, C3>
{
type T = ((X, Y, Z), isize);
fn foreach<'a>(&'a mut self, mut continuation: impl FnMut(Self::T) + 'a) {
let mapxy = &mut self.mapxy;
let mapxz = &mut self.mapxz;
let mapyz = &mut self.mapyz;
self.c1.foreach(|((x, y), count)| {
let xzs = mapxz.get_forward(&x);
let yzs = mapyz.get_forward(&y);
for (z, lcount, rcount) in intersection(&xzs, &yzs) {
continuation(((x.clone(), y.clone(), z.clone()), count * lcount * rcount))
}
mapxy.add((x, y), count);
});
self.c2.foreach(|((x, z), count)| {
let xys = mapxy.get_forward(&x);
let zys = mapyz.get_backward(&z);
for (y, lcount, rcount) in intersection(&xys, &zys) {
continuation(((x.clone(), y.clone(), z.clone()), count * lcount * rcount))
}
mapxz.add((x, z), count);
});
self.c3.foreach(|((y, z), count)| {
let yxs = mapxy.get_backward(&y);
let zxs = mapxz.get_backward(&z);
for (x, lcount, rcount) in intersection(&yxs, &zxs) {
continuation(((x.clone(), y.clone(), z.clone()), count * lcount * rcount))
}
mapyz.add((y, z), count);
});
}
fn get_type_name() -> &'static str {
"triangles"
}
}
impl<X: Clone + Eq + Hash, Y: Clone + Eq + Hash, C1: Op<D = (X, Y)>> Relation<C1> {
pub fn triangles<Z: Clone + Eq + Hash, C2: Op<D = (X, Z)>, C3: Op<D = (Y, Z)>>(
self,
rel2: Relation<C2>,
rel3: Relation<C3>,
) -> Relation<Triangles<X, Y, Z, C1, C2, C3>> {
assert_eq!(
self.context_tracker, rel2.context_tracker,
"Context mismatch"
);
assert_eq!(
self.context_tracker, rel3.context_tracker,
"Context mismatch"
);
self.context_tracker.add_relation(
self.dirty.or(rel2.dirty).or(rel3.dirty),
Triangles {
c1: self.inner,
c2: rel2.inner,
c3: rel3.inner,
mapxy: BiMap::new(),
mapxz: BiMap::new(),
mapyz: BiMap::new(),
},
vec![
self.tracking_index,
rel2.tracking_index,
rel3.tracking_index,
],
)
}
}