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