oxygengine_utils/
grid_2d.rs

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    /// (input size, output size)
14    InputAndOutputBuffersHaveDifferentSizeForReads(usize, usize),
15    /// (input size, output size)
16    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}