1use crate::{
4 ContainerType,
5 base_types::NumberType,
6 traits::{
7 accessors::{
8 UnsafeRandom1DAccessByRef, UnsafeRandom1DAccessByValue, UnsafeRandom1DAccessMut,
9 },
10 base_operations::BaseItem,
11 number_relations::IsSmallerByOne,
12 },
13};
14
15use super::{
16 Array, RawAccess, RawAccessMut, Shape, Stride, UnsafeRandomAccessByRef,
17 UnsafeRandomAccessByValue, UnsafeRandomAccessMut,
18};
19
20#[derive(Clone, Copy)]
22pub enum AxisPosition {
23 Front,
25 Back,
27}
28
29pub struct ArrayAppendAxis<ArrayImpl, const ADIM: usize, const NDIM: usize>
31where
32 NumberType<ADIM>: IsSmallerByOne<NDIM>,
33{
34 arr: Array<ArrayImpl, ADIM>,
35 axis_position: AxisPosition,
36}
37
38impl<ArrayImpl, const ADIM: usize, const NDIM: usize> ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
39where
40 NumberType<ADIM>: IsSmallerByOne<NDIM>,
41{
42 pub fn new(arr: Array<ArrayImpl, ADIM>, axis_position: AxisPosition) -> Self {
44 Self { arr, axis_position }
45 }
46}
47
48impl<ArrayImpl, const ADIM: usize, const NDIM: usize> ContainerType
49 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
50where
51 NumberType<ADIM>: IsSmallerByOne<NDIM>,
52 ArrayImpl: ContainerType,
53{
54 type Type = ArrayImpl::Type;
55}
56
57impl<ArrayImpl, const ADIM: usize, const NDIM: usize> BaseItem
58 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
59where
60 NumberType<ADIM>: IsSmallerByOne<NDIM>,
61 ArrayImpl: BaseItem,
62{
63 type Item = ArrayImpl::Item;
64}
65
66impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandomAccessByValue<NDIM>
67 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
68where
69 NumberType<ADIM>: IsSmallerByOne<NDIM>,
70 ArrayImpl: UnsafeRandomAccessByValue<ADIM>,
71{
72 #[inline(always)]
73 unsafe fn get_value_unchecked(&self, multi_index: [usize; NDIM]) -> Self::Item {
74 unsafe {
75 self.arr
76 .get_value_unchecked(multi_index_to_orig(multi_index, self.axis_position))
77 }
78 }
79}
80
81impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandom1DAccessByValue
82 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
83where
84 NumberType<ADIM>: IsSmallerByOne<NDIM>,
85 ArrayImpl: UnsafeRandom1DAccessByValue,
86{
87 #[inline(always)]
88 unsafe fn get_value_1d_unchecked(&self, index: usize) -> Self::Item {
89 unsafe { self.arr.imp().get_value_1d_unchecked(index) }
90 }
91}
92
93impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandom1DAccessByRef
94 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
95where
96 NumberType<ADIM>: IsSmallerByOne<NDIM>,
97 ArrayImpl: UnsafeRandom1DAccessByRef,
98{
99 #[inline(always)]
100 unsafe fn get_1d_unchecked(&self, index: usize) -> &Self::Item {
101 unsafe { self.arr.imp().get_1d_unchecked(index) }
102 }
103}
104
105impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandom1DAccessMut
106 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
107where
108 NumberType<ADIM>: IsSmallerByOne<NDIM>,
109 ArrayImpl: UnsafeRandom1DAccessMut,
110{
111 #[inline(always)]
112 unsafe fn get_1d_unchecked_mut(&mut self, index: usize) -> &mut Self::Item {
113 unsafe { self.arr.imp_mut().get_1d_unchecked_mut(index) }
114 }
115}
116
117impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandomAccessByRef<NDIM>
118 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
119where
120 NumberType<ADIM>: IsSmallerByOne<NDIM>,
121 ArrayImpl: UnsafeRandomAccessByRef<ADIM>,
122{
123 #[inline(always)]
124 unsafe fn get_unchecked(&self, multi_index: [usize; NDIM]) -> &Self::Item {
125 unsafe {
126 self.arr
127 .get_unchecked(multi_index_to_orig(multi_index, self.axis_position))
128 }
129 }
130}
131
132impl<ArrayImpl, const ADIM: usize, const NDIM: usize> UnsafeRandomAccessMut<NDIM>
133 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
134where
135 NumberType<ADIM>: IsSmallerByOne<NDIM>,
136 ArrayImpl: UnsafeRandomAccessMut<ADIM>,
137{
138 #[inline(always)]
139 unsafe fn get_unchecked_mut(&mut self, multi_index: [usize; NDIM]) -> &mut Self::Item {
140 unsafe {
141 self.arr
142 .get_unchecked_mut(multi_index_to_orig(multi_index, self.axis_position))
143 }
144 }
145}
146
147impl<ArrayImpl, const ADIM: usize, const NDIM: usize> Shape<NDIM>
148 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
149where
150 NumberType<ADIM>: IsSmallerByOne<NDIM>,
151 ArrayImpl: Shape<ADIM>,
152{
153 fn shape(&self) -> [usize; NDIM] {
154 let mut result = [1; NDIM];
155 let orig_shape = self.arr.shape();
156
157 match self.axis_position {
158 AxisPosition::Front => result[1..].copy_from_slice(&orig_shape),
159 AxisPosition::Back => result[..ADIM].copy_from_slice(&orig_shape),
160 }
161 result
162 }
163}
164
165impl<ArrayImpl: RawAccess, const ADIM: usize, const NDIM: usize> RawAccess
166 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
167where
168 NumberType<ADIM>: IsSmallerByOne<NDIM>,
169{
170 #[inline(always)]
171 fn data(&self) -> Option<&[Self::Item]> {
172 self.arr.data()
173 }
174}
175
176impl<ArrayImpl: RawAccessMut, const ADIM: usize, const NDIM: usize> RawAccessMut
177 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
178where
179 NumberType<ADIM>: IsSmallerByOne<NDIM>,
180{
181 #[inline(always)]
182 fn data_mut(&mut self) -> Option<&mut [Self::Item]> {
183 self.arr.data_mut()
184 }
185}
186
187impl<ArrayImpl, const ADIM: usize, const NDIM: usize> Stride<NDIM>
188 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
189where
190 NumberType<ADIM>: IsSmallerByOne<NDIM>,
191 ArrayImpl: Stride<ADIM> + Shape<ADIM>,
192{
193 fn stride(&self) -> [usize; NDIM] {
194 let mut result = [0; NDIM];
195 let orig_stride = self.arr.stride();
196
197 match self.axis_position {
198 AxisPosition::Front => {
199 result[0] = 1;
200 result[1..].copy_from_slice(&orig_stride)
201 }
202 AxisPosition::Back => {
203 result[NDIM - 1] = orig_stride[ADIM - 1] * self.arr.shape()[ADIM - 1];
204 result[..ADIM].copy_from_slice(&orig_stride)
205 }
206 }
207 result
208 }
209}
210
211impl<ArrayImpl, const ADIM: usize> Array<ArrayImpl, ADIM> {
212 pub fn insert_empty_axis<const NDIM: usize>(
217 self,
218 axis_position: AxisPosition,
219 ) -> Array<ArrayAppendAxis<ArrayImpl, ADIM, NDIM>, NDIM>
220 where
221 NumberType<ADIM>: IsSmallerByOne<NDIM>,
222 {
223 Array::new(ArrayAppendAxis::new(self, axis_position))
224 }
225}
226
227fn multi_index_to_orig<const ADIM: usize, const NDIM: usize>(
229 multi_index: [usize; NDIM],
230 axis_position: AxisPosition,
231) -> [usize; ADIM]
232where
233 NumberType<ADIM>: IsSmallerByOne<NDIM>,
234{
235 let mut orig = [0; ADIM];
236 match axis_position {
237 AxisPosition::Front => orig.copy_from_slice(&multi_index[1..]),
238 AxisPosition::Back => orig.copy_from_slice(&multi_index[..ADIM]),
239 }
240
241 orig
242}
243
244unsafe impl<ArrayImpl, const ADIM: usize, const NDIM: usize> crate::UnsafeDisjointRandom1DAccessMut
246 for ArrayAppendAxis<ArrayImpl, ADIM, NDIM>
247where
248 NumberType<ADIM>: IsSmallerByOne<NDIM>,
249 ArrayImpl: crate::UnsafeDisjointRandom1DAccessMut,
250{
251}