Thanks to visit codestin.com
Credit goes to docs.rs

ndarray/zip/
ndproducer.rs

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