building_blocks_storage/
array.rs

1//! N-dimensional arrays, where N is 2 or 3.
2//!
3//! The domains of all arrays are located within an ambient space, a signed integer lattice where the elements are `Point2i` or
4//! `Point3i`. This means they contain data at exactly the set of points in an `ExtentN`, and no more.
5//!
6//! # Indexing
7//!
8//! You can index an array with 3 kinds of coordinates, with [`Get`](crate::access_traits) traits:
9//!   - `Get*<Stride>`: flat array offset
10//!   - `Get*<Local<N>>`: N-dimensional point in extent-local coordinates (i.e. min = `[0, 0, 0]`)
11//!   - `Get*<PointN<N>>`: N-dimensional point in global (ambient) coordinates
12//!
13//! Indexing assumes that the coordinates are in-bounds of the array, panicking otherwise. Bounds checking is only enabled in
14//! debug mode.
15//!
16//! # Iteration
17//!
18//! Arrays also support fast iteration over extents with `ForEach*` trait impls. These methods will only iterate over the
19//! section of the extent which is in-bounds of the array, so it's impossible to index out of bounds.
20//!
21//! ```
22//! use building_blocks_core::prelude::*;
23//! use building_blocks_storage::prelude::*;
24//!
25//! let array_extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(64));
26//! let mut array = Array3x1::fill(array_extent, 0);
27//!
28//! // Write all points in the extent to the same value.
29//! let write_extent = Extent3i::from_min_and_lub(Point3i::fill(10), Point3i::fill(20));
30//! array.for_each_mut(&write_extent, |_: (), value| *value = 1);
31//!
32//! // Only the points in the extent should have been written.
33//! array.for_each(array.extent(), |p: Point3i, value|
34//!     if write_extent.contains(p) {
35//!         assert_eq!(value, 1);
36//!     } else {
37//!         assert_eq!(value, 0);
38//!     }
39//! );
40//! ```
41//!
42//! # Strides
43//!
44//! Since `Stride` lookups are fast and linear, they are ideal for kernel-based algorithms (like edge/surface detection). Use
45//! the `ForEach*<N, Stride>` traits to iterate over an extent and use the linearity of `Stride` to access adjacent points.
46//! ```
47//! # use building_blocks_core::prelude::*;
48//! # use building_blocks_storage::prelude::*;
49//! # let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(64));
50//! // Use a more interesting data set, just to show off this constructor.
51//! let mut array = Array3x1::fill_with(extent, |p| if p.x() % 2 == 0 { 1 } else { 0 });
52//!
53//! let subextent = Extent3i::from_min_and_shape(Point3i::fill(1), Point3i::fill(62));
54//!
55//! // Some of these offsets include negative coordinates, which would underflow when translated
56//! // into an unsigned index. That's OK though, because Stride is intended to be used with modular
57//! // arithmetic.
58//! let offsets = Local::localize_points_array(&Point3i::VON_NEUMANN_OFFSETS);
59//! let mut neighbor_strides = [Stride(0); 6];
60//! array.strides_from_local_points(&offsets, &mut neighbor_strides);
61//!
62//! // Sum up the values in the Von Neumann neighborhood of each point, acting as a sort of blur
63//! // filter.
64//! array.for_each(&subextent, |stride: Stride, value| {
65//!     let mut neighborhood_sum = value;
66//!     for offset in neighbor_strides.iter() {
67//!         let adjacent_value = array.get(stride + *offset);
68//!         neighborhood_sum += adjacent_value;
69//!     }
70//! });
71//! ```
72//! This means you keep the performance of simple array indexing, as opposed to indexing with a `Point3i`, which requires 2
73//! multiplications to convert to a `Stride`. You'd be surprised how important this difference can be in tight loops.
74//!
75//! # Storage
76//!
77//! By default, `Array` uses a `Vec` to store elements. But any type that implements `Deref<Target = [T]>` or `DerefMut<Target =
78//! [T]>` should be usable. This means you can construct an array with most pointer types.
79//!
80//! ```
81//! # use building_blocks_core::prelude::*;
82//! # use building_blocks_storage::prelude::*;
83//! # let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(32));
84//! // Borrow `array`'s values for the lifetime of `other_array`.
85//! let array = Array3x1::fill(extent, 1);
86//! let other_array = Array3x1::new_one_channel(extent, array.channels().store().as_slice());
87//! assert_eq!(other_array.get(Stride(0)), 1);
88//!
89//! // A stack-allocated array.
90//! let mut data = [1; 32 * 32 * 32];
91//! let mut stack_array = Array3x1::new_one_channel(extent, &mut data[..]);
92//! *stack_array.get_mut(Stride(0)) = 2;
93//! assert_eq!(data[0], 2);
94//!
95//! // A boxed array.
96//! let data: Box<[u32]> = Box::new([1; 32 * 32 * 32]); // must forget the size
97//! let box_array = Array3x1::new_one_channel(extent, data);
98//! box_array.for_each(&extent, |p: Point3i, value| assert_eq!(value, 1));
99//! ```
100//!
101//! # Multichannel
102//!
103//! It's often the case that you have multiple data types to store per spatial dimension. For example, you might store geometry
104//! data like `Sd8` as well as a voxel type identifier. While you can put these in a struct, that may not be the most efficient
105//! option. If you only need access to one of those fields of the struct for a particular algorithm, then you will needlessly
106//! load the entire struct into cache. To avoid this problem, `Array` supports storing multiple data "channels" in
107//! structure-of-arrays (SoA) style.
108//!
109//! ```
110//! # use building_blocks_core::prelude::*;
111//! # use building_blocks_storage::{prelude::*};
112//! # let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
113//! #
114//! #[derive(Clone, Copy, Debug, Eq, PartialEq)]
115//! struct VoxelId(u8);
116//!
117//! // This means 3D with 2 channels. Although we pass in a tuple, the two data
118//! // types are internally stored in separate arrays.
119//! let mut array = Array3x2::fill(extent, (VoxelId(0), 1.0));
120//!
121//! // This array supports all of the usual access traits and maps the channels
122//! // to tuples as you would expect.
123//! let p = Point3i::fill(1);
124//! assert_eq!(array.get(p), (VoxelId(0), 1.0));
125//! assert_eq!(array.get_ref(p), (&VoxelId(0), &1.0));
126//! assert_eq!(array.get_mut(p), (&mut VoxelId(0), &mut 1.0));
127//!
128//! // Here we choose to access just one channel, and there is no performance penalty.
129//! array.borrow_channels_mut(|(_id, dist)| dist).for_each_mut(&extent, |p: Point3i, dist| {
130//!     let r = p.dot(p);
131//!     *dist = (r as f32).sqrt();
132//! });
133//!
134//! // And if we want to copy just one of those channels into another map, we can
135//! // create a new array that borrows just one of the channels.
136//! let mut dst = Array3x1::fill(extent, 0.0);
137//! let src = array.borrow_channels(|(_id, dist)| dist);
138//! copy_extent(&extent, &src, &mut dst);
139//! ```
140
141mod coords;
142#[macro_use]
143mod for_each;
144mod indexer;
145
146pub mod channels;
147pub mod compression;
148
149#[cfg(feature = "dot_vox")]
150mod dot_vox_conversions;
151#[cfg(feature = "image")]
152mod image_conversions;
153
154pub use channels::*;
155pub use compression::*;
156pub use coords::*;
157pub use for_each::*;
158pub use indexer::*;
159
160use crate::{
161    ChunkCopySrc, FillExtent, ForEach, ForEachMut, ForEachMutPtr, Get, GetMut, GetMutPtr, GetRef,
162    IntoMultiMut, IntoMultiMutPtr, MultiMutPtr, ReadExtent, TransformMap, WriteExtent,
163};
164
165use building_blocks_core::prelude::*;
166
167use core::iter::{once, Once};
168use core::ops::{Add, Deref};
169use either::Either;
170use serde::{Deserialize, Serialize};
171
172/// A map from lattice location `PointN<N>` to data `T`, stored as a flat array.
173#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
174pub struct Array<N, Chan> {
175    channels: Chan,
176    extent: ExtentN<N>,
177}
178
179macro_rules! array_n_type_alias {
180    ($name:ident, $( $chan:ident : $store:ident ),+ ) => {
181        pub type $name<N, $( $chan ),+, $( $store = Vec<$chan> ),+> = Array<N, ($( Channel<$chan, $store> ),+)>;
182    };
183}
184
185macro_rules! array_type_alias {
186    ($name:ident, $dim:ty, $( $chan:ident : $store:ident ),+ ) => {
187        pub type $name<$( $chan ),+, $( $store = Vec<$chan> ),+> = Array<$dim, ($( Channel<$chan, $store> ),+)>;
188    };
189}
190
191pub type ArrayNx1<N, A, S1 = Vec<A>> = Array<N, Channel<A, S1>>;
192array_n_type_alias!(ArrayNx2, A: S1, B: S2);
193array_n_type_alias!(ArrayNx3, A: S1, B: S2, C: S3);
194array_n_type_alias!(ArrayNx4, A: S1, B: S2, C: S3, D: S4);
195array_n_type_alias!(ArrayNx5, A: S1, B: S2, C: S3, D: S4, E: S5);
196array_n_type_alias!(ArrayNx6, A: S1, B: S2, C: S3, D: S4, E: S5, F: S6);
197
198pub mod multichannel_aliases {
199    use super::*;
200
201    pub type Array2x1<A, S1 = Vec<A>> = Array<[i32; 2], Channel<A, S1>>;
202    array_type_alias!(Array2x2, [i32; 2], A: S1, B: S2);
203    array_type_alias!(Array2x3, [i32; 2], A: S1, B: S2, C: S3);
204    array_type_alias!(Array2x4, [i32; 2], A: S1, B: S2, C: S3, D: S4);
205    array_type_alias!(Array2x5, [i32; 2], A: S1, B: S2, C: S3, D: S4, E: S5);
206    array_type_alias!(Array2x6, [i32; 2], A: S1, B: S2, C: S3, D: S4, E: S5, F: S6);
207
208    pub type Array3x1<A, S1 = Vec<A>> = Array<[i32; 3], Channel<A, S1>>;
209    array_type_alias!(Array3x2, [i32; 3], A: S1, B: S2);
210    array_type_alias!(Array3x3, [i32; 3], A: S1, B: S2, C: S3);
211    array_type_alias!(Array3x4, [i32; 3], A: S1, B: S2, C: S3, D: S4);
212    array_type_alias!(Array3x5, [i32; 3], A: S1, B: S2, C: S3, D: S4, E: S5);
213    array_type_alias!(Array3x6, [i32; 3], A: S1, B: S2, C: S3, D: S4, E: S5, F: S6);
214}
215
216pub use multichannel_aliases::*;
217
218impl<N, Chan> Array<N, Chan> {
219    /// Create a new `Array` directly from the extent and values. This asserts that the number of points in the extent matches
220    /// the length of the values `Vec`.
221    pub fn new(extent: ExtentN<N>, channels: Chan) -> Self {
222        // TODO: assert that channels has length matching extent
223        Self { channels, extent }
224    }
225
226    /// Moves the raw extent and values storage out of `self`.
227    #[inline]
228    pub fn into_parts(self) -> (ExtentN<N>, Chan) {
229        (self.extent, self.channels)
230    }
231
232    #[inline]
233    pub fn extent(&self) -> &ExtentN<N> {
234        &self.extent
235    }
236
237    #[inline]
238    pub fn channels(&self) -> &Chan {
239        &self.channels
240    }
241
242    #[inline]
243    pub fn channels_mut(&mut self) -> &mut Chan {
244        &mut self.channels
245    }
246}
247
248impl<N, Chan> IndexedArray<N> for Array<N, Chan>
249where
250    N: ArrayIndexer<N>,
251{
252    type Indexer = N;
253
254    #[inline]
255    fn extent(&self) -> &ExtentN<N> {
256        self.extent()
257    }
258}
259
260impl<N, Chan> Array<N, Chan>
261where
262    PointN<N>: IntegerPoint<N>,
263{
264    /// Creates a new `Array` from the return value of `selector`. `selector` takes a tuple of `Channel`s that borrow their
265    /// storage.
266    #[inline]
267    pub fn borrow_channels<'a, NewChan>(
268        &'a self,
269        selector: impl Fn(Chan::Borrowed) -> NewChan,
270    ) -> Array<N, NewChan>
271    where
272        Chan: BorrowChannels<'a>,
273    {
274        Array::new(self.extent, selector(self.channels().borrow()))
275    }
276
277    /// Creates a new `Array` from the return value of `selector`. `selector` takes a tuple of `Channel`s that mutably borrow
278    /// their storage.
279    #[inline]
280    pub fn borrow_channels_mut<'a, NewChan>(
281        &'a mut self,
282        selector: impl Fn(Chan::Borrowed) -> NewChan,
283    ) -> Array<N, NewChan>
284    where
285        Chan: BorrowChannelsMut<'a>,
286    {
287        Array::new(self.extent, selector(self.channels_mut().borrow_mut()))
288    }
289
290    /// Sets the extent minimum to `p`. This doesn't change the shape of the extent.
291    #[inline]
292    pub fn set_minimum(&mut self, p: PointN<N>) {
293        self.extent.minimum = p;
294    }
295
296    /// Adds `p` to the extent minimum.
297    #[inline]
298    pub fn translate(&mut self, p: PointN<N>) {
299        self.extent = self.extent.add(p);
300    }
301
302    /// Returns `true` iff this map contains point `p`.
303    #[inline]
304    pub fn contains(&self, p: PointN<N>) -> bool {
305        self.extent.contains(p)
306    }
307}
308
309impl<N, Chan> FillExtent<N> for Array<N, Chan>
310where
311    Self: ForEachMutPtr<N, (), Item = Chan::Ptr>,
312    PointN<N>: IntegerPoint<N>,
313    Chan: ResetChannels,
314    Chan::Data: Clone,
315{
316    type Item = Chan::Data;
317
318    /// Fill the entire `extent` with the same `value`.
319    fn fill_extent(&mut self, extent: &ExtentN<N>, value: Self::Item) {
320        if self.extent.eq(extent) {
321            self.channels.reset_values(value);
322        } else {
323            unsafe {
324                self.for_each_mut_ptr(extent, |_: (), v| v.write(value.clone()));
325            }
326        }
327    }
328}
329
330impl<N, Chan> Array<N, Chan>
331where
332    Chan: ResetChannels,
333{
334    /// Set all points to the same value.
335    #[inline]
336    pub fn reset_values(&mut self, value: Chan::Data)
337    where
338        Chan::Data: Clone,
339    {
340        self.channels.reset_values(value);
341    }
342}
343
344impl<N, Chan> Array<N, Chan>
345where
346    PointN<N>: IntegerPoint<N>,
347    Chan: FillChannels,
348{
349    /// Creates a map that fills the entire `extent` with the same `value`.
350    pub fn fill(extent: ExtentN<N>, value: Chan::Data) -> Self
351    where
352        Chan::Data: Clone,
353    {
354        Self::new(extent, Chan::fill(value, extent.num_points()))
355    }
356}
357
358impl<N, Chan, UninitChan> Array<N, Chan>
359where
360    Array<N, UninitChan>: ForEachMutPtr<N, PointN<N>, Item = UninitChan::Ptr>,
361    PointN<N>: IntegerPoint<N>,
362    Chan: Channels<UninitSelf = UninitChan>,
363    UninitChan: UninitChannels<InitSelf = Chan>,
364    UninitChan::Ptr: IntoMultiMutPtr<Data = Chan::Data>,
365{
366    /// Create a new array for `extent` where each point's value is determined by the `filler` function.
367    pub fn fill_with(extent: ExtentN<N>, mut filler: impl FnMut(PointN<N>) -> Chan::Data) -> Self {
368        unsafe {
369            let mut array = Array::<_, UninitChan>::maybe_uninit(extent);
370
371            array.for_each_mut_ptr(&extent, |p, val| {
372                val.into_multi_mut_ptr().write(filler(p));
373            });
374
375            array.assume_init()
376        }
377    }
378}
379
380impl<N, Chan> Array<N, Chan>
381where
382    PointN<N>: IntegerPoint<N>,
383    Chan: UninitChannels,
384{
385    /// Creates an uninitialized map, mainly for performance.
386    /// # Safety
387    /// Call `assume_init` after manually initializing all of the values.
388    pub unsafe fn maybe_uninit(extent: ExtentN<N>) -> Array<N, Chan> {
389        Array::new(extent, Chan::maybe_uninit(extent.num_points()))
390    }
391
392    /// Transmutes the map values from `MaybeUninit<T>` to `T` after manual initialization. The implementation just reconstructs
393    /// the internal `Vec` after transmuting the data pointer, so the overhead is minimal.
394    /// # Safety
395    /// All elements of the map must be initialized.
396    pub unsafe fn assume_init(self) -> Array<N, Chan::InitSelf> {
397        let (extent, channel) = self.into_parts();
398
399        Array::new(extent, channel.assume_init())
400    }
401}
402
403impl<N, T, Store> ArrayNx1<N, T, Store>
404where
405    PointN<N>: IntegerPoint<N>,
406    Store: Deref<Target = [T]>,
407{
408    pub fn new_one_channel(extent: ExtentN<N>, values: Store) -> Self {
409        assert_eq!(extent.num_points(), values.len());
410
411        Self::new(extent, Channel::new(values))
412    }
413}
414
415//  ██████╗ ███████╗████████╗████████╗███████╗██████╗ ███████╗
416// ██╔════╝ ██╔════╝╚══██╔══╝╚══██╔══╝██╔════╝██╔══██╗██╔════╝
417// ██║  ███╗█████╗     ██║      ██║   █████╗  ██████╔╝███████╗
418// ██║   ██║██╔══╝     ██║      ██║   ██╔══╝  ██╔══██╗╚════██║
419// ╚██████╔╝███████╗   ██║      ██║   ███████╗██║  ██║███████║
420//  ╚═════╝ ╚══════╝   ╚═╝      ╚═╝   ╚══════╝╚═╝  ╚═╝╚══════╝
421
422impl<N, Chan> Get<Stride> for Array<N, Chan>
423where
424    Chan: Get<usize>,
425{
426    type Item = Chan::Item;
427
428    #[inline]
429    fn get(&self, stride: Stride) -> Self::Item {
430        self.channels.get(stride.0)
431    }
432}
433
434impl<'a, N, Chan> GetRef<'a, Stride> for Array<N, Chan>
435where
436    Chan: GetRef<'a, usize>,
437{
438    type Item = Chan::Item;
439
440    #[inline]
441    fn get_ref(&'a self, stride: Stride) -> Self::Item {
442        self.channels.get_ref(stride.0)
443    }
444}
445
446impl<'a, N, Chan> GetMut<'a, Stride> for Array<N, Chan>
447where
448    Chan: GetMut<'a, usize>,
449{
450    type Item = Chan::Item;
451
452    #[inline]
453    fn get_mut(&'a mut self, stride: Stride) -> Self::Item {
454        self.channels.get_mut(stride.0)
455    }
456}
457
458impl<N, Chan> GetMutPtr<Stride> for Array<N, Chan>
459where
460    Chan: GetMutPtr<usize>,
461{
462    type Item = Chan::Item;
463
464    #[inline]
465    unsafe fn get_mut_ptr(&mut self, stride: Stride) -> Self::Item {
466        self.channels.get_mut_ptr(stride.0)
467    }
468}
469
470impl<N, Chan> Get<Local<N>> for Array<N, Chan>
471where
472    Self: IndexedArray<N> + Get<Stride>,
473    PointN<N>: Copy,
474{
475    type Item = <Self as Get<Stride>>::Item;
476
477    #[inline]
478    fn get(&self, p: Local<N>) -> Self::Item {
479        self.get(self.stride_from_local_point(p))
480    }
481}
482
483impl<'a, N, Chan> GetRef<'a, Local<N>> for Array<N, Chan>
484where
485    Self: IndexedArray<N> + GetRef<'a, Stride>,
486    PointN<N>: Copy,
487{
488    type Item = <Self as GetRef<'a, Stride>>::Item;
489
490    #[inline]
491    fn get_ref(&'a self, p: Local<N>) -> Self::Item {
492        self.get_ref(self.stride_from_local_point(p))
493    }
494}
495
496impl<'a, N, Chan> GetMut<'a, Local<N>> for Array<N, Chan>
497where
498    Self: IndexedArray<N> + GetMut<'a, Stride>,
499    PointN<N>: Copy,
500{
501    type Item = <Self as GetMut<'a, Stride>>::Item;
502
503    #[inline]
504    fn get_mut(&'a mut self, p: Local<N>) -> Self::Item {
505        self.get_mut(self.stride_from_local_point(p))
506    }
507}
508
509impl<N, Chan> Get<PointN<N>> for Array<N, Chan>
510where
511    Self: IndexedArray<N> + Get<Local<N>>,
512    PointN<N>: Point,
513{
514    type Item = <Self as Get<Local<N>>>::Item;
515
516    #[inline]
517    fn get(&self, p: PointN<N>) -> Self::Item {
518        let local_p = p - self.extent().minimum;
519
520        self.get(Local(local_p))
521    }
522}
523
524impl<'a, N, Chan> GetRef<'a, PointN<N>> for Array<N, Chan>
525where
526    Self: IndexedArray<N> + GetRef<'a, Local<N>>,
527    PointN<N>: Point,
528{
529    type Item = <Self as GetRef<'a, Local<N>>>::Item;
530
531    #[inline]
532    fn get_ref(&'a self, p: PointN<N>) -> Self::Item {
533        let local_p = p - self.extent().minimum;
534
535        self.get_ref(Local(local_p))
536    }
537}
538
539impl<'a, N, Chan> GetMut<'a, PointN<N>> for Array<N, Chan>
540where
541    Self: IndexedArray<N> + GetMut<'a, Local<N>>,
542    PointN<N>: Point,
543{
544    type Item = <Self as GetMut<'a, Local<N>>>::Item;
545
546    #[inline]
547    fn get_mut(&'a mut self, p: PointN<N>) -> Self::Item {
548        let local_p = p - self.extent().minimum;
549
550        self.get_mut(Local(local_p))
551    }
552}
553
554// ███████╗ ██████╗ ██████╗     ███████╗ █████╗  ██████╗██╗  ██╗
555// ██╔════╝██╔═══██╗██╔══██╗    ██╔════╝██╔══██╗██╔════╝██║  ██║
556// █████╗  ██║   ██║██████╔╝    █████╗  ███████║██║     ███████║
557// ██╔══╝  ██║   ██║██╔══██╗    ██╔══╝  ██╔══██║██║     ██╔══██║
558// ██║     ╚██████╔╝██║  ██║    ███████╗██║  ██║╚██████╗██║  ██║
559// ╚═╝      ╚═════╝ ╚═╝  ╚═╝    ╚══════╝╚═╝  ╚═╝ ╚═════╝╚═╝  ╚═╝
560
561macro_rules! impl_array_for_each {
562    (coords: $coords:ty; forwarder = |$p:ident, $stride:ident| $forward_coords:expr;) => {
563        impl<N, Chan> ForEach<N, $coords> for Array<N, Chan>
564        where
565            Self: Get<Stride>,
566            N: ArrayIndexer<N>,
567            PointN<N>: IntegerPoint<N>,
568        {
569            type Item = <Self as Get<Stride>>::Item;
570
571            #[inline]
572            fn for_each(&self, iter_extent: &ExtentN<N>, mut f: impl FnMut($coords, Self::Item)) {
573                let visitor = ArrayForEach::new_global(*self.extent(), *iter_extent);
574                visitor.for_each(|$p, $stride| f($forward_coords, self.get($stride)));
575            }
576        }
577
578        impl<'a, N, Chan> ForEachMutPtr<N, $coords> for Array<N, Chan>
579        where
580            Self: GetMutPtr<Stride, Item = Chan::Ptr>,
581            N: ArrayIndexer<N>,
582            PointN<N>: IntegerPoint<N>,
583            Chan: Channels,
584        {
585            type Item = Chan::Ptr;
586
587            #[inline]
588            unsafe fn for_each_mut_ptr(
589                &mut self,
590                iter_extent: &ExtentN<N>,
591                mut f: impl FnMut($coords, Self::Item),
592            ) {
593                let visitor = ArrayForEach::new_global(*self.extent(), *iter_extent);
594                visitor.for_each(|$p, $stride| {
595                    f($forward_coords, self.get_mut_ptr($stride));
596                });
597            }
598        }
599
600        impl<'a, N, Chan> ForEachMut<'a, N, $coords> for Array<N, Chan>
601        where
602            Self: ForEachMutPtr<N, $coords, Item = Chan::Ptr>,
603            Chan: Channels,
604            Chan::Ptr: IntoMultiMut<'a>,
605        {
606            type Item = <Chan::Ptr as IntoMultiMut<'a>>::MultiMut;
607
608            #[inline]
609            fn for_each_mut(
610                &'a mut self,
611                iter_extent: &ExtentN<N>,
612                mut f: impl FnMut($coords, Self::Item),
613            ) {
614                unsafe {
615                    self.for_each_mut_ptr(iter_extent, |c, ptr| f(c, ptr.into_multi_mut()));
616                }
617            }
618        }
619    };
620}
621
622impl_array_for_each!(
623    coords: (PointN<N>, Stride);
624    forwarder = |p, stride| (p, stride);
625);
626impl_array_for_each!(
627    coords: Stride;
628    forwarder = |_p, stride| stride;
629);
630impl_array_for_each!(
631    coords: PointN<N>;
632    forwarder = |p, _stride| p;
633);
634impl_array_for_each!(
635    coords: ();
636    forwarder = |_p, _stride| ();
637);
638
639//  ██████╗ ██████╗ ██████╗ ██╗   ██╗
640// ██╔════╝██╔═══██╗██╔══██╗╚██╗ ██╔╝
641// ██║     ██║   ██║██████╔╝ ╚████╔╝
642// ██║     ██║   ██║██╔═══╝   ╚██╔╝
643// ╚██████╗╚██████╔╝██║        ██║
644//  ╚═════╝ ╚═════╝ ╚═╝        ╚═╝
645
646// Newtype avoids potential conflicting impls downstream.
647#[doc(hidden)]
648#[derive(Copy, Clone)]
649pub struct ArrayCopySrc<Map>(pub Map);
650
651impl<'a, N: 'a, Chan: 'a> ReadExtent<'a, N> for Array<N, Chan>
652where
653    PointN<N>: IntegerPoint<N>,
654{
655    type Src = ArrayCopySrc<&'a Array<N, Chan>>;
656    type SrcIter = Once<(ExtentN<N>, Self::Src)>;
657
658    fn read_extent(&'a self, extent: &ExtentN<N>) -> Self::SrcIter {
659        let in_bounds_extent = extent.intersection(self.extent());
660
661        once((in_bounds_extent, ArrayCopySrc(&self)))
662    }
663}
664
665impl<'a, N, Data, SrcSlices, ChanSrc, ChanDst> WriteExtent<N, ArrayCopySrc<&'a Array<N, ChanSrc>>>
666    for Array<N, ChanDst>
667where
668    Self: GetMutPtr<Stride, Item = ChanDst::Ptr>,
669    Array<N, ChanSrc>: Get<Stride, Item = Data>,
670    N: ArrayIndexer<N>,
671    PointN<N>: IntegerPoint<N>,
672    ChanSrc: Channels<Data = Data> + Slices<'a, Target = SrcSlices>,
673    ChanDst: Channels<Data = Data> + CopySlices<'a, Src = SrcSlices>,
674{
675    fn write_extent(
676        &mut self,
677        extent: &ExtentN<N>,
678        src_array: ArrayCopySrc<&'a Array<N, ChanSrc>>,
679    ) {
680        // It is assumed by the interface that extent is a subset of the src array, so we only need to intersect with the
681        // destination.
682        let in_bounds_extent = extent.intersection(self.extent());
683
684        let copy_entire_array = in_bounds_extent.shape == self.extent().shape
685            && in_bounds_extent.shape == src_array.0.extent().shape;
686
687        if copy_entire_array {
688            // Fast path, mostly for copying entire chunks between chunk maps.
689            self.channels.copy_slices(src_array.0.channels.slices());
690        } else {
691            unchecked_copy_extent_between_arrays(self, src_array.0, in_bounds_extent);
692        }
693    }
694}
695
696impl<'a, N, Chan, Delegate, F> WriteExtent<N, ArrayCopySrc<TransformMap<'a, Delegate, F>>>
697    for Array<N, Chan>
698where
699    Self: IndexedArray<N> + GetMutPtr<Stride, Item = Chan::Ptr>,
700    TransformMap<'a, Delegate, F>: IndexedArray<N> + Get<Stride, Item = Chan::Data>,
701    N: ArrayIndexer<N>,
702    PointN<N>: IntegerPoint<N>,
703    Chan: Channels,
704{
705    fn write_extent(
706        &mut self,
707        extent: &ExtentN<N>,
708        src_array: ArrayCopySrc<TransformMap<'a, Delegate, F>>,
709    ) {
710        // It is assumed by the interface that extent is a subset of the src array, so we only need to intersect with the
711        // destination.
712        let in_bounds_extent = extent.intersection(self.extent());
713
714        unchecked_copy_extent_between_arrays(self, &src_array.0, in_bounds_extent);
715    }
716}
717
718// SAFETY: `extent` must be in-bounds of both arrays.
719fn unchecked_copy_extent_between_arrays<Dst, Src, N, Ptr>(
720    dst: &mut Dst,
721    src: &Src,
722    extent: ExtentN<N>,
723) where
724    N: ArrayIndexer<N>,
725    PointN<N>: IntegerPoint<N>,
726    Dst: IndexedArray<N> + GetMutPtr<Stride, Item = Ptr>,
727    Src: IndexedArray<N> + Get<Stride, Item = Ptr::Data>,
728    Ptr: MultiMutPtr,
729{
730    // It shoudn't matter which type we use for the indexer.
731    let for_each = LockStepArrayForEach::new_global_unchecked(extent, *dst.extent(), *src.extent());
732    Dst::Indexer::for_each_lockstep_unchecked(for_each, |_p, (s_dst, s_src)| {
733        // The actual copy.
734        // PERF: could be faster with SIMD copy
735        unsafe {
736            dst.get_mut_ptr(s_dst).write(src.get(s_src));
737        }
738    });
739}
740
741impl<N, Chan, Ch> WriteExtent<N, ChunkCopySrc<N, Chan::Data, Ch>> for Array<N, Chan>
742where
743    Self: ForEachMutPtr<N, (), Item = Chan::Ptr> + WriteExtent<N, ArrayCopySrc<Ch>>,
744    PointN<N>: IntegerPoint<N>,
745    Chan: ResetChannels,
746    Chan::Data: Clone,
747{
748    fn write_extent(&mut self, extent: &ExtentN<N>, src: ChunkCopySrc<N, Chan::Data, Ch>) {
749        match src {
750            Either::Left(array) => self.write_extent(extent, array),
751            Either::Right(ambient) => self.fill_extent(extent, ambient.get()),
752        }
753    }
754}
755
756impl<N, Chan, F> WriteExtent<N, F> for Array<N, Chan>
757where
758    Self: ForEachMutPtr<N, PointN<N>, Item = Chan::Ptr>,
759    F: Fn(PointN<N>) -> Chan::Data,
760    Chan: Channels,
761{
762    fn write_extent(&mut self, extent: &ExtentN<N>, src: F) {
763        unsafe {
764            self.for_each_mut_ptr(extent, |p, v| v.write((src)(p)));
765        }
766    }
767}
768
769// ████████╗███████╗███████╗████████╗
770// ╚══██╔══╝██╔════╝██╔════╝╚══██╔══╝
771//    ██║   █████╗  ███████╗   ██║
772//    ██║   ██╔══╝  ╚════██║   ██║
773//    ██║   ███████╗███████║   ██║
774//    ╚═╝   ╚══════╝╚══════╝   ╚═╝
775
776#[cfg(test)]
777mod tests {
778    use super::*;
779    use crate::{copy_extent, Array2x1, Array3x1, Get};
780    use core::mem::MaybeUninit;
781
782    #[test]
783    fn fill_and_get_2d() {
784        let extent = Extent2i::from_min_and_shape(PointN([1, 1]), PointN([10, 10]));
785        let mut array = Array2x1::fill(extent, 0);
786        assert_eq!(array.extent.num_points(), 100);
787        *array.get_mut(Stride(0)) = 1;
788
789        assert_eq!(array.get(Stride(0)), 1);
790        assert_eq!(array.get_mut(Stride(0)), &mut 1);
791
792        assert_eq!(array.get(Local(PointN([0, 0]))), 1);
793        assert_eq!(array.get_mut(Local(PointN([0, 0]))), &mut 1);
794
795        assert_eq!(array.get(PointN([1, 1])), 1);
796        assert_eq!(array.get_mut(PointN([1, 1])), &mut 1);
797    }
798
799    #[test]
800    fn fill_and_get_3d() {
801        let extent = Extent3i::from_min_and_shape(Point3i::fill(1), Point3i::fill(10));
802        let mut array = Array3x1::fill(extent, 0);
803        assert_eq!(array.extent.num_points(), 1000);
804        *array.get_mut(Stride(0)) = 1;
805
806        assert_eq!(array.get(Stride(0)), 1);
807        assert_eq!(array.get_mut(Stride(0)), &mut 1);
808
809        assert_eq!(array.get(Local(Point3i::ZERO)), 1);
810        assert_eq!(array.get_mut(Local(Point3i::ZERO)), &mut 1);
811
812        assert_eq!(array.get(PointN([1, 1, 1])), 1);
813        assert_eq!(array.get_mut(PointN([1, 1, 1])), &mut 1);
814    }
815
816    #[test]
817    fn fill_and_for_each_2d() {
818        let extent = Extent2i::from_min_and_shape(Point2i::fill(1), Point2i::fill(10));
819        let mut array = Array2x1::fill(extent, 0);
820        assert_eq!(array.extent.num_points(), 100);
821        *array.get_mut(Stride(0)) = 1;
822
823        array.for_each(&extent, |p: Point2i, value| {
824            if p == Point2i::fill(1) {
825                assert_eq!(value, 1);
826            } else {
827                assert_eq!(value, 0);
828            }
829        });
830    }
831
832    #[test]
833    fn fill_and_for_each_3d() {
834        let extent = Extent3i::from_min_and_shape(Point3i::fill(1), Point3i::fill(10));
835        let mut array = Array3x1::fill(extent, 0);
836        assert_eq!(array.extent.num_points(), 1000);
837        *array.get_mut(Stride(0)) = 1;
838
839        array.for_each(&extent, |p: Point3i, value| {
840            if p == Point3i::fill(1) {
841                assert_eq!(value, 1);
842            } else {
843                assert_eq!(value, 0);
844            }
845        });
846    }
847
848    #[test]
849    fn uninitialized() {
850        let extent = Extent3i::from_min_and_shape(Point3i::fill(1), Point3i::fill(10));
851        let mut array: Array3x1<MaybeUninit<i32>> = unsafe { Array3x1::maybe_uninit(extent) };
852
853        array.for_each_mut(&extent, |_: (), val| unsafe {
854            val.as_mut_ptr().write(1);
855        });
856
857        let array = unsafe { array.assume_init() };
858
859        array.for_each(&extent, |_: (), val| {
860            assert_eq!(val, 1i32);
861        });
862    }
863
864    #[test]
865    fn copy() {
866        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
867        let mut array = Array3x1::fill(extent, 0);
868
869        let subextent = Extent3i::from_min_and_shape(Point3i::fill(1), Point3i::fill(5));
870        array.for_each_mut(&subextent, |p: Point3i, val| {
871            *val = p.x() + p.y() + p.z();
872        });
873
874        let mut other_array = Array3x1::fill(extent, 0);
875        copy_extent(&subextent, &array, &mut other_array);
876
877        assert_eq!(array, other_array);
878    }
879
880    #[test]
881    fn multichannel_get() {
882        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
883        let mut array = Array3x2::fill(extent, (0, 'a'));
884
885        assert_eq!(array.get(Stride(0)), (0, 'a'));
886        assert_eq!(array.get_ref(Stride(0)), (&0, &'a'));
887        assert_eq!(array.get_mut(Stride(0)), (&mut 0, &mut 'a'));
888
889        assert_eq!(array.get(Local(Point3i::fill(0))), (0, 'a'));
890        assert_eq!(array.get_ref(Local(Point3i::fill(0))), (&0, &'a'));
891        assert_eq!(array.get_mut(Local(Point3i::fill(0))), (&mut 0, &mut 'a'));
892
893        assert_eq!(array.get(Point3i::fill(0)), (0, 'a'));
894        assert_eq!(array.get_ref(Point3i::fill(0)), (&0, &'a'));
895        assert_eq!(array.get_mut(Point3i::fill(0)), (&mut 0, &mut 'a'));
896    }
897
898    #[test]
899    fn multichannel_access_with_borrowed_storage() {
900        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
901        let mut array = Array3x2::fill(extent, (0, 'a'));
902
903        // Swap the order.
904        let borrowed = array.borrow_channels(|(c1, c2)| (c2, c1));
905
906        assert_eq!(borrowed.get(Stride(0)), ('a', 0));
907        assert_eq!(borrowed.get_ref(Stride(0)), (&'a', &0));
908
909        assert_eq!(borrowed.get(Local(Point3i::fill(0))), ('a', 0));
910        assert_eq!(borrowed.get_ref(Local(Point3i::fill(0))), (&'a', &0));
911
912        borrowed.for_each(&extent, |_: (), x| assert_eq!(x, ('a', 0)));
913
914        let mut other = Array3x2::fill(extent, ('b', 1));
915        copy_extent(&extent, &borrowed, &mut other);
916
917        let mut borrowed = array.borrow_channels_mut(|(c1, c2)| (c2, c1));
918
919        assert_eq!(borrowed.get(Stride(0)), ('a', 0));
920        assert_eq!(borrowed.get_ref(Stride(0)), (&'a', &0));
921        assert_eq!(borrowed.get_mut(Stride(0)), (&mut 'a', &mut 0));
922
923        assert_eq!(borrowed.get(Local(Point3i::fill(0))), ('a', 0));
924        assert_eq!(borrowed.get_ref(Local(Point3i::fill(0))), (&'a', &0));
925        assert_eq!(
926            borrowed.get_mut(Local(Point3i::fill(0))),
927            (&mut 'a', &mut 0)
928        );
929
930        borrowed.for_each_mut(&extent, |_: (), x| assert_eq!(x, (&mut 'a', &mut 0)));
931
932        copy_extent(&extent, &other, &mut borrowed);
933    }
934
935    #[test]
936    fn multichannel_for_each() {
937        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
938        let mut array = Array3x2::fill(extent, (0, 'a'));
939
940        array.for_each(&extent, |_: (), (c1, c2)| {
941            assert_eq!(c1, 0);
942            assert_eq!(c2, 'a');
943        });
944
945        array.for_each_mut(&extent, |_: (), (c1, c2)| {
946            *c1 = 1;
947            *c2 = 'b';
948        });
949
950        array.for_each(&extent, |_: (), (c1, c2)| {
951            assert_eq!(c1, 1);
952            assert_eq!(c2, 'b');
953        });
954    }
955
956    #[test]
957    fn multichannel_fill_extent() {
958        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
959        let mut array = Array3x2::fill(extent, (0, 'a'));
960
961        array.fill_extent(&extent, (1, 'b'));
962
963        array.for_each(array.extent(), |_: (), (num, letter)| {
964            assert_eq!(num, 1);
965            assert_eq!(letter, 'b');
966        });
967    }
968
969    #[test]
970    fn multichannel_fill_with() {
971        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
972        let array =
973            Array3x2::fill_with(extent, |p| if p.x() % 2 == 0 { (1, 'b') } else { (0, 'a') });
974
975        array.for_each(array.extent(), |p: Point3i, (num, letter)| {
976            if p.x() % 2 == 0 {
977                assert_eq!((num, letter), (1, 'b'));
978            } else {
979                assert_eq!((num, letter), (0, 'a'));
980            }
981        });
982    }
983
984    #[test]
985    fn multichannel_copy() {
986        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
987        let src = Array3x2::fill(extent, (0, 'a'));
988        let mut dst = Array3x2::fill(extent, (1, 'b'));
989        copy_extent(&extent, &src, &mut dst);
990        assert_eq!(src, dst);
991    }
992
993    #[test]
994    fn select_channel_with_transform() {
995        let extent = Extent3i::from_min_and_shape(Point3i::ZERO, Point3i::fill(10));
996        let src = Array3x2::fill(extent, (0, 'a'));
997        let src_select = TransformMap::new(&src, |(_num, letter): (i32, char)| letter);
998
999        let mut dst = Array3x1::fill(extent, 'b');
1000
1001        copy_extent(&extent, &src_select, &mut dst);
1002
1003        dst.for_each(&extent, |_: (), letter| {
1004            assert_eq!(letter, 'a');
1005        });
1006    }
1007}