1mod layoutfmt;
2
3#[doc(hidden)]
7#[derive(Copy, Clone)]
9pub struct Layout(u32);
10
11impl Layout {
12 pub(crate) const CORDER: u32 = 0b01;
13 pub(crate) const FORDER: u32 = 0b10;
14 pub(crate) const CPREFER: u32 = 0b0100;
15 pub(crate) const FPREFER: u32 = 0b1000;
16
17 #[inline(always)]
18 pub(crate) fn is(self, flag: u32) -> bool {
19 self.0 & flag != 0
20 }
21
22 #[inline(always)]
24 pub(crate) fn intersect(self, other: Layout) -> Layout {
25 Layout(self.0 & other.0)
26 }
27
28 #[inline(always)]
30 pub(crate) fn also(self, other: Layout) -> Layout {
31 Layout(self.0 | other.0)
32 }
33
34 #[inline(always)]
35 pub(crate) fn one_dimensional() -> Layout {
36 Layout::c().also(Layout::f())
37 }
38
39 #[inline(always)]
40 pub(crate) fn c() -> Layout {
41 Layout(Layout::CORDER | Layout::CPREFER)
42 }
43
44 #[inline(always)]
45 pub(crate) fn f() -> Layout {
46 Layout(Layout::FORDER | Layout::FPREFER)
47 }
48
49 #[inline(always)]
50 pub(crate) fn cpref() -> Layout {
51 Layout(Layout::CPREFER)
52 }
53
54 #[inline(always)]
55 pub(crate) fn fpref() -> Layout {
56 Layout(Layout::FPREFER)
57 }
58
59 #[inline(always)]
60 pub(crate) fn none() -> Layout {
61 Layout(0)
62 }
63
64 #[inline]
67 pub(crate) fn tendency(self) -> i32 {
68 (self.is(Layout::CORDER) as i32 - self.is(Layout::FORDER) as i32) +
69 (self.is(Layout::CPREFER) as i32 - self.is(Layout::FPREFER) as i32)
70
71 }
72}
73
74
75#[cfg(test)]
76mod tests {
77 use super::*;
78 use crate::imp_prelude::*;
79 use crate::NdProducer;
80
81 type M = Array2<f32>;
82 type M1 = Array1<f32>;
83 type M0 = Array0<f32>;
84
85 macro_rules! assert_layouts {
86 ($mat:expr, $($layout:ident),*) => {{
87 let layout = $mat.view().layout();
88 $(
89 assert!(layout.is(Layout::$layout),
90 "Assertion failed: array {:?} is not layout {}",
91 $mat,
92 stringify!($layout));
93 )*
94 }}
95 }
96
97 macro_rules! assert_not_layouts {
98 ($mat:expr, $($layout:ident),*) => {{
99 let layout = $mat.view().layout();
100 $(
101 assert!(!layout.is(Layout::$layout),
102 "Assertion failed: array {:?} show not have layout {}",
103 $mat,
104 stringify!($layout));
105 )*
106 }}
107 }
108
109 #[test]
110 fn contig_layouts() {
111 let a = M::zeros((5, 5));
112 let b = M::zeros((5, 5).f());
113 let ac = a.view().layout();
114 let af = b.view().layout();
115 assert!(ac.is(Layout::CORDER) && ac.is(Layout::CPREFER));
116 assert!(!ac.is(Layout::FORDER) && !ac.is(Layout::FPREFER));
117 assert!(!af.is(Layout::CORDER) && !af.is(Layout::CPREFER));
118 assert!(af.is(Layout::FORDER) && af.is(Layout::FPREFER));
119 }
120
121 #[test]
122 fn contig_cf_layouts() {
123 let a = M::zeros((5, 1));
124 let b = M::zeros((1, 5).f());
125 assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER);
126 assert_layouts!(b, CORDER, CPREFER, FORDER, FPREFER);
127
128 let a = M1::zeros(5);
129 let b = M1::zeros(5.f());
130 assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER);
131 assert_layouts!(b, CORDER, CPREFER, FORDER, FPREFER);
132
133 let a = M0::zeros(());
134 assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER);
135
136 let a = M::zeros((5, 5));
137 let b = M::zeros((5, 5).f());
138 let arow = a.slice(s![..1, ..]);
139 let bcol = b.slice(s![.., ..1]);
140 assert_layouts!(arow, CORDER, CPREFER, FORDER, FPREFER);
141 assert_layouts!(bcol, CORDER, CPREFER, FORDER, FPREFER);
142
143 let acol = a.slice(s![.., ..1]);
144 let brow = b.slice(s![..1, ..]);
145 assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER);
146 assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER);
147 }
148
149 #[test]
150 fn stride_layouts() {
151 let a = M::zeros((5, 5));
152
153 {
154 let v1 = a.slice(s![1.., ..]).layout();
155 let v2 = a.slice(s![.., 1..]).layout();
156
157 assert!(v1.is(Layout::CORDER) && v1.is(Layout::CPREFER));
158 assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER));
159 assert!(!v2.is(Layout::CORDER) && v2.is(Layout::CPREFER));
160 assert!(!v2.is(Layout::FORDER) && !v2.is(Layout::FPREFER));
161 }
162
163 let b = M::zeros((5, 5).f());
164
165 {
166 let v1 = b.slice(s![1.., ..]).layout();
167 let v2 = b.slice(s![.., 1..]).layout();
168
169 assert!(!v1.is(Layout::CORDER) && !v1.is(Layout::CPREFER));
170 assert!(!v1.is(Layout::FORDER) && v1.is(Layout::FPREFER));
171 assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER));
172 assert!(v2.is(Layout::FORDER) && v2.is(Layout::FPREFER));
173 }
174 }
175
176 #[test]
177 fn no_layouts() {
178 let a = M::zeros((5, 5));
179 let b = M::zeros((5, 5).f());
180
181 let arow = a.slice(s![0..1, ..]);
183 let acol = a.slice(s![.., 0..1]);
184 let brow = b.slice(s![0..1, ..]);
185 let bcol = b.slice(s![.., 0..1]);
186 assert_layouts!(arow, CORDER, FORDER);
187 assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER);
188 assert_layouts!(bcol, CORDER, FORDER);
189 assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER);
190
191 for &axis in &[Axis(0), Axis(1)] {
193 let arow = a.slice(s![0, ..]).insert_axis(axis);
194 let acol = a.slice(s![.., 0]).insert_axis(axis);
195 let brow = b.slice(s![0, ..]).insert_axis(axis);
196 let bcol = b.slice(s![.., 0]).insert_axis(axis);
197 assert_layouts!(arow, CORDER, FORDER);
198 assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER);
199 assert_layouts!(bcol, CORDER, FORDER);
200 assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER);
201 }
202 }
203
204 #[test]
205 fn skip_layouts() {
206 let a = M::zeros((5, 5));
207 {
208 let v1 = a.slice(s![..;2, ..]).layout();
209 let v2 = a.slice(s![.., ..;2]).layout();
210
211 assert!(!v1.is(Layout::CORDER) && v1.is(Layout::CPREFER));
212 assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER));
213 assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER));
214 assert!(!v2.is(Layout::FORDER) && !v2.is(Layout::FPREFER));
215 }
216
217 let b = M::zeros((5, 5).f());
218 {
219 let v1 = b.slice(s![..;2, ..]).layout();
220 let v2 = b.slice(s![.., ..;2]).layout();
221
222 assert!(!v1.is(Layout::CORDER) && !v1.is(Layout::CPREFER));
223 assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER));
224 assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER));
225 assert!(!v2.is(Layout::FORDER) && v2.is(Layout::FPREFER));
226 }
227 }
228}