ndarray/zip/
ndproducer.rs

1
2use crate::imp_prelude::*;
3use crate::Layout;
4use crate::NdIndex;
5#[cfg(not(features = "std"))]
6use alloc::vec::Vec;
7
8/// Argument conversion into a producer.
9///
10/// Slices and vectors can be used (equivalent to 1-dimensional array views).
11///
12/// This trait is like `IntoIterator` for `NdProducers` instead of iterators.
13pub trait IntoNdProducer {
14    /// The element produced per iteration.
15    type Item;
16    /// Dimension type of the producer
17    type Dim: Dimension;
18    type Output: NdProducer<Dim = Self::Dim, Item = Self::Item>;
19    /// Convert the value into an `NdProducer`.
20    fn into_producer(self) -> Self::Output;
21}
22
23impl<P> IntoNdProducer for P
24where
25    P: NdProducer,
26{
27    type Item = P::Item;
28    type Dim = P::Dim;
29    type Output = Self;
30    fn into_producer(self) -> Self::Output {
31        self
32    }
33}
34
35/// A producer of an n-dimensional set of elements;
36/// for example an array view, mutable array view or an iterator
37/// that yields chunks.
38///
39/// Producers are used as a arguments to [`Zip`](struct.Zip.html) and
40/// [`azip!()`](macro.azip.html).
41///
42/// # Comparison to `IntoIterator`
43///
44/// Most `NdProducers` are *iterable* (implement `IntoIterator`) but not directly
45/// iterators. This separation is needed because the producer represents
46/// a multidimensional set of items, it can be split along a particular axis for
47/// parallelization, and it has no fixed correspondance to a sequence.
48///
49/// The natural exception is one dimensional producers, like `AxisIter`, which
50/// implement `Iterator` directly
51/// (`AxisIter` traverses a one dimensional sequence, along an axis, while
52/// *producing* multidimensional items).
53///
54/// See also [`IntoNdProducer`](trait.IntoNdProducer.html)
55pub trait NdProducer {
56    /// The element produced per iteration.
57    type Item;
58    // Internal use / Pointee type
59    /// Dimension type
60    type Dim: Dimension;
61
62    // The pointer Ptr is used by an array view to simply point to the
63    // current element. It doesn't have to be a pointer (see Indices).
64    // Its main function is that it can be incremented with a particular
65    // stride (= along a particular axis)
66    #[doc(hidden)]
67    /// Pointer or stand-in for pointer
68    type Ptr: Offset<Stride = Self::Stride>;
69    #[doc(hidden)]
70    /// Pointer stride
71    type Stride: Copy;
72
73    #[doc(hidden)]
74    fn layout(&self) -> Layout;
75    /// Return the shape of the producer.
76    fn raw_dim(&self) -> Self::Dim;
77    #[doc(hidden)]
78    fn equal_dim(&self, dim: &Self::Dim) -> bool {
79        self.raw_dim() == *dim
80    }
81    #[doc(hidden)]
82    fn as_ptr(&self) -> Self::Ptr;
83    #[doc(hidden)]
84    unsafe fn as_ref(&self, ptr: Self::Ptr) -> Self::Item;
85    #[doc(hidden)]
86    unsafe fn uget_ptr(&self, i: &Self::Dim) -> Self::Ptr;
87    #[doc(hidden)]
88    fn stride_of(&self, axis: Axis) -> <Self::Ptr as Offset>::Stride;
89    #[doc(hidden)]
90    fn contiguous_stride(&self) -> Self::Stride;
91    #[doc(hidden)]
92    fn split_at(self, axis: Axis, index: usize) -> (Self, Self)
93    where
94        Self: Sized;
95
96    private_decl! {}
97}
98
99pub trait Offset: Copy {
100    type Stride: Copy;
101    unsafe fn stride_offset(self, s: Self::Stride, index: usize) -> Self;
102    private_decl! {}
103}
104
105impl<T> Offset for *const T {
106    type Stride = isize;
107    unsafe fn stride_offset(self, s: Self::Stride, index: usize) -> Self {
108        self.offset(s * (index as isize))
109    }
110    private_impl! {}
111}
112
113impl<T> Offset for *mut T {
114    type Stride = isize;
115    unsafe fn stride_offset(self, s: Self::Stride, index: usize) -> Self {
116        self.offset(s * (index as isize))
117    }
118    private_impl! {}
119}
120
121/// An array reference is an n-dimensional producer of element references
122/// (like ArrayView).
123impl<'a, A: 'a, S, D> IntoNdProducer for &'a ArrayBase<S, D>
124where
125    D: Dimension,
126    S: Data<Elem = A>,
127{
128    type Item = &'a A;
129    type Dim = D;
130    type Output = ArrayView<'a, A, D>;
131    fn into_producer(self) -> Self::Output {
132        self.view()
133    }
134}
135
136/// A mutable array reference is an n-dimensional producer of mutable element
137/// references (like ArrayViewMut).
138impl<'a, A: 'a, S, D> IntoNdProducer for &'a mut ArrayBase<S, D>
139where
140    D: Dimension,
141    S: DataMut<Elem = A>,
142{
143    type Item = &'a mut A;
144    type Dim = D;
145    type Output = ArrayViewMut<'a, A, D>;
146    fn into_producer(self) -> Self::Output {
147        self.view_mut()
148    }
149}
150
151/// A slice is a one-dimensional producer
152impl<'a, A: 'a> IntoNdProducer for &'a [A] {
153    type Item = <Self::Output as NdProducer>::Item;
154    type Dim = Ix1;
155    type Output = ArrayView1<'a, A>;
156    fn into_producer(self) -> Self::Output {
157        <_>::from(self)
158    }
159}
160
161/// A mutable slice is a mutable one-dimensional producer
162impl<'a, A: 'a> IntoNdProducer for &'a mut [A] {
163    type Item = <Self::Output as NdProducer>::Item;
164    type Dim = Ix1;
165    type Output = ArrayViewMut1<'a, A>;
166    fn into_producer(self) -> Self::Output {
167        <_>::from(self)
168    }
169}
170
171/// A Vec is a one-dimensional producer
172impl<'a, A: 'a> IntoNdProducer for &'a Vec<A> {
173    type Item = <Self::Output as NdProducer>::Item;
174    type Dim = Ix1;
175    type Output = ArrayView1<'a, A>;
176    fn into_producer(self) -> Self::Output {
177        <_>::from(self)
178    }
179}
180
181/// A mutable Vec is a mutable one-dimensional producer
182impl<'a, A: 'a> IntoNdProducer for &'a mut Vec<A> {
183    type Item = <Self::Output as NdProducer>::Item;
184    type Dim = Ix1;
185    type Output = ArrayViewMut1<'a, A>;
186    fn into_producer(self) -> Self::Output {
187        <_>::from(self)
188    }
189}
190
191impl<'a, A, D: Dimension> NdProducer for ArrayView<'a, A, D> {
192    type Item = &'a A;
193    type Dim = D;
194    type Ptr = *mut A;
195    type Stride = isize;
196
197    private_impl! {}
198    #[doc(hidden)]
199    fn raw_dim(&self) -> Self::Dim {
200        self.raw_dim()
201    }
202
203    #[doc(hidden)]
204    fn equal_dim(&self, dim: &Self::Dim) -> bool {
205        self.dim.equal(dim)
206    }
207
208    #[doc(hidden)]
209    fn as_ptr(&self) -> *mut A {
210        self.as_ptr() as _
211    }
212
213    #[doc(hidden)]
214    fn layout(&self) -> Layout {
215        self.layout_impl()
216    }
217
218    #[doc(hidden)]
219    unsafe fn as_ref(&self, ptr: *mut A) -> Self::Item {
220        &*ptr
221    }
222
223    #[doc(hidden)]
224    unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A {
225        self.ptr.as_ptr().offset(i.index_unchecked(&self.strides))
226    }
227
228    #[doc(hidden)]
229    fn stride_of(&self, axis: Axis) -> isize {
230        self.stride_of(axis)
231    }
232
233    #[inline(always)]
234    fn contiguous_stride(&self) -> Self::Stride {
235        1
236    }
237
238    #[doc(hidden)]
239    fn split_at(self, axis: Axis, index: usize) -> (Self, Self) {
240        self.split_at(axis, index)
241    }
242}
243
244impl<'a, A, D: Dimension> NdProducer for ArrayViewMut<'a, A, D> {
245    type Item = &'a mut A;
246    type Dim = D;
247    type Ptr = *mut A;
248    type Stride = isize;
249
250    private_impl! {}
251    #[doc(hidden)]
252    fn raw_dim(&self) -> Self::Dim {
253        self.raw_dim()
254    }
255
256    #[doc(hidden)]
257    fn equal_dim(&self, dim: &Self::Dim) -> bool {
258        self.dim.equal(dim)
259    }
260
261    #[doc(hidden)]
262    fn as_ptr(&self) -> *mut A {
263        self.as_ptr() as _
264    }
265
266    #[doc(hidden)]
267    fn layout(&self) -> Layout {
268        self.layout_impl()
269    }
270
271    #[doc(hidden)]
272    unsafe fn as_ref(&self, ptr: *mut A) -> Self::Item {
273        &mut *ptr
274    }
275
276    #[doc(hidden)]
277    unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A {
278        self.ptr.as_ptr().offset(i.index_unchecked(&self.strides))
279    }
280
281    #[doc(hidden)]
282    fn stride_of(&self, axis: Axis) -> isize {
283        self.stride_of(axis)
284    }
285
286    #[inline(always)]
287    fn contiguous_stride(&self) -> Self::Stride {
288        1
289    }
290
291    #[doc(hidden)]
292    fn split_at(self, axis: Axis, index: usize) -> (Self, Self) {
293        self.split_at(axis, index)
294    }
295}
296
297impl<A, D: Dimension> NdProducer for RawArrayView<A, D> {
298    type Item = *const A;
299    type Dim = D;
300    type Ptr = *const A;
301    type Stride = isize;
302
303    private_impl! {}
304    #[doc(hidden)]
305    fn raw_dim(&self) -> Self::Dim {
306        self.raw_dim()
307    }
308
309    #[doc(hidden)]
310    fn equal_dim(&self, dim: &Self::Dim) -> bool {
311        self.dim.equal(dim)
312    }
313
314    #[doc(hidden)]
315    fn as_ptr(&self) -> *const A {
316        self.as_ptr()
317    }
318
319    #[doc(hidden)]
320    fn layout(&self) -> Layout {
321        self.layout_impl()
322    }
323
324    #[doc(hidden)]
325    unsafe fn as_ref(&self, ptr: *const A) -> *const A {
326        ptr
327    }
328
329    #[doc(hidden)]
330    unsafe fn uget_ptr(&self, i: &Self::Dim) -> *const A {
331        self.ptr.as_ptr().offset(i.index_unchecked(&self.strides))
332    }
333
334    #[doc(hidden)]
335    fn stride_of(&self, axis: Axis) -> isize {
336        self.stride_of(axis)
337    }
338
339    #[inline(always)]
340    fn contiguous_stride(&self) -> Self::Stride {
341        1
342    }
343
344    #[doc(hidden)]
345    fn split_at(self, axis: Axis, index: usize) -> (Self, Self) {
346        self.split_at(axis, index)
347    }
348}
349
350impl<A, D: Dimension> NdProducer for RawArrayViewMut<A, D> {
351    type Item = *mut A;
352    type Dim = D;
353    type Ptr = *mut A;
354    type Stride = isize;
355
356    private_impl! {}
357    #[doc(hidden)]
358    fn raw_dim(&self) -> Self::Dim {
359        self.raw_dim()
360    }
361
362    #[doc(hidden)]
363    fn equal_dim(&self, dim: &Self::Dim) -> bool {
364        self.dim.equal(dim)
365    }
366
367    #[doc(hidden)]
368    fn as_ptr(&self) -> *mut A {
369        self.as_ptr() as _
370    }
371
372    #[doc(hidden)]
373    fn layout(&self) -> Layout {
374        self.layout_impl()
375    }
376
377    #[doc(hidden)]
378    unsafe fn as_ref(&self, ptr: *mut A) -> *mut A {
379        ptr
380    }
381
382    #[doc(hidden)]
383    unsafe fn uget_ptr(&self, i: &Self::Dim) -> *mut A {
384        self.ptr.as_ptr().offset(i.index_unchecked(&self.strides))
385    }
386
387    #[doc(hidden)]
388    fn stride_of(&self, axis: Axis) -> isize {
389        self.stride_of(axis)
390    }
391
392    #[inline(always)]
393    fn contiguous_stride(&self) -> Self::Stride {
394        1
395    }
396
397    #[doc(hidden)]
398    fn split_at(self, axis: Axis, index: usize) -> (Self, Self) {
399        self.split_at(axis, index)
400    }
401}
402