opensrdk_linear_algebra/macros/
stack.rs

1use crate::{macros::sub_matrix::SubMatrix, number::Number, Matrix};
2
3#[macro_export]
4macro_rules! stack_v {
5    ($e: expr) => {{
6        use $crate::macros::stack::Stack;
7        Stack::Vertical($e)
8    }};
9}
10
11#[macro_export]
12macro_rules! stack_h {
13    ($e: expr) => {{
14        use $crate::macros::stack::Stack;
15        Stack::Horizontal($e)
16    }};
17}
18
19#[macro_export]
20macro_rules! stack {
21  ($e: expr) => {
22    {
23      use $crate::macros::stack::Stack;
24      Stack::Only(Box::new($e))
25    }
26  };
27  ($($e: expr),+) => {
28    {
29      use $crate::stack_h;
30      stack_h!(vec![$(stack!($e)),+])
31    }
32  };
33  ($($($e: expr),+);+) => {
34    {
35      use $crate::stack_v;
36      stack_v!(vec![$(stack!($($e),+)),+])
37    }
38  };
39}
40
41pub enum Stack<'a, T: Number> {
42    Only(Box<dyn SubMatrix<T> + 'a>),
43    Horizontal(Vec<Stack<'a, T>>),
44    Vertical(Vec<Stack<'a, T>>),
45}
46
47impl<'a, T> Stack<'a, T>
48where
49    T: Number,
50{
51    pub fn matrix(&self) -> Matrix<T> {
52        let size = self.size();
53        let mut matrix = Matrix::<T>::new(size.0, size.1);
54        self.transcript(&mut matrix, 0, 0);
55
56        matrix
57    }
58
59    fn size(&self) -> (usize, usize) {
60        match self {
61            Stack::Only(sub_matrix) => sub_matrix.size(),
62            Stack::Horizontal(vec) => {
63                let mut rows = 0usize;
64                let mut columns = 0usize;
65
66                for e in vec.iter() {
67                    let size = e.size();
68
69                    if rows == 0 {
70                        rows = size.0;
71                    } else if rows != size.0 {
72                        panic!("Dimension mismatch.")
73                    }
74
75                    columns += size.1;
76                }
77
78                (rows, columns)
79            }
80            Stack::Vertical(vec) => {
81                let mut rows = 0usize;
82                let mut columns = 0usize;
83
84                for e in vec.iter() {
85                    let size = e.size();
86
87                    if columns == 0 {
88                        columns = size.1;
89                    } else if columns != size.1 {
90                        panic!("Dimension mismatch.")
91                    }
92
93                    rows += size.0;
94                }
95
96                (rows, columns)
97            }
98        }
99    }
100
101    fn transcript(&self, matrix: &mut Matrix<T>, i: usize, j: usize) -> (usize, usize) {
102        match self {
103            Stack::Only(sub_matrix) => {
104                let size = sub_matrix.size();
105
106                for l in 0..size.1 {
107                    for k in 0..size.0 {
108                        matrix[j + l][i + k] = sub_matrix.index(k, l);
109                    }
110                }
111
112                size
113            }
114            Stack::Horizontal(vec) => {
115                let mut size = (0usize, 0usize);
116
117                for e in vec.iter() {
118                    let s = e.transcript(matrix, i, j + size.1);
119                    size.0 = s.0;
120                    size.1 += s.1;
121                }
122
123                size
124            }
125            Stack::Vertical(vec) => {
126                let mut size = (0usize, 0usize);
127
128                for e in vec.iter() {
129                    let s = e.transcript(matrix, i + size.0, j);
130                    size.0 += s.0;
131                    size.1 = s.1;
132                }
133
134                size
135            }
136        }
137    }
138}