/rust/registry/src/index.crates.io-1949cf8c6b5b557f/ndarray-0.16.1/src/layout/mod.rs
Line | Count | Source |
1 | | mod layoutfmt; |
2 | | |
3 | | // Layout it a bitset used for internal layout description of |
4 | | // arrays, producers and sets of producers. |
5 | | // The type is public but users don't interact with it. |
6 | | #[doc(hidden)] |
7 | | /// Memory layout description |
8 | | #[derive(Copy, Clone)] |
9 | | pub struct Layout(u32); |
10 | | |
11 | | impl Layout |
12 | | { |
13 | | pub(crate) const CORDER: u32 = 0b01; |
14 | | pub(crate) const FORDER: u32 = 0b10; |
15 | | pub(crate) const CPREFER: u32 = 0b0100; |
16 | | pub(crate) const FPREFER: u32 = 0b1000; |
17 | | |
18 | | #[inline(always)] |
19 | 0 | pub(crate) fn is(self, flag: u32) -> bool |
20 | | { |
21 | 0 | self.0 & flag != 0 |
22 | 0 | } |
23 | | |
24 | | /// Return layout common to both inputs |
25 | | #[inline(always)] |
26 | 0 | pub(crate) fn intersect(self, other: Layout) -> Layout |
27 | | { |
28 | 0 | Layout(self.0 & other.0) |
29 | 0 | } |
30 | | |
31 | | /// Return a layout that simultaneously "is" what both of the inputs are |
32 | | #[inline(always)] |
33 | 0 | pub(crate) fn also(self, other: Layout) -> Layout |
34 | | { |
35 | 0 | Layout(self.0 | other.0) |
36 | 0 | } |
37 | | |
38 | | #[inline(always)] |
39 | 0 | pub(crate) fn one_dimensional() -> Layout |
40 | | { |
41 | 0 | Layout::c().also(Layout::f()) |
42 | 0 | } |
43 | | |
44 | | #[inline(always)] |
45 | 0 | pub(crate) fn c() -> Layout |
46 | | { |
47 | 0 | Layout(Layout::CORDER | Layout::CPREFER) |
48 | 0 | } |
49 | | |
50 | | #[inline(always)] |
51 | 0 | pub(crate) fn f() -> Layout |
52 | | { |
53 | 0 | Layout(Layout::FORDER | Layout::FPREFER) |
54 | 0 | } |
55 | | |
56 | | #[inline(always)] |
57 | 0 | pub(crate) fn cpref() -> Layout |
58 | | { |
59 | 0 | Layout(Layout::CPREFER) |
60 | 0 | } |
61 | | |
62 | | #[inline(always)] |
63 | 0 | pub(crate) fn fpref() -> Layout |
64 | | { |
65 | 0 | Layout(Layout::FPREFER) |
66 | 0 | } |
67 | | |
68 | | #[inline(always)] |
69 | 0 | pub(crate) fn none() -> Layout |
70 | | { |
71 | 0 | Layout(0) |
72 | 0 | } |
73 | | |
74 | | /// A simple "score" method which scores positive for preferring C-order, negative for F-order |
75 | | /// Subject to change when we can describe other layouts |
76 | | #[inline] |
77 | 0 | pub(crate) fn tendency(self) -> i32 |
78 | | { |
79 | 0 | (self.is(Layout::CORDER) as i32 - self.is(Layout::FORDER) as i32) |
80 | 0 | + (self.is(Layout::CPREFER) as i32 - self.is(Layout::FPREFER) as i32) |
81 | 0 | } Unexecuted instantiation: <ndarray::layout::Layout>::tendency Unexecuted instantiation: <ndarray::layout::Layout>::tendency |
82 | | } |
83 | | |
84 | | #[cfg(test)] |
85 | | mod tests |
86 | | { |
87 | | use super::*; |
88 | | use crate::imp_prelude::*; |
89 | | use crate::NdProducer; |
90 | | |
91 | | type M = Array2<f32>; |
92 | | type M1 = Array1<f32>; |
93 | | type M0 = Array0<f32>; |
94 | | |
95 | | macro_rules! assert_layouts { |
96 | | ($mat:expr, $($layout:ident),*) => {{ |
97 | | let layout = $mat.view().layout(); |
98 | | $( |
99 | | assert!(layout.is(Layout::$layout), |
100 | | "Assertion failed: array {:?} is not layout {}", |
101 | | $mat, |
102 | | stringify!($layout)); |
103 | | )* |
104 | | }}; |
105 | | } |
106 | | |
107 | | macro_rules! assert_not_layouts { |
108 | | ($mat:expr, $($layout:ident),*) => {{ |
109 | | let layout = $mat.view().layout(); |
110 | | $( |
111 | | assert!(!layout.is(Layout::$layout), |
112 | | "Assertion failed: array {:?} show not have layout {}", |
113 | | $mat, |
114 | | stringify!($layout)); |
115 | | )* |
116 | | }}; |
117 | | } |
118 | | |
119 | | #[test] |
120 | | fn contig_layouts() |
121 | | { |
122 | | let a = M::zeros((5, 5)); |
123 | | let b = M::zeros((5, 5).f()); |
124 | | let ac = a.view().layout(); |
125 | | let af = b.view().layout(); |
126 | | assert!(ac.is(Layout::CORDER) && ac.is(Layout::CPREFER)); |
127 | | assert!(!ac.is(Layout::FORDER) && !ac.is(Layout::FPREFER)); |
128 | | assert!(!af.is(Layout::CORDER) && !af.is(Layout::CPREFER)); |
129 | | assert!(af.is(Layout::FORDER) && af.is(Layout::FPREFER)); |
130 | | } |
131 | | |
132 | | #[test] |
133 | | fn contig_cf_layouts() |
134 | | { |
135 | | let a = M::zeros((5, 1)); |
136 | | let b = M::zeros((1, 5).f()); |
137 | | assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER); |
138 | | assert_layouts!(b, CORDER, CPREFER, FORDER, FPREFER); |
139 | | |
140 | | let a = M1::zeros(5); |
141 | | let b = M1::zeros(5.f()); |
142 | | assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER); |
143 | | assert_layouts!(b, CORDER, CPREFER, FORDER, FPREFER); |
144 | | |
145 | | let a = M0::zeros(()); |
146 | | assert_layouts!(a, CORDER, CPREFER, FORDER, FPREFER); |
147 | | |
148 | | let a = M::zeros((5, 5)); |
149 | | let b = M::zeros((5, 5).f()); |
150 | | let arow = a.slice(s![..1, ..]); |
151 | | let bcol = b.slice(s![.., ..1]); |
152 | | assert_layouts!(arow, CORDER, CPREFER, FORDER, FPREFER); |
153 | | assert_layouts!(bcol, CORDER, CPREFER, FORDER, FPREFER); |
154 | | |
155 | | let acol = a.slice(s![.., ..1]); |
156 | | let brow = b.slice(s![..1, ..]); |
157 | | assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER); |
158 | | assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER); |
159 | | } |
160 | | |
161 | | #[test] |
162 | | fn stride_layouts() |
163 | | { |
164 | | let a = M::zeros((5, 5)); |
165 | | |
166 | | { |
167 | | let v1 = a.slice(s![1.., ..]).layout(); |
168 | | let v2 = a.slice(s![.., 1..]).layout(); |
169 | | |
170 | | assert!(v1.is(Layout::CORDER) && v1.is(Layout::CPREFER)); |
171 | | assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER)); |
172 | | assert!(!v2.is(Layout::CORDER) && v2.is(Layout::CPREFER)); |
173 | | assert!(!v2.is(Layout::FORDER) && !v2.is(Layout::FPREFER)); |
174 | | } |
175 | | |
176 | | let b = M::zeros((5, 5).f()); |
177 | | |
178 | | { |
179 | | let v1 = b.slice(s![1.., ..]).layout(); |
180 | | let v2 = b.slice(s![.., 1..]).layout(); |
181 | | |
182 | | assert!(!v1.is(Layout::CORDER) && !v1.is(Layout::CPREFER)); |
183 | | assert!(!v1.is(Layout::FORDER) && v1.is(Layout::FPREFER)); |
184 | | assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER)); |
185 | | assert!(v2.is(Layout::FORDER) && v2.is(Layout::FPREFER)); |
186 | | } |
187 | | } |
188 | | |
189 | | #[test] |
190 | | fn no_layouts() |
191 | | { |
192 | | let a = M::zeros((5, 5)); |
193 | | let b = M::zeros((5, 5).f()); |
194 | | |
195 | | // 2D row/column matrixes |
196 | | let arow = a.slice(s![0..1, ..]); |
197 | | let acol = a.slice(s![.., 0..1]); |
198 | | let brow = b.slice(s![0..1, ..]); |
199 | | let bcol = b.slice(s![.., 0..1]); |
200 | | assert_layouts!(arow, CORDER, FORDER); |
201 | | assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER); |
202 | | assert_layouts!(bcol, CORDER, FORDER); |
203 | | assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER); |
204 | | |
205 | | // 2D row/column matrixes - now made with insert axis |
206 | | for &axis in &[Axis(0), Axis(1)] { |
207 | | let arow = a.slice(s![0, ..]).insert_axis(axis); |
208 | | let acol = a.slice(s![.., 0]).insert_axis(axis); |
209 | | let brow = b.slice(s![0, ..]).insert_axis(axis); |
210 | | let bcol = b.slice(s![.., 0]).insert_axis(axis); |
211 | | assert_layouts!(arow, CORDER, FORDER); |
212 | | assert_not_layouts!(acol, CORDER, CPREFER, FORDER, FPREFER); |
213 | | assert_layouts!(bcol, CORDER, FORDER); |
214 | | assert_not_layouts!(brow, CORDER, CPREFER, FORDER, FPREFER); |
215 | | } |
216 | | } |
217 | | |
218 | | #[test] |
219 | | fn skip_layouts() |
220 | | { |
221 | | let a = M::zeros((5, 5)); |
222 | | { |
223 | | let v1 = a.slice(s![..;2, ..]).layout(); |
224 | | let v2 = a.slice(s![.., ..;2]).layout(); |
225 | | |
226 | | assert!(!v1.is(Layout::CORDER) && v1.is(Layout::CPREFER)); |
227 | | assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER)); |
228 | | assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER)); |
229 | | assert!(!v2.is(Layout::FORDER) && !v2.is(Layout::FPREFER)); |
230 | | } |
231 | | |
232 | | let b = M::zeros((5, 5).f()); |
233 | | { |
234 | | let v1 = b.slice(s![..;2, ..]).layout(); |
235 | | let v2 = b.slice(s![.., ..;2]).layout(); |
236 | | |
237 | | assert!(!v1.is(Layout::CORDER) && !v1.is(Layout::CPREFER)); |
238 | | assert!(!v1.is(Layout::FORDER) && !v1.is(Layout::FPREFER)); |
239 | | assert!(!v2.is(Layout::CORDER) && !v2.is(Layout::CPREFER)); |
240 | | assert!(!v2.is(Layout::FORDER) && v2.is(Layout::FPREFER)); |
241 | | } |
242 | | } |
243 | | } |