1#[cfg(feature="serde")]
5use serde::{Deserialize, Serialize};
6
7pub mod coordinate;
8pub mod dimensions;
9pub mod rectangle;
10pub use self::coordinate::Coordinate;
11pub use self::dimensions::Dimensions;
12pub use self::rectangle::Rectangle;
13
14#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
16#[derive(Clone, Debug, Default, Eq, PartialEq)]
17pub struct Mat <T> {
18 elements : Vec <T>,
19 dimensions : Dimensions
20}
21
22pub struct RectIter <'a, T : 'a> {
28 mat : &'a Mat <T>,
29 rectangle : Rectangle,
30 current : Coordinate
31}
32
33pub struct RectIterMut <'a, T : 'a> {
38 mat : &'a mut Mat <T>,
39 rectangle : Rectangle,
40 current : Coordinate
41}
42
43impl <T> Mat <T> {
44 #[inline]
47 pub fn fill_with (dimensions : Dimensions, element : &T) -> Self where
48 T : Clone
49 {
50 Mat {
51 elements: vec![element.clone(); dimensions.area()],
52 dimensions
53 }
54 }
55 #[inline]
57 pub fn with_dimensions (dimensions : Dimensions) -> Self where
58 T : Clone + Default
59 {
60 Self::fill_with (dimensions, &T::default())
61 }
62 #[inline]
67 pub fn from_vec (dimensions : Dimensions, elements : Vec <T>)
68 -> Option <Self>
69 {
70 if dimensions.area() == elements.len() {
71 Some (Mat { elements, dimensions })
72 } else {
73 None
74 }
75 }
76 #[inline]
77 pub fn dimensions (&self) -> Dimensions {
78 self.dimensions
79 }
80 #[inline]
95 pub fn get (&self, Coordinate { row, column } : Coordinate) -> Option <&T> {
96 self.get_rc (row, column)
97 }
98 #[inline]
99 pub fn get_rc (&self, row : usize, column : usize) -> Option <&T> {
100 if self.dimensions.contains_rc (row, column) {
101 let i = row * self.width() + column;
102 Some (&self.elements[i])
103 } else {
104 None
105 }
106 }
107 #[inline]
108 pub fn get_mut (&mut self, Coordinate { row, column } : Coordinate)
109 -> Option <&mut T>
110 {
111 self.get_mut_rc (row, column)
112 }
113 #[inline]
131 pub fn get_mut_rc (&mut self, row : usize, column : usize)
132 -> Option <&mut T>
133 {
134 if self.dimensions.contains_rc (row, column) {
135 let i = row * self.dimensions.columns + column;
136 Some (&mut self.elements[i])
137 } else {
138 None
139 }
140 }
141 #[inline]
142 pub const fn width (&self) -> usize {
143 self.dimensions.columns
144 }
145 #[inline]
146 pub const fn height (&self) -> usize {
147 self.dimensions.rows
148 }
149 #[inline]
150 pub fn rectangle (&self) -> Rectangle {
151 self.dimensions.into()
152 }
153 #[inline]
154 pub fn row (&self, row : usize) -> Option <Rectangle> {
155 self.dimensions.row (row)
156 }
157 #[inline]
158 pub fn column (&self, column : usize) -> Option <Rectangle> {
159 self.dimensions.column (column)
160 }
161 #[inline]
162 pub fn top (&self) -> Option <Rectangle> {
163 self.dimensions.top()
164 }
165 #[inline]
166 pub fn bottom (&self) -> Option <Rectangle> {
167 self.dimensions.bottom()
168 }
169 #[inline]
170 pub fn left (&self) -> Option <Rectangle> {
171 self.dimensions.left()
172 }
173 #[inline]
174 pub fn right (&self) -> Option <Rectangle> {
175 self.dimensions.right()
176 }
177 #[inline]
182 pub fn resize (&mut self, dimensions : Dimensions, element : T) where
183 T : Clone
184 {
185 self.elements.resize (dimensions.area(), element);
186 self.dimensions = dimensions;
187 }
188 pub fn flip_horizontal (&mut self) -> &mut Self {
189 let cols = self.dimensions.columns;
190 let rows = self.dimensions.rows;
191 for row in 0..rows {
192 let min = row * cols;
193 let max = row * cols + cols;
194 self.elements[min..max].reverse();
195 }
196 self
197 }
198 pub fn flip_vertical (&mut self) -> &mut Self {
199 self.elements.reverse();
200 self.flip_horizontal()
201 }
202 #[inline]
203 pub fn to_vec (self) -> Vec <T> {
204 self.elements
205 }
206 #[inline]
208 #[allow(mismatched_lifetime_syntaxes)]
209 pub fn elements (&self) -> std::slice::Iter <T> {
210 self.elements.iter()
211 }
212 #[inline]
214 #[allow(mismatched_lifetime_syntaxes)]
215 pub fn elements_mut (&mut self) -> std::slice::IterMut <T> {
216 self.elements.iter_mut()
217 }
218 #[inline]
219 #[allow(mismatched_lifetime_syntaxes)]
220 pub fn rows (&self) -> std::slice::Chunks <T> {
221 self.elements.chunks (self.width())
222 }
223 #[inline]
224 #[allow(mismatched_lifetime_syntaxes)]
225 pub fn rows_mut (&mut self) -> std::slice::ChunksMut <T> {
226 let width = self.width();
227 self.elements.chunks_mut (width)
228 }
229 pub fn rect_iter <'a> (&'a self, rectangle : Rectangle)
234 -> Option <RectIter <'a, T>>
235 {
236 if self.dimensions.contains (rectangle.min()) &&
237 self.dimensions.contains (rectangle.max())
238 {
239 let current = rectangle.min();
240 Some (RectIter { mat: self, rectangle, current })
241 } else {
242 None
243 }
244 }
245 pub fn rect_iter_mut <'a> (&'a mut self, rectangle : Rectangle)
250 -> Option <RectIterMut <'a, T>>
251 {
252 println!("DIMENSIONS: {:?}", self.dimensions);
253 println!("RECT: {:?}", rectangle);
254 if self.dimensions.contains (rectangle.max()) &&
255 self.dimensions.contains (rectangle.min())
256 {
257 let current = rectangle.min();
258 Some (RectIterMut { mat: self, rectangle, current })
259 } else {
260 None
261 }
262 }
263}
264impl <T : Clone> Mat <T> {
265 pub fn rotate_cw (&mut self) -> &mut Self {
266 let len = self.elements.len();
267 let mut v = Vec::with_capacity (len);
268 for col in 0..self.dimensions.columns {
269 for row in 0..self.dimensions.rows {
270 let row = self.dimensions.rows - row - 1;
271 v.push (self.get_rc (row, col).unwrap().clone());
272 }
273 }
274 debug_assert_eq!(v.len(), len);
275 self.elements = v;
276 self
277 }
278 pub fn rotate_ccw (&mut self) -> &mut Self {
279 let len = self.elements.len();
280 let mut v = Vec::with_capacity (len);
281 for col in 0..self.dimensions.columns {
282 let col = self.dimensions.columns - col - 1;
283 for row in 0..self.dimensions.rows {
284 v.push (self.get_rc (row, col).unwrap().clone());
285 }
286 }
287 debug_assert_eq!(v.len(), len);
288 self.elements = v;
289 self
290 }
291 #[inline]
292 pub fn tranpose (&mut self) -> &mut Self {
293 self.rotate_cw().flip_horizontal()
294 }
295}
296impl <T> std::ops::Deref for Mat <T> {
297 type Target = Vec <T>;
298 fn deref (&self) -> &Vec <T> {
299 &self.elements
300 }
301}
302impl <T : std::fmt::Debug> Mat <T> {
303 pub fn write_formatted <W : std::io::Write>
304 (&self, w : &mut W) -> std::io::Result <()>
305 {
306 let mut columns = Vec::new();
307 for column in 0..self.width() {
308 let v = self.rect_iter (self.column (column).unwrap()).unwrap()
309 .map (|(_, element)| format!("{:?}", element))
310 .collect::<Vec <String>>();
311 let longest = v.iter().map (String::len).max().unwrap();
312 columns.push ((longest, v));
313 }
314 for row in 0..self.height() {
315 for column in 0..self.width() {
316 use std::iter::FromIterator;
317 let (longest, col) = &columns[column];
318 let s = &col[row];
319 let space = longest - s.len() + 1;
320 write!(w, "{}{}", s,
321 String::from_iter (std::iter::repeat (' ').take (space)))?;
322 }
323 writeln!(w)?;
324 }
325 Ok (())
326 }
327}
328impl <T : std::fmt::Display> std::fmt::Display for Mat <T> {
329 fn fmt (&self, f : &mut std::fmt::Formatter <'_>) -> std::fmt::Result {
330 let mut columns = Vec::new();
331 for column in 0..self.width() {
332 let v = self.rect_iter (self.column (column).unwrap()).unwrap()
333 .map (|(_, element)| format!("{}", element))
334 .collect::<Vec <String>>();
335 let longest = v.iter().map (String::len).max().unwrap();
336 columns.push ((longest, v));
337 }
338 for row in 0..self.height() {
339 for column in 0..self.width() {
340 use std::iter::FromIterator;
341 let (longest, col) = &columns[column];
342 let s = &col[row];
343 let space = longest - s.len() + 1;
344 write!(f, "{}{}", s,
345 String::from_iter (std::iter::repeat (' ').take (space)))?;
346 }
347 writeln!(f)?;
348 }
349 Ok (())
350 }
351}
352
353impl <'a, T> Iterator for RectIter <'a, T> {
354 type Item = (Coordinate, &'a T);
355 fn next (&mut self) -> Option <Self::Item> {
356 if self.current.row <= self.rectangle.max().row {
357 let next = (self.current, self.mat.get (self.current).unwrap());
358 self.current.column += 1;
359 if self.current.column > self.rectangle.max().column {
360 self.current.column = self.rectangle.min().column;
361 self.current.row += 1;
362 }
363 Some (next)
364 } else {
365 None
366 }
367 }
368}
369
370impl <'a, T> Iterator for RectIterMut <'a, T> {
371 type Item = (Coordinate, &'a mut T);
372 fn next (&mut self) -> Option <Self::Item> {
373 if self.current.row <= self.rectangle.max().row {
374 let coordinate = self.current;
375 let element = unsafe {
376 &mut *(self.mat.get_mut (coordinate).unwrap() as *mut T)
377 };
378 self.current.column += 1;
379 if self.current.column > self.rectangle.max().column {
380 self.current.column = self.rectangle.min().column;
381 self.current.row += 1;
382 }
383 Some ((coordinate, element))
384 } else {
385 None
386 }
387 }
388}
389
390#[cfg(test)]
391mod test {
392 use super::*;
393
394 #[test]
395 fn test_rect_iter_mut() {
396 let elements = vec![1, 2, 3, 4];
397 let mut mat = Mat::from_vec ((2, 2).into(), elements).unwrap();
398 let rectangle = Rectangle::from (((0, 0).into(), (2, 2).into()));
399 let mut actual_coords = Vec::new();
400 for (coord, elem) in mat.rect_iter_mut (rectangle).unwrap() {
401 *elem = -(*elem);
402 actual_coords.push ((coord.row, coord.column));
403 }
404 assert_eq!(actual_coords, [(0, 0), (0, 1), (1, 0), (1, 1)]);
405 assert_eq!(mat.elements, [-1, -2, -3, -4]);
406 }
407
408 #[test]
409 fn test_two_iterators() {
410 let dimensions = (2, 3).into();
411 let m = Mat::from_vec (dimensions, vec![0, 1, 2, 3, 4, 5]).unwrap();
412 let iter1 = m.rect_iter (dimensions.into()).unwrap();
413 let iter2 = m.rect_iter (dimensions.into()).unwrap();
414 for ((coord1, elem1), (coord2, elem2)) in iter1.zip (iter2) {
415 assert_eq!(coord1, coord2);
416 assert_eq!(elem1, elem2);
417 }
418 }
419
420 #[test]
421 fn test_rect_iter() {
422 let dimensions = (3, 3).into();
423 let m = Mat::from_vec (dimensions, vec![0, 1, 2, 3, 4, 5, 6, 7, 8])
424 .unwrap();
425 let dimensions = Dimensions::from ((2, 2));
426 let mut iter = m.rect_iter (dimensions.into()).unwrap();
427 let (coord, elem) = iter.next().unwrap();
428 assert_eq!((coord, *elem), (Coordinate {row: 0, column: 0}, 0));
429 let (coord, elem) = iter.next().unwrap();
430 assert_eq!((coord, *elem), (Coordinate {row: 0, column: 1}, 1));
431 let (coord, elem) = iter.next().unwrap();
432 assert_eq!((coord, *elem), (Coordinate {row: 1, column: 0}, 3));
433 let (coord, elem) = iter.next().unwrap();
434 assert_eq!((coord, *elem), (Coordinate {row: 1, column: 1}, 4));
435 assert!(iter.next().is_none());
436 }
437}