orx_v/cardinality/
d3_variable.rs

1use super::{
2    card::{child_fun_unchecked, Card},
3    panic_d1, panic_d2,
4};
5use crate::{
6    cardinality::d2_variable::VariableCardD2, CardD1, Dim, FunVec, IdxLeqD2, NVec, D3, V2,
7};
8
9/// A variable cardinality of dimension `D3` vectors such that every child
10/// in every lower dimension can have different numbers of children.
11#[derive(Clone, Copy)]
12pub struct VariableCardD3<V: V2<usize>>(pub(super) V);
13
14impl<V: V2<usize>> From<V> for VariableCardD3<V> {
15    fn from(value: V) -> Self {
16        Self(value)
17    }
18}
19
20impl<V: V2<usize>> Card<D3> for VariableCardD3<V> {
21    fn is_rectangular(&self) -> bool {
22        let n = self.0.card([]);
23        let m = match n {
24            0 => 0,
25            _ => self.0.card([0]),
26        };
27        let p = match m {
28            0 => 0,
29            _ => self.0.at([0, 0]),
30        };
31
32        for i in 0..n {
33            if self.0.card([i]) != m {
34                return false;
35            }
36
37            for j in 0..m {
38                if self.0.at([i, j]) != p {
39                    return false;
40                }
41            }
42        }
43
44        true
45    }
46
47    fn cardinality_of(&self, idx: impl Into<<D3 as Dim>::CardIdx>) -> usize {
48        match idx.into() {
49            IdxLeqD2::IdxD0([]) => self.0.card([]),
50            IdxLeqD2::IdxD1([i]) => match i < self.0.card([]) {
51                true => self.0.card([i]),
52                false => panic_d1(i, self.0.card([])),
53            },
54            IdxLeqD2::IdxD2([i, j]) => match i < self.0.card([]) {
55                true => match j < self.0.card([i]) {
56                    true => self.0.at([i, j]),
57                    false => panic_d2(i, j, self.0.card([i])),
58                },
59                false => panic_d1(i, self.0.card([])),
60            },
61        }
62    }
63
64    fn child_card(&self, i: usize) -> impl Card<<D3 as Dim>::PrevDim> {
65        match i < self.0.card([]) {
66            true => {
67                let card_idx0 = self.0.card([i]);
68                let card_idx1 = FunVec::new(move |[j]| self.0.at([i, j]), CardD1::from(card_idx0));
69                VariableCardD2(card_idx1)
70            }
71            false => panic_d1(i, self.0.card([])),
72        }
73    }
74
75    fn child_fun<T, F>(&self, i: usize, fun: F) -> impl Fn(<<D3 as Dim>::PrevDim as Dim>::Idx) -> T
76    where
77        F: Fn(<D3 as Dim>::Idx) -> T,
78    {
79        match i < self.0.card([]) {
80            true => child_fun_unchecked::<D3, _, _>(i, fun),
81            false => panic_d1(i, self.0.card([])),
82        }
83    }
84
85    fn vec_all<'a, T, N>(&'a self, vec: &'a N) -> impl Iterator<Item = T>
86    where
87        N: NVec<D3, T> + 'a,
88    {
89        (0..self.cardinality_of([])).flat_map(move |i| {
90            (0..self.cardinality_of([i]))
91                .flat_map(move |j| (0..self.cardinality_of([i, j])).map(move |k| vec.at([i, j, k])))
92        })
93    }
94
95    fn vec_enumerate_all<'a, T, N>(
96        &'a self,
97        vec: &'a N,
98    ) -> impl Iterator<Item = (<D3 as Dim>::Idx, T)>
99    where
100        N: NVec<D3, T> + 'a,
101    {
102        (0..self.cardinality_of([])).flat_map(move |i| {
103            (0..self.cardinality_of([i])).flat_map(move |j| {
104                (0..self.cardinality_of([i, j])).map(move |k| ([i, j, k], vec.at([i, j, k])))
105            })
106        })
107    }
108}