standing_relations/core/op/
triangles.rs

1mod 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}