1#[cfg(feature = "parallel")]
2use rayon::prelude::*;
3use serde::{Deserialize, Serialize};
4use std::ops::{Add, Div, Index, IndexMut, Mul, Neg, Range, Sub};
5
6pub type Grid2dCommonAreas = (Range<(usize, usize)>, Range<(usize, usize)>);
7
8#[derive(Debug, Clone)]
9pub enum Grid2dError {
10 DifferentDimensions((usize, usize), (usize, usize)),
11 TryingToReadFromAndWriteToSameLocation(usize, usize),
12 DuplicatedCoord(usize, usize),
13 InputAndOutputBuffersHaveDifferentSizeForReads(usize, usize),
15 InputAndOutputBuffersHaveDifferentSizeForWrites(usize, usize),
17}
18
19#[derive(Debug)]
20pub struct Grid2dNeighborSample<T> {
21 cells: [T; 9],
22 cols: usize,
23 rows: usize,
24}
25
26impl<T> Grid2dNeighborSample<T>
27where
28 T: Clone,
29{
30 #[inline]
31 pub fn cols(&self) -> usize {
32 self.cols
33 }
34
35 #[inline]
36 pub fn rows(&self) -> usize {
37 self.rows
38 }
39
40 #[inline]
41 pub fn size(&self) -> (usize, usize) {
42 (self.cols, self.rows)
43 }
44
45 #[inline]
46 pub fn len(&self) -> usize {
47 self.cols * self.rows
48 }
49
50 #[inline]
51 pub fn is_empty(&self) -> bool {
52 self.cols == 0 && self.rows == 0
53 }
54
55 #[inline]
56 pub fn cells(&self) -> &[T] {
57 &self.cells
58 }
59
60 #[inline]
61 pub fn cell(&self, col: usize, row: usize) -> Option<&T> {
62 if col < self.cols && row < self.rows {
63 Some(&self.cells[row * self.cols + col])
64 } else {
65 None
66 }
67 }
68
69 #[inline]
70 pub fn cell_mut(&mut self, col: usize, row: usize) -> Option<&mut T> {
71 if col < self.cols && row < self.rows {
72 Some(&mut self.cells[row * self.cols + col])
73 } else {
74 None
75 }
76 }
77
78 #[inline]
79 pub fn get(&self, col: usize, row: usize) -> Option<T> {
80 if col < self.cols && row < self.rows {
81 Some(self.cells[row * self.cols + col].clone())
82 } else {
83 None
84 }
85 }
86
87 #[inline]
88 pub fn set(&mut self, col: usize, row: usize, value: T) {
89 if col < self.cols && row < self.rows {
90 self.cells[row * self.cols + col] = value;
91 }
92 }
93
94 pub fn map<F, R>(&self, mut f: F) -> Grid2dNeighborSample<R>
95 where
96 F: FnMut(usize, usize, &T) -> R,
97 R: Default + Copy,
98 {
99 let mut cells = [R::default(); 9];
100 for (i, v) in self.cells.iter().enumerate() {
101 cells[i] = f(i % self.cols, i / self.cols, v);
102 }
103 Grid2dNeighborSample::<R> {
104 cells,
105 cols: self.cols,
106 rows: self.rows,
107 }
108 }
109
110 pub fn with<F>(&mut self, mut f: F)
111 where
112 F: FnMut(usize, usize, &T) -> T,
113 {
114 for (i, v) in self.cells.iter_mut().enumerate() {
115 *v = f(i % self.cols, i / self.cols, v);
116 }
117 }
118
119 #[inline]
120 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> {
121 self.cells.iter()
122 }
123
124 #[inline]
125 pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut T> {
126 self.cells.iter_mut()
127 }
128}
129
130impl<T> Index<(usize, usize)> for Grid2dNeighborSample<T>
131where
132 T: Clone + Send + Sync,
133{
134 type Output = T;
135
136 fn index(&self, (col, row): (usize, usize)) -> &T {
137 self.cell(col, row).unwrap()
138 }
139}
140
141impl<T> Index<[usize; 2]> for Grid2dNeighborSample<T>
142where
143 T: Clone + Send + Sync,
144{
145 type Output = T;
146
147 fn index(&self, [col, row]: [usize; 2]) -> &T {
148 self.cell(col, row).unwrap()
149 }
150}
151
152impl<T> IndexMut<(usize, usize)> for Grid2dNeighborSample<T>
153where
154 T: Clone + Send + Sync,
155{
156 fn index_mut(&mut self, (col, row): (usize, usize)) -> &mut T {
157 self.cell_mut(col, row).unwrap()
158 }
159}
160
161impl<T> IndexMut<[usize; 2]> for Grid2dNeighborSample<T>
162where
163 T: Clone + Send + Sync,
164{
165 fn index_mut(&mut self, [col, row]: [usize; 2]) -> &mut T {
166 self.cell_mut(col, row).unwrap()
167 }
168}
169
170impl<I, T> From<(usize, I)> for Grid2dNeighborSample<T>
171where
172 I: Iterator<Item = T>,
173 T: Default + Copy,
174{
175 fn from((cols, iter): (usize, I)) -> Self {
176 let mut cells = [T::default(); 9];
177 let mut index = 0;
178 for v in iter.take(9) {
179 cells[index] = v;
180 index += 1;
181 }
182 Self {
183 cells,
184 cols,
185 rows: index / cols,
186 }
187 }
188}
189
190#[derive(Debug, Default, Clone, Serialize, Deserialize)]
191pub struct Grid2d<T> {
192 cells: Vec<T>,
193 cols: usize,
194 rows: usize,
195}
196
197impl<T> Grid2d<T>
198where
199 T: Clone + Send + Sync,
200{
201 pub fn new(cols: usize, rows: usize, fill: T) -> Self {
202 Self {
203 cells: vec![fill; cols * rows],
204 cols,
205 rows,
206 }
207 }
208
209 pub fn with_cells(cols: usize, cells: Vec<T>) -> Self {
210 if cells.len() % cols != 0 {
211 panic!(
212 "cells does not fill grid with desired cols number. cells: {}, cols: {}",
213 cells.len(),
214 cols
215 );
216 }
217 let rows = cells.len() / cols;
218 Self { cells, cols, rows }
219 }
220
221 pub fn resize(&mut self, cols: usize, rows: usize, default: T) {
222 if cols == self.cols && rows == self.rows {
223 return;
224 }
225 let old = std::mem::replace(self, Self::new(cols, rows, default));
226 let cols = old.cols().min(self.cols());
227 let rows = old.rows().min(self.rows());
228 for row in 0..rows {
229 for col in 0..cols {
230 self.set(col, row, self.get(col, row).unwrap());
231 }
232 }
233 }
234
235 #[inline]
236 pub fn cols(&self) -> usize {
237 self.cols
238 }
239
240 #[inline]
241 pub fn rows(&self) -> usize {
242 self.rows
243 }
244
245 #[inline]
246 pub fn size(&self) -> (usize, usize) {
247 (self.cols, self.rows)
248 }
249
250 #[inline]
251 pub fn len(&self) -> usize {
252 self.cols * self.rows
253 }
254
255 #[inline]
256 pub fn is_empty(&self) -> bool {
257 self.cols == 0 && self.rows == 0
258 }
259
260 #[inline]
261 pub fn cells(&self) -> &[T] {
262 &self.cells
263 }
264
265 #[inline]
266 pub fn cells_mut(&mut self) -> &mut [T] {
267 &mut self.cells
268 }
269
270 #[inline]
271 pub fn cell(&self, col: usize, row: usize) -> Option<&T> {
272 if col < self.cols && row < self.rows {
273 Some(&self.cells[row * self.cols + col])
274 } else {
275 None
276 }
277 }
278
279 #[inline]
280 pub fn cell_mut(&mut self, col: usize, row: usize) -> Option<&mut T> {
281 if col < self.cols && row < self.rows {
282 Some(&mut self.cells[row * self.cols + col])
283 } else {
284 None
285 }
286 }
287
288 #[inline]
289 pub fn get(&self, col: usize, row: usize) -> Option<T> {
290 if col < self.cols && row < self.rows {
291 Some(self.cells[row * self.cols + col].clone())
292 } else {
293 None
294 }
295 }
296
297 #[inline]
298 pub fn set(&mut self, col: usize, row: usize, value: T) {
299 if col < self.cols && row < self.rows {
300 self.cells[row * self.cols + col] = value;
301 }
302 }
303
304 pub fn get_col_cells(&self, index: usize) -> Option<Vec<T>> {
305 if index < self.cols {
306 let result = {
307 (0..self.rows)
308 .map(|row| self.cells[row * self.cols + index].clone())
309 .collect::<Vec<_>>()
310 };
311 Some(result)
312 } else {
313 None
314 }
315 }
316
317 pub fn get_row_cells(&self, index: usize) -> Option<Vec<T>> {
318 if index < self.rows {
319 let start = index * self.cols;
320 let end = start + self.cols;
321 Some(self.cells.as_slice()[start..end].to_owned())
322 } else {
323 None
324 }
325 }
326
327 pub fn copy_part(&self, mut range: Range<(usize, usize)>, result: &mut Self)
328 where
329 T: Default,
330 {
331 range.end.0 = range.end.0.min(self.cols);
332 range.end.1 = range.end.1.min(self.rows);
333 range.start.0 = range.start.0.min(range.end.0);
334 range.start.1 = range.start.1.min(range.end.1);
335 let cols = range.end.0 - range.start.0;
336 let rows = range.end.1 - range.start.1;
337 result.resize(cols, rows, T::default());
338 for row in range.start.1..range.end.1 {
339 for col in range.start.0..range.end.0 {
340 result.set(col, row, self.cells[row * self.cols + col].clone());
341 }
342 }
343 }
344
345 pub fn get_part(&self, mut range: Range<(usize, usize)>) -> Self {
346 range.end.0 = range.end.0.min(self.cols);
347 range.end.1 = range.end.1.min(self.rows);
348 range.start.0 = range.start.0.min(range.end.0);
349 range.start.1 = range.start.1.min(range.end.1);
350 let cols = range.end.0 - range.start.0;
351 let rows = range.end.1 - range.start.1;
352 let result = (0..(cols * rows))
353 .map(|i| {
354 let col = range.start.0 + (i % cols);
355 let row = range.start.1 + (i / cols);
356 self.cells[row * self.cols + col].clone()
357 })
358 .collect::<Vec<_>>();
359 Self::with_cells(cols, result)
360 }
361
362 pub fn get_part_seamless(&self, range: Range<(usize, usize)>) -> Self {
363 let from_col = range.start.0.min(range.end.0);
364 let to_col = range.start.0.max(range.end.0);
365 let from_row = range.start.1.min(range.end.1);
366 let to_row = range.start.1.max(range.end.1);
367 let cols = to_col - from_col;
368 let rows = to_row - from_row;
369 let result = (0..(cols * rows))
370 .map(|i| {
371 let col = from_col + (i % cols);
372 let row = from_row + (i / cols);
373 let c = col % self.cols;
374 let r = row % self.rows;
375 self.cells[r * self.cols + c].clone()
376 })
377 .collect::<Vec<_>>();
378 Grid2d::with_cells(cols, result)
379 }
380
381 pub fn get_view(&self, mut range: Range<(usize, usize)>) -> Grid2d<&T> {
382 range.end.0 = range.end.0.min(self.cols);
383 range.end.1 = range.end.1.min(self.rows);
384 range.start.0 = range.start.0.min(range.end.0);
385 range.start.1 = range.start.1.min(range.end.1);
386 let cols = range.end.0 - range.start.0;
387 let rows = range.end.1 - range.start.1;
388 let result = (0..(cols * rows))
389 .map(|i| {
390 let col = range.start.0 + (i % cols);
391 let row = range.start.1 + (i / cols);
392 &self.cells[row * self.cols + col]
393 })
394 .collect::<Vec<_>>();
395 Grid2d::with_cells(cols, result)
396 }
397
398 pub fn get_view_seamless(&self, range: Range<(usize, usize)>) -> Grid2d<&T> {
399 let from_col = range.start.0.min(range.end.0);
400 let to_col = range.start.0.max(range.end.0);
401 let from_row = range.start.1.min(range.end.1);
402 let to_row = range.start.1.max(range.end.1);
403 let cols = to_col - from_col;
404 let rows = to_row - from_row;
405 let result = (0..(cols * rows))
406 .map(|i| {
407 let col = from_col + (i % cols);
408 let row = from_row + (i / cols);
409 let c = col % self.cols;
410 let r = row % self.rows;
411 &self.cells[r * self.cols + c]
412 })
413 .collect::<Vec<_>>();
414 Grid2d::with_cells(cols, result)
415 }
416
417 pub fn copy_sample(&self, (col, row): (usize, usize), margin: usize, result: &mut Self)
418 where
419 T: Default,
420 {
421 let min = (col.max(margin) - margin, row.max(margin) - margin);
422 let max = (col + margin + 1, row + margin + 1);
423 self.copy_part(min..max, result);
424 }
425
426 pub fn sample(&self, (col, row): (usize, usize), margin: usize) -> Self {
427 let min = (col.max(margin) - margin, row.max(margin) - margin);
428 let max = (col + margin + 1, row + margin + 1);
429 self.get_part(min..max)
430 }
431
432 pub fn sample_seamless(&self, (col, row): (usize, usize), margin: usize) -> Self {
433 let (cols, rows) = self.size();
434 let ox = (1 + margin / cols) * cols;
435 let oy = (1 + margin / rows) * rows;
436 let min = (col + ox - margin, row + oy - margin);
437 let max = (col + ox + margin + 1, row + oy + margin + 1);
438 self.get_part_seamless(min..max)
439 }
440
441 pub fn view_sample(&self, (col, row): (usize, usize), margin: usize) -> Grid2d<&T> {
442 let min = (col.max(margin) - margin, row.max(margin) - margin);
443 let max = (col + margin + 1, row + margin + 1);
444 self.get_view(min..max)
445 }
446
447 pub fn view_sample_seamless(&self, (col, row): (usize, usize), margin: usize) -> Grid2d<&T> {
448 let (cols, rows) = self.size();
449 let ox = (1 + margin / cols) * cols;
450 let oy = (1 + margin / rows) * rows;
451 let min = (col + ox - margin, row + oy - margin);
452 let max = (col + ox + margin + 1, row + oy + margin + 1);
453 self.get_view_seamless(min..max)
454 }
455
456 pub fn map<F, R>(&self, f: F) -> Grid2d<R>
457 where
458 F: FnMut(usize, usize, &T) -> R,
459 R: Clone + Send + Sync,
460 {
461 let cols = self.cols;
462 let mut f = f;
463 let cells = self
464 .cells
465 .iter()
466 .enumerate()
467 .map(|(i, v)| f(i % cols, i / cols, v))
468 .collect();
469 Grid2d::<R>::with_cells(cols, cells)
470 }
471
472 #[cfg(feature = "parallel")]
473 pub fn par_map<F, R>(&self, f: F) -> Grid2d<R>
474 where
475 F: FnMut(usize, usize, &T) -> R + Clone + Sync,
476 R: Clone + Send + Sync,
477 {
478 let cols = self.cols;
479 let cells = self
480 .cells
481 .par_iter()
482 .enumerate()
483 .map(|(i, v)| f.clone()(i % cols, i / cols, v))
484 .collect();
485 Grid2d::<R>::with_cells(cols, cells)
486 }
487
488 pub fn with<F>(&mut self, mut f: F)
489 where
490 F: FnMut(usize, usize, &T) -> T,
491 {
492 let cols = self.cols;
493 for (i, v) in self.cells.iter_mut().enumerate() {
494 *v = f(i % cols, i / cols, v);
495 }
496 }
497
498 #[cfg(feature = "parallel")]
499 pub fn par_with<F>(&mut self, f: F)
500 where
501 F: FnMut(usize, usize, &T) -> T + Clone + Sync,
502 {
503 let cols = self.cols;
504 self.cells.par_iter_mut().enumerate().for_each(|(i, v)| {
505 *v = f.clone()(i % cols, i / cols, v);
506 });
507 }
508
509 #[inline]
510 pub fn iter(&self) -> impl DoubleEndedIterator<Item = &T> {
511 self.cells.iter()
512 }
513
514 #[cfg(feature = "parallel")]
515 #[inline]
516 pub fn par_iter(&self) -> impl IndexedParallelIterator<Item = &T> {
517 self.cells.par_iter()
518 }
519
520 #[inline]
521 pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = &mut T> {
522 self.cells.iter_mut()
523 }
524
525 #[cfg(feature = "parallel")]
526 #[inline]
527 pub fn par_iter_mut(&mut self) -> impl IndexedParallelIterator<Item = &mut T> {
528 self.cells.par_iter_mut()
529 }
530
531 pub fn iter_view(
532 &self,
533 mut range: Range<(usize, usize)>,
534 ) -> impl DoubleEndedIterator<Item = (usize, usize, &T)> {
535 range.end.0 = range.end.0.min(self.cols);
536 range.end.1 = range.end.1.min(self.rows);
537 range.start.0 = range.start.0.min(range.end.0);
538 range.start.1 = range.start.1.min(range.end.1);
539 let cols = range.end.0 - range.start.0;
540 let rows = range.end.1 - range.start.1;
541 (0..(cols * rows)).map(move |i| {
542 let lc = i % cols;
543 let lr = i / cols;
544 let gc = range.start.0 + lc;
545 let gr = range.start.1 + lr;
546 (gc, gr, &self.cells[gr * self.cols + gc])
547 })
548 }
549
550 #[cfg(feature = "parallel")]
551 pub fn par_iter_view(
552 &self,
553 mut range: Range<(usize, usize)>,
554 ) -> impl IndexedParallelIterator<Item = (usize, usize, &T)> {
555 range.end.0 = range.end.0.min(self.cols);
556 range.end.1 = range.end.1.min(self.rows);
557 range.start.0 = range.start.0.min(range.end.0);
558 range.start.1 = range.start.1.min(range.end.1);
559 let cols = range.end.0 - range.start.0;
560 let rows = range.end.1 - range.start.1;
561 (0..(cols * rows)).into_par_iter().map(move |i| {
562 let lc = i % cols;
563 let lr = i / cols;
564 let gc = range.start.0 + lc;
565 let gr = range.start.1 + lr;
566 (gc, gr, &self.cells[gr * self.cols + gc])
567 })
568 }
569
570 pub fn iter_view_mut(
571 &mut self,
572 mut range: Range<(usize, usize)>,
573 ) -> impl DoubleEndedIterator<Item = (usize, usize, &mut T)> {
574 range.end.0 = range.end.0.min(self.cols);
575 range.end.1 = range.end.1.min(self.rows);
576 range.start.0 = range.start.0.min(range.end.0);
577 range.start.1 = range.start.1.min(range.end.1);
578 let cols = self.cols;
579 self.cells.iter_mut().enumerate().filter_map(move |(i, v)| {
580 let c = i % cols;
581 let r = i / cols;
582 if c >= range.start.0 && c < range.end.0 && r >= range.start.1 && r < range.end.1 {
583 Some((c, r, v))
584 } else {
585 None
586 }
587 })
588 }
589
590 pub fn iter_sample(
591 &self,
592 mut range: Range<(usize, usize)>,
593 margin: usize,
594 ) -> impl DoubleEndedIterator<Item = (usize, usize, Grid2d<&T>)> + '_ {
595 range.end.0 = range.end.0.min(self.cols);
596 range.end.1 = range.end.1.min(self.rows);
597 range.start.0 = range.start.0.min(range.end.0);
598 range.start.1 = range.start.1.min(range.end.1);
599 let cols = range.end.0 - range.start.0;
600 let rows = range.end.1 - range.start.1;
601 (0..(cols * rows)).map(move |i| {
602 let lc = i % cols;
603 let lr = i / cols;
604 let gc = range.start.0 + lc;
605 let gr = range.start.1 + lr;
606 (gc, gr, self.view_sample((gc, gr), margin))
607 })
608 }
609
610 pub fn neighbor_sample(&self, (col, row): (usize, usize)) -> Grid2dNeighborSample<T>
611 where
612 T: Default + Copy,
613 {
614 let min = (col.max(1) - 1, row.max(1) - 1);
615 let max = ((col + 2).min(self.cols), (row + 2).min(self.rows));
616 let cols = max.0 - min.0;
617 let rows = max.1 - min.1;
618 let mut cells = [T::default(); 9];
619 let mut index = 0;
620 for row in min.1..max.1 {
621 for col in min.0..max.0 {
622 cells[index] = self.cells[row * self.cols + col];
623 index += 1;
624 }
625 }
626 Grid2dNeighborSample { cells, cols, rows }
627 }
628
629 pub fn windows(
630 &self,
631 (cols, rows): (usize, usize),
632 ) -> impl DoubleEndedIterator<Item = Grid2d<&T>> {
633 let cols = cols.min(self.cols);
634 let rows = rows.min(self.rows);
635 (0..(self.rows - rows + 1)).flat_map(move |row| {
636 (0..(self.cols - cols + 1))
637 .map(move |col| self.get_view((col, row)..(col + cols, row + rows)))
638 })
639 }
640
641 #[cfg(feature = "parallel")]
642 pub fn par_windows(
643 &self,
644 (cols, rows): (usize, usize),
645 ) -> impl ParallelIterator<Item = Grid2d<&T>> {
646 let cols = cols.min(self.cols);
647 let rows = rows.min(self.rows);
648 (0..(self.rows - rows + 1))
649 .into_par_iter()
650 .flat_map(move |row| {
651 (0..(self.cols - cols + 1))
652 .into_par_iter()
653 .map(move |col| self.get_view((col, row)..(col + cols, row + rows)))
654 })
655 }
656
657 pub fn windows_seamless(
658 &self,
659 (cols, rows): (usize, usize),
660 ) -> impl DoubleEndedIterator<Item = Grid2d<&T>> {
661 (0..self.rows).flat_map(move |row| {
662 (0..self.cols)
663 .map(move |col| self.get_view_seamless((col, row)..(col + cols, row + rows)))
664 })
665 }
666
667 #[cfg(feature = "parallel")]
668 pub fn par_windows_seamless(
669 &self,
670 (cols, rows): (usize, usize),
671 ) -> impl ParallelIterator<Item = Grid2d<&T>> {
672 (0..self.rows).into_par_iter().flat_map(move |row| {
673 (0..self.cols)
674 .into_par_iter()
675 .map(move |col| self.get_view_seamless((col, row)..(col + cols, row + rows)))
676 })
677 }
678
679 pub fn into_inner(self) -> (usize, usize, Vec<T>) {
680 (self.cols, self.rows, self.cells)
681 }
682
683 pub fn from_view(view: &Grid2d<&T>) -> Self {
684 Self::with_cells(
685 view.cols(),
686 view.iter().map(|c| (*c).clone()).collect::<Vec<T>>(),
687 )
688 }
689
690 pub fn get_common_areas(
691 first_size: (usize, usize),
692 second_size: (usize, usize),
693 second_offset: (usize, usize),
694 ) -> Option<Grid2dCommonAreas> {
695 let (cols, rows) = first_size;
696 let (other_cols, other_rows) = second_size;
697 let (offset_col, offset_row) = second_offset;
698 if offset_col >= cols || offset_row >= rows {
699 return None;
700 }
701 let common_cols = {
702 let a = cols - offset_col;
703 let b = other_cols;
704 a.min(b)
705 };
706 let common_rows = {
707 let a = rows - offset_row;
708 let b = other_rows;
709 a.min(b)
710 };
711 let a = (offset_col, offset_row)..(offset_col + common_cols, offset_row + common_rows);
712 let b = (0, 0)..(common_cols, common_rows);
713 Some((a, b))
714 }
715
716 pub fn access_decoupled<'a>(
717 &'a self,
718 read: &[(usize, usize)],
719 write: &[(usize, usize)],
720 reads: &mut [&'a T],
721 writes: &mut [&'a mut T],
722 ) -> Result<(), Grid2dError> {
723 for i in 0..read.len() {
724 let coord = read[i];
725 if read[(i + 1)..].contains(&coord) {
726 return Err(Grid2dError::DuplicatedCoord(coord.0, coord.1));
727 }
728 }
729 for i in 0..write.len() {
730 let coord = write[i];
731 if write[(i + 1)..].contains(&coord) {
732 return Err(Grid2dError::DuplicatedCoord(coord.0, coord.1));
733 }
734 }
735 for coord in read {
736 if write.contains(coord) {
737 return Err(Grid2dError::TryingToReadFromAndWriteToSameLocation(
738 coord.0, coord.1,
739 ));
740 }
741 }
742 unsafe { self.access_decoupled_unsafe(read, write, reads, writes) }
743 }
744
745 #[allow(clippy::missing_safety_doc)]
746 pub unsafe fn access_decoupled_unsafe<'a>(
747 &'a self,
748 read: &[(usize, usize)],
749 write: &[(usize, usize)],
750 reads: &mut [&'a T],
751 writes: &mut [&'a mut T],
752 ) -> Result<(), Grid2dError> {
753 if read.len() != reads.len() {
754 return Err(Grid2dError::InputAndOutputBuffersHaveDifferentSizeForReads(
755 read.len(),
756 reads.len(),
757 ));
758 }
759 if write.len() != writes.len() {
760 return Err(
761 Grid2dError::InputAndOutputBuffersHaveDifferentSizeForWrites(
762 write.len(),
763 writes.len(),
764 ),
765 );
766 }
767 for i in 0..read.len() {
768 let (col, row) = read[i];
769 reads[i] = self.cell(col, row).unwrap();
770 }
771 for i in 0..write.len() {
772 #[allow(mutable_transmutes)]
773 #[allow(clippy::transmute_ptr_to_ptr)]
774 {
775 let (col, row) = write[i];
776 writes[i] = std::mem::transmute(self.cell(col, row).unwrap());
777 }
778 }
779 Ok(())
780 }
781}
782
783impl<T> Grid2d<T>
784where
785 T: Clone + Send + Sync + PartialEq,
786{
787 pub fn has_union_with(&self, other: &Self, offset_col: usize, offset_row: usize) -> bool {
788 if self.cells.is_empty() || other.cells.is_empty() {
789 return false;
790 }
791 if let Some((a, b)) =
792 Self::get_common_areas(self.size(), other.size(), (offset_col, offset_row))
793 {
794 let view = self.get_view(a);
795 let other_view = other.get_view(b);
796 if view.size() == other_view.size() {
797 return !view.iter().zip(other_view.iter()).any(|(a, b)| a != b);
798 }
799 }
800 false
801 }
802}
803
804impl<T> PartialEq for Grid2d<T>
805where
806 T: PartialEq,
807{
808 fn eq(&self, other: &Self) -> bool {
809 self.cols == other.cols && self.rows == other.rows && self.cells == other.cells
810 }
811}
812
813impl<T> Index<(usize, usize)> for Grid2d<T>
814where
815 T: Clone + Send + Sync,
816{
817 type Output = T;
818
819 fn index(&self, (col, row): (usize, usize)) -> &T {
820 self.cell(col, row).unwrap()
821 }
822}
823
824impl<T> Index<[usize; 2]> for Grid2d<T>
825where
826 T: Clone + Send + Sync,
827{
828 type Output = T;
829
830 fn index(&self, [col, row]: [usize; 2]) -> &T {
831 self.cell(col, row).unwrap()
832 }
833}
834
835impl<T> IndexMut<(usize, usize)> for Grid2d<T>
836where
837 T: Clone + Send + Sync,
838{
839 fn index_mut(&mut self, (col, row): (usize, usize)) -> &mut T {
840 self.cell_mut(col, row).unwrap()
841 }
842}
843
844impl<T> IndexMut<[usize; 2]> for Grid2d<T>
845where
846 T: Clone + Send + Sync,
847{
848 fn index_mut(&mut self, [col, row]: [usize; 2]) -> &mut T {
849 self.cell_mut(col, row).unwrap()
850 }
851}
852
853impl<T> Add for &Grid2d<T>
854where
855 T: Clone + Send + Sync + Add<Output = T>,
856{
857 type Output = Result<Grid2d<T>, Grid2dError>;
858
859 fn add(self, other: &Grid2d<T>) -> Self::Output {
860 if self.cols() == other.cols() && self.rows() == other.rows() {
861 let cells = self
862 .iter()
863 .zip(other.iter())
864 .map(|(a, b)| a.clone() + b.clone())
865 .collect::<Vec<T>>();
866 Ok(Grid2d::with_cells(self.cols(), cells))
867 } else {
868 Err(Grid2dError::DifferentDimensions(
869 (self.cols(), self.rows()),
870 (other.cols(), other.rows()),
871 ))
872 }
873 }
874}
875
876impl<T> Sub for &Grid2d<T>
877where
878 T: Clone + Send + Sync + Sub<Output = T>,
879{
880 type Output = Result<Grid2d<T>, Grid2dError>;
881
882 fn sub(self, other: &Grid2d<T>) -> Self::Output {
883 if self.cols() == other.cols() && self.rows() == other.rows() {
884 let cells = self
885 .iter()
886 .zip(other.iter())
887 .map(|(a, b)| a.clone() - b.clone())
888 .collect::<Vec<T>>();
889 Ok(Grid2d::with_cells(self.cols(), cells))
890 } else {
891 Err(Grid2dError::DifferentDimensions(
892 (self.cols(), self.rows()),
893 (other.cols(), other.rows()),
894 ))
895 }
896 }
897}
898
899impl<T> Mul for &Grid2d<T>
900where
901 T: Clone + Send + Sync + Mul<Output = T>,
902{
903 type Output = Result<Grid2d<T>, Grid2dError>;
904
905 fn mul(self, other: &Grid2d<T>) -> Self::Output {
906 if self.cols() == other.cols() && self.rows() == other.rows() {
907 let cells = self
908 .iter()
909 .zip(other.iter())
910 .map(|(a, b)| a.clone() * b.clone())
911 .collect::<Vec<T>>();
912 Ok(Grid2d::with_cells(self.cols(), cells))
913 } else {
914 Err(Grid2dError::DifferentDimensions(
915 (self.cols(), self.rows()),
916 (other.cols(), other.rows()),
917 ))
918 }
919 }
920}
921
922impl<T> Div for &Grid2d<T>
923where
924 T: Clone + Send + Sync + Div<Output = T>,
925{
926 type Output = Result<Grid2d<T>, Grid2dError>;
927
928 fn div(self, other: &Grid2d<T>) -> Self::Output {
929 if self.cols() == other.cols() && self.rows() == other.rows() {
930 let cells = self
931 .iter()
932 .zip(other.iter())
933 .map(|(a, b)| a.clone() / b.clone())
934 .collect::<Vec<T>>();
935 Ok(Grid2d::with_cells(self.cols(), cells))
936 } else {
937 Err(Grid2dError::DifferentDimensions(
938 (self.cols(), self.rows()),
939 (other.cols(), other.rows()),
940 ))
941 }
942 }
943}
944
945impl<T> Neg for &Grid2d<T>
946where
947 T: Clone + Send + Sync + Neg<Output = T>,
948{
949 type Output = Grid2d<T>;
950
951 fn neg(self) -> Self::Output {
952 let cells = self.iter().map(|v| -v.clone()).collect::<Vec<T>>();
953 Grid2d::with_cells(self.cols(), cells)
954 }
955}
956
957impl<T> IntoIterator for Grid2d<T>
958where
959 T: Clone + Send + Sync,
960{
961 type Item = T;
962 type IntoIter = std::vec::IntoIter<T>;
963
964 fn into_iter(self) -> Self::IntoIter {
965 self.cells.into_iter()
966 }
967}
968
969#[cfg(feature = "parallel")]
970impl<T> IntoParallelIterator for Grid2d<T>
971where
972 T: Clone + Send + Sync,
973{
974 type Item = T;
975 type Iter = rayon::vec::IntoIter<T>;
976
977 fn into_par_iter(self) -> Self::Iter {
978 self.cells.into_par_iter()
979 }
980}
981
982impl<I, T> From<(usize, I)> for Grid2d<T>
983where
984 I: Iterator<Item = T>,
985 T: Clone + Send + Sync,
986{
987 fn from((cols, iter): (usize, I)) -> Self {
988 Self::with_cells(cols, iter.collect::<Vec<T>>())
989 }
990}
991
992impl<T> From<Grid2d<T>> for Vec<T> {
993 fn from(v: Grid2d<T>) -> Self {
994 v.cells
995 }
996}
997
998impl<T> From<Grid2d<T>> for (usize, usize, Vec<T>)
999where
1000 T: Clone + Send + Sync,
1001{
1002 fn from(v: Grid2d<T>) -> Self {
1003 v.into_inner()
1004 }
1005}