1mod 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#[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 pub fn new(extent: ExtentN<N>, channels: Chan) -> Self {
222 Self { channels, extent }
224 }
225
226 #[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 #[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 #[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 #[inline]
292 pub fn set_minimum(&mut self, p: PointN<N>) {
293 self.extent.minimum = p;
294 }
295
296 #[inline]
298 pub fn translate(&mut self, p: PointN<N>) {
299 self.extent = self.extent.add(p);
300 }
301
302 #[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 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 #[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 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 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 pub unsafe fn maybe_uninit(extent: ExtentN<N>) -> Array<N, Chan> {
389 Array::new(extent, Chan::maybe_uninit(extent.num_points()))
390 }
391
392 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
415impl<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
554macro_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#[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 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 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 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
718fn 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 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 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#[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 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}