1use core::fmt;
2use core::fmt::{Formatter, Debug};
3use core::ops::{Index, IndexMut, Range};
4use core::ptr;
5use core::mem;
6
7use crate::toodee::*;
8use crate::ops::*;
9use crate::iter::*;
10
11fn calculate_view_dimensions<T>(start: Coordinate, end: Coordinate, toodee: &impl TooDeeOps<T>, stride: usize) -> (usize, usize, Range<usize>) {
14 assert!(end.0 >= start.0);
15 assert!(end.1 >= start.1);
16 assert!(end.0 <= toodee.num_cols());
17 assert!(end.1 <= toodee.num_rows());
18 assert!(stride >= toodee.num_cols());
19 let mut num_cols = end.0 - start.0;
20 let mut num_rows = end.1 - start.1;
21 if num_cols == 0 || num_rows == 0 {
23 num_cols = 0;
24 num_rows = 0;
25 }
26 let data_start = start.1 * stride + start.0;
27 let data_len = {
28 if num_rows == 0 {
29 0
30 } else {
31 (num_rows - 1) * stride + num_cols
32 }
33 };
34 (num_cols, num_rows, data_start..data_start + data_len)
35}
36
37#[cfg(test)]
38mod tests {
39 use super::*;
40 use alloc::vec;
41
42 #[test]
43 fn calc_dims_view() {
44 let v = vec![1u32; 32];
45 let view = TooDeeView::new(4, 4, &v);
46 let (num_cols, num_rows, range) = calculate_view_dimensions((0, 1), (2,3), &view, 4);
47 assert_eq!(num_cols, 2);
48 assert_eq!(num_rows, 2);
49 assert_eq!(range, 4..10);
50 }
51}
52
53trait TooDeeViewCommon<T>: TooDeeOps<T> {
55
56 fn data(&self) -> &[T];
57
58 fn stride(&self) -> usize;
59
60 fn get_col_params(&self, col: usize) -> (Range<usize>, usize){
61 assert!(col < self.num_cols());
62 let stride = self.stride();
63 let start = col;
64 let end = {
65 let num_rows = self.num_rows();
66 if num_rows == 0 {
67 start
68 } else {
69 start + (num_rows - 1) * stride + 1
70 }
71 };
72 (start..end, stride - 1)
73 }
74
75
76}
77
78impl<T> TooDeeViewCommon<T> for TooDeeView<'_, T> {
79 #[inline]
80 fn data(&self) -> &[T] { &self.data }
81 #[inline]
82 fn stride(&self) -> usize {
83 self.stride
84 }
85}
86
87impl<T> TooDeeViewCommon<T> for TooDeeViewMut<'_, T> {
88 #[inline]
89 fn data(&self) -> &[T] { &self.data }
90 #[inline]
91 fn stride(&self) -> usize {
92 self.stride
93 }
94}
95
96
97#[derive(Copy, Clone, Hash, Eq, PartialEq)]
99pub struct TooDeeView<'a, T> {
100 data: &'a [T],
101 num_cols: usize,
102 num_rows: usize,
103 stride: usize,
104}
105
106impl<'a, T> TooDeeView<'a, T> {
107 pub fn new(num_cols: usize, num_rows: usize, data: &'a [T]) -> TooDeeView<'a, T> {
127 if num_cols == 0 || num_rows == 0 {
128 assert_eq!(num_rows, num_cols);
129 }
130 let size = num_cols.checked_mul(num_rows).unwrap();
131 assert!(size <= data.len());
132 TooDeeView {
133 data: &data[..size],
134 num_cols,
135 num_rows,
136 stride: num_cols,
137 }
138 }
139
140 pub(super) fn from_toodee(start: Coordinate, end: Coordinate, toodee: &'a TooDee<T>) -> TooDeeView<'a, T> {
142 let stride = toodee.num_cols();
143 let (num_cols, num_rows, data_range) = calculate_view_dimensions(start, end, toodee, stride);
144 unsafe {
145 TooDeeView {
146 data: toodee.data().get_unchecked(data_range),
147 num_cols,
148 num_rows,
149 stride,
150 }
151 }
152 }
153}
154
155impl<'a, T> TooDeeOps<T> for TooDeeView<'a, T>
156{
157 #[inline]
158 fn num_cols(&self) -> usize {
159 self.num_cols
160 }
161
162 #[inline]
163 fn num_rows(&self) -> usize {
164 self.num_rows
165 }
166
167 fn view(&self, start: Coordinate, end: Coordinate) -> TooDeeView<'_, T> {
168 let (num_cols, num_rows, data_range) = calculate_view_dimensions(start, end, self, self.stride);
169 unsafe {
170 TooDeeView {
171 data: self.data.get_unchecked(data_range),
172 num_cols,
173 num_rows,
174 stride: self.stride,
175 }
176 }
177 }
178
179 fn rows(&self) -> Rows<'_, T> {
180 Rows {
181 v: self.data,
182 cols: self.num_cols,
183 skip_cols: self.stride - self.num_cols,
184 }
185 }
186
187 fn col(&self, col: usize) -> Col<'_, T> {
188 let (data_range, skip) = self.get_col_params(col);
189 unsafe {
190 Col {
191 v: self.data.get_unchecked(data_range),
192 skip,
193 }
194 }
195 }
196
197 unsafe fn get_unchecked_row(&self, row: usize) -> &[T] {
209 let start = row * self.stride;
210 self.data.get_unchecked(start..start + self.num_cols)
211 }
212
213 unsafe fn get_unchecked(&self, coord: Coordinate) -> &T {
224 self.data.get_unchecked(coord.1 * self.stride + coord.0)
225 }
226}
227
228impl<'a, T> Index<usize> for TooDeeView<'a, T> {
229 type Output = [T];
230
231 fn index(&self, row: usize) -> &Self::Output {
232 assert!(row < self.num_rows);
233 let start = row * self.stride;
234 unsafe {
235 self.data.get_unchecked(start..start + self.num_cols)
236 }
237 }
238}
239
240impl<'a, T> Index<Coordinate> for TooDeeView<'a, T> {
241 type Output = T;
242
243 fn index(&self, coord: Coordinate) -> &Self::Output {
244 assert!(coord.1 < self.num_rows);
245 assert!(coord.0 < self.num_cols);
246 unsafe {
248 self.data.get_unchecked(coord.1 * self.stride + coord.0)
249 }
250 }
251}
252
253
254#[derive(Hash, Eq, PartialEq)]
256pub struct TooDeeViewMut<'a, T> {
257 data: &'a mut [T],
258 num_cols: usize,
259 num_rows: usize,
260 stride: usize,
261}
262
263
264impl<'a, T> TooDeeViewMut<'a, T> {
265 pub fn new(num_cols: usize, num_rows: usize, data: &'a mut [T]) -> TooDeeViewMut<'a, T> {
285 if num_cols == 0 || num_rows == 0 {
286 assert_eq!(num_rows, num_cols);
287 }
288 let size = num_cols.checked_mul(num_rows).unwrap();
289 assert!(size <= data.len());
290 unsafe {
291 TooDeeViewMut {
292 data: data.get_unchecked_mut(..size),
293 num_cols,
294 num_rows,
295 stride: num_cols,
296 }
297 }
298 }
299
300 pub(super) fn from_toodee(start: Coordinate, end: Coordinate, toodee: &'a mut TooDee<T>) -> TooDeeViewMut<'a, T> {
302 let stride = toodee.num_cols();
303 let (num_cols, num_rows, data_range) = calculate_view_dimensions(start, end, toodee, stride);
304 unsafe {
305 TooDeeViewMut {
306 data: toodee.data_mut().get_unchecked_mut(data_range),
307 num_cols,
308 num_rows,
309 stride,
310 }
311 }
312 }
313}
314
315
316impl<'a, T> TooDeeOps<T> for TooDeeViewMut<'a, T> {
317 #[inline]
318 fn num_rows(&self) -> usize {
319 self.num_rows
320 }
321
322 #[inline]
323 fn num_cols(&self) -> usize {
324 self.num_cols
325 }
326
327 fn view(&self, start: Coordinate, end: Coordinate) -> TooDeeView<'_, T> {
328 let (num_cols, num_rows, data_range) = calculate_view_dimensions(start, end, self, self.stride);
329 TooDeeView {
330 data: &self.data[data_range],
331 num_cols,
332 num_rows,
333 stride: self.stride,
334 }
335 }
336
337 fn rows(&self) -> Rows<'_, T> {
338 Rows {
339 v: self.data,
340 cols: self.num_cols,
341 skip_cols: self.stride - self.num_cols,
342 }
343 }
344
345 fn col(&self, col: usize) -> Col<'_, T> {
346 let (data_range, skip) = self.get_col_params(col);
347 unsafe {
348 Col {
349 v: self.data.get_unchecked(data_range),
350 skip,
351 }
352 }
353 }
354
355 unsafe fn get_unchecked_row(&self, row: usize) -> &[T] {
367 let start = row * self.stride;
368 self.data.get_unchecked(start..start + self.num_cols)
369 }
370
371 unsafe fn get_unchecked(&self, coord: Coordinate) -> &T {
382 self.data.get_unchecked(coord.1 * self.stride + coord.0)
383 }
384}
385
386impl<'a, T> TooDeeOpsMut<T> for TooDeeViewMut<'a, T> {
387 fn view_mut(&mut self, start: Coordinate, end: Coordinate) -> TooDeeViewMut<'_, T> {
388 let (num_cols, num_rows, data_range) = calculate_view_dimensions(start, end, self, self.stride);
389 unsafe {
390 TooDeeViewMut {
391 data: self.data.get_unchecked_mut(data_range),
392 num_cols,
393 num_rows,
394 stride: self.stride,
395 }
396 }
397 }
398
399 fn rows_mut(&mut self) -> RowsMut<'_, T> {
400 RowsMut {
401 v: self.data,
402 cols: self.num_cols,
403 skip_cols: self.stride - self.num_cols,
404 }
405 }
406
407 fn col_mut(&mut self, col: usize) -> ColMut<'_, T> {
408 let (data_range, skip) = self.get_col_params(col);
409 unsafe {
410 ColMut {
411 v: self.data.get_unchecked_mut(data_range),
412 skip,
413 }
414 }
415 }
416
417 fn swap_rows(&mut self, mut r1: usize, mut r2: usize) {
434 if r1 == r2 {
435 return;
436 }
437 if r2 < r1 {
438 mem::swap(&mut r1, &mut r2);
439 }
440 assert!(r2 < self.num_rows);
441 let num_cols = self.num_cols;
442 unsafe {
443 let (first, rest) = self.data.get_unchecked_mut(r1 * self.stride..).split_at_mut(num_cols);
444 let snd_idx = (r2 - r1) * self.stride - num_cols;
445 let second = rest.get_unchecked_mut(snd_idx..snd_idx + num_cols);
446 debug_assert_eq!(first.len(), num_cols);
448 debug_assert_eq!(second.len(), num_cols);
449 ptr::swap_nonoverlapping(first.as_mut_ptr(), second.as_mut_ptr(), num_cols);
451 }
452 }
453
454 unsafe fn get_unchecked_row_mut(&mut self, row: usize) -> &mut [T] {
466 let start = row * self.stride;
467 self.data.get_unchecked_mut(start..start + self.num_cols)
468 }
469
470
471 unsafe fn get_unchecked_mut(&mut self, coord: Coordinate) -> &mut T {
482 self.data.get_unchecked_mut(coord.1 * self.stride + coord.0)
483 }
484}
485
486impl<'a, T> Index<usize> for TooDeeViewMut<'a, T> {
487 type Output = [T];
488 fn index(&self, row: usize) -> &Self::Output {
489 assert!(row < self.num_rows);
490 let start = row * self.stride;
491 unsafe {
492 self.data.get_unchecked(start..start + self.num_cols)
493 }
494 }
495}
496
497impl<'a, T> Index<Coordinate> for TooDeeViewMut<'a, T> {
498 type Output = T;
499 fn index(&self, coord: Coordinate) -> &Self::Output {
500 assert!(coord.1 < self.num_rows);
501 assert!(coord.0 < self.num_cols);
502 unsafe {
504 self.data.get_unchecked(coord.1 * self.stride + coord.0)
505 }
506 }
507}
508
509impl<'a, T> IndexMut<usize> for TooDeeViewMut<'a, T> {
510 fn index_mut(&mut self, row: usize) -> &mut Self::Output {
511 assert!(row < self.num_rows);
512 let start = row * self.stride;
513 unsafe {
514 self.data.get_unchecked_mut(start..start + self.num_cols)
515 }
516 }
517}
518
519impl<'a, T> IndexMut<Coordinate> for TooDeeViewMut<'a, T> {
520 fn index_mut(&mut self, coord: Coordinate) -> &mut Self::Output {
521 assert!(coord.1 < self.num_rows);
522 assert!(coord.0 < self.num_cols);
523 unsafe {
525 self.data.get_unchecked_mut(coord.1 * self.stride + coord.0)
526 }
527 }
528}
529
530impl<'a, T> From<TooDeeViewMut<'a, T>> for TooDeeView<'a, T> {
531 fn from(v: TooDeeViewMut<'a, T>) -> TooDeeView<'a, T> {
532 TooDeeView {
533 data: v.data,
534 num_cols: v.num_cols,
535 num_rows: v.num_rows,
536 stride: v.stride,
537 }
538 }
539}
540
541impl<'a, T> IntoIterator for &'a TooDeeView<'a, T> {
542 type Item = &'a T;
543 type IntoIter = Cells<'a, T>;
544 fn into_iter(self) -> Self::IntoIter {
545 self.cells()
546 }
547}
548
549impl<'a, T> IntoIterator for &'a TooDeeViewMut<'a, T> {
550 type Item = &'a T;
551 type IntoIter = Cells<'a, T>;
552 fn into_iter(self) -> Self::IntoIter {
553 self.cells()
554 }
555}
556
557impl<'a, T> IntoIterator for &'a mut TooDeeViewMut<'a, T> {
558 type Item = &'a mut T;
559 type IntoIter = CellsMut<'a, T>;
560 fn into_iter(self) -> Self::IntoIter {
561 self.cells_mut()
562 }
563}
564
565impl<T> Debug for TooDeeView<'_, T> where T: Debug {
566 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
567 f.debug_list().entries(self.rows()).finish()
568 }
569}
570
571impl<T> Debug for TooDeeViewMut<'_, T> where T: Debug {
572 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
573 f.debug_list().entries(self.rows()).finish()
574 }
575}