mdarray/
slice.rs

1#[cfg(feature = "nightly")]
2use alloc::alloc::Allocator;
3#[cfg(not(feature = "std"))]
4use alloc::borrow::ToOwned;
5#[cfg(not(feature = "std"))]
6use alloc::vec::Vec;
7
8use core::fmt::{Debug, Formatter, Result};
9use core::hash::{Hash, Hasher};
10use core::marker::PhantomData;
11use core::mem;
12use core::ops::{Index, IndexMut};
13use core::ptr::{self, NonNull};
14
15use crate::array::Array;
16use crate::dim::{Const, Dim, Dyn};
17use crate::expr::{Apply, Expression, FromExpression, IntoExpression};
18use crate::expr::{AxisExpr, AxisExprMut, Iter, Lanes, LanesMut, Map, Zip};
19use crate::index::{self, Axis, Cols, Resize, Rows, Split};
20use crate::index::{DimIndex, Permutation, SliceIndex, ViewIndex};
21use crate::layout::{Dense, Layout, Strided};
22use crate::mapping::Mapping;
23use crate::raw_slice::RawSlice;
24use crate::shape::{ConstShape, DynRank, IntoShape, Rank, Shape};
25use crate::tensor::Tensor;
26use crate::traits::{IntoCloned, Owned};
27use crate::view::{View, ViewMut};
28
29/// Multidimensional array slice.
30pub struct Slice<T, S: Shape = DynRank, L: Layout = Dense> {
31    phantom: PhantomData<(T, S, L)>,
32}
33
34/// Multidimensional array slice with dynamically-sized dimensions.
35pub type DSlice<T, const N: usize, L = Dense> = Slice<T, Rank<N>, L>;
36
37impl<T, S: Shape, L: Layout> Slice<T, S, L> {
38    /// Returns a mutable pointer to the array buffer.
39    #[inline]
40    pub fn as_mut_ptr(&mut self) -> *mut T {
41        if mem::size_of::<L::Mapping<S>>() > 0 {
42            RawSlice::from_mut_slice(self).as_mut_ptr()
43        } else {
44            self as *mut Self as *mut T
45        }
46    }
47
48    /// Returns a raw pointer to the array buffer.
49    #[inline]
50    pub fn as_ptr(&self) -> *const T {
51        if mem::size_of::<L::Mapping<S>>() > 0 {
52            RawSlice::from_slice(self).as_ptr()
53        } else {
54            self as *const Self as *const T
55        }
56    }
57
58    /// Assigns an expression to the array slice with broadcasting, cloning elements if needed.
59    ///
60    /// # Panics
61    ///
62    /// Panics if the expression cannot be broadcast to the shape of the array slice.
63    #[inline]
64    pub fn assign<I: IntoExpression<Item: IntoCloned<T>>>(&mut self, expr: I) {
65        self.expr_mut().zip(expr).for_each(|(x, y)| y.clone_to(x));
66    }
67
68    /// Returns an array view after indexing the first dimension.
69    ///
70    /// # Panics
71    ///
72    /// Panics if the index is out of bounds, or if the rank is not at least 1.
73    #[inline]
74    pub fn at(&self, index: usize) -> View<'_, T, S::Tail, L> {
75        self.axis_at(Const::<0>, index)
76    }
77
78    /// Returns a mutable array view after indexing the first dimension.
79    ///
80    /// # Panics
81    ///
82    /// Panics if the index is out of bounds, or if the rank is not at least 1.
83    #[inline]
84    pub fn at_mut(&mut self, index: usize) -> ViewMut<'_, T, S::Tail, L> {
85        self.axis_at_mut(Const::<0>, index)
86    }
87
88    /// Returns an array view after indexing the specified dimension.
89    ///
90    /// If the dimension to be indexed is know at compile time, the resulting array shape
91    /// will maintain constant-sized dimensions. Furthermore, if it is the first dimension
92    /// the resulting array view has the same layout as the input.
93    ///
94    /// # Panics
95    ///
96    /// Panics if the dimension or the index is out of bounds.
97    #[inline]
98    pub fn axis_at<A: Axis>(
99        &self,
100        axis: A,
101        index: usize,
102    ) -> View<'_, T, A::Remove<S>, Split<A, S, L>> {
103        unsafe { View::axis_at(self.as_ptr(), self.mapping(), axis, index) }
104    }
105
106    /// Returns a mutable array view after indexing the specified dimension.
107    ///
108    /// If the dimension to be indexed is know at compile time, the resulting array shape
109    /// will maintain constant-sized dimensions. Furthermore, if it is the first dimension
110    /// the resulting array view has the same layout as the input.
111    ///
112    /// # Panics
113    ///
114    /// Panics if the dimension or the index is out of bounds.
115    #[inline]
116    pub fn axis_at_mut<A: Axis>(
117        &mut self,
118        axis: A,
119        index: usize,
120    ) -> ViewMut<'_, T, A::Remove<S>, Split<A, S, L>> {
121        unsafe { ViewMut::axis_at(self.as_mut_ptr(), self.mapping(), axis, index) }
122    }
123
124    /// Returns an expression that gives array views iterating over the specified dimension.
125    ///
126    /// If the dimension to be iterated over is know at compile time, the resulting array
127    /// shape will maintain constant-sized dimensions. Furthermore, if it is the first
128    /// dimension the resulting array views have the same layout as the input.
129    ///
130    /// # Panics
131    ///
132    /// Panics if the dimension is out of bounds.
133    #[inline]
134    pub fn axis_expr<A: Axis>(&self, axis: A) -> AxisExpr<'_, T, S, L, A> {
135        AxisExpr::new(self, axis)
136    }
137
138    /// Returns a mutable expression that gives array views iterating over the specified dimension.
139    ///
140    /// If the dimension to be iterated over is know at compile time, the resulting array
141    /// shape will maintain constant-sized dimensions. Furthermore, if it is the first
142    /// dimension the resulting array views have the same layout as the input.
143    ///
144    /// # Panics
145    ///
146    /// Panics if the dimension is out of bounds.
147    #[inline]
148    pub fn axis_expr_mut<A: Axis>(&mut self, axis: A) -> AxisExprMut<'_, T, S, L, A> {
149        AxisExprMut::new(self, axis)
150    }
151
152    /// Returns an array view for the specified column.
153    ///
154    /// # Panics
155    ///
156    /// Panics if the rank is not equal to 2, or if the index is out of bounds.
157    #[inline]
158    pub fn col(&self, index: usize) -> View<'_, T, (S::Head,), Strided> {
159        let shape = self.shape().with_dims(<(_, <S::Tail as Shape>::Head)>::from_dims);
160
161        self.reshape(shape).into_view(.., index)
162    }
163
164    /// Returns a mutable array view for the specified column.
165    ///
166    /// # Panics
167    ///
168    /// Panics if the rank is not equal to 2, or if the index is out of bounds.
169    #[inline]
170    pub fn col_mut(&mut self, index: usize) -> ViewMut<'_, T, (S::Head,), Strided> {
171        let shape = self.shape().with_dims(<(_, <S::Tail as Shape>::Head)>::from_dims);
172
173        self.reshape_mut(shape).into_view(.., index)
174    }
175
176    /// Returns an expression that gives column views iterating over the other dimensions.
177    ///
178    /// # Panics
179    ///
180    /// Panics if the rank is not at least 2.
181    #[inline]
182    pub fn cols(&self) -> Lanes<'_, T, S, L, Cols> {
183        self.lanes(Cols)
184    }
185
186    /// Returns a mutable expression that gives column views iterating over the other dimensions.
187    ///
188    /// # Panics
189    ///
190    /// Panics if the rank is not at least 2.
191    #[inline]
192    pub fn cols_mut(&mut self) -> LanesMut<'_, T, S, L, Cols> {
193        self.lanes_mut(Cols)
194    }
195
196    /// Returns `true` if the array slice contains an element with the given value.
197    #[inline]
198    pub fn contains(&self, x: &T) -> bool
199    where
200        T: PartialEq,
201    {
202        contains(self, x)
203    }
204
205    /// Returns an array view for the given diagonal of the array slice,
206    /// where `index` > 0 is above and `index` < 0 is below the main diagonal.
207    ///
208    /// # Panics
209    ///
210    /// Panics if the rank is not equal to 2, or if the absolute index is larger
211    /// than the number of columns or rows.
212    #[inline]
213    pub fn diag(&self, index: isize) -> View<'_, T, (Dyn,), Strided> {
214        let shape = self.shape().with_dims(<(S::Head, <S::Tail as Shape>::Head)>::from_dims);
215
216        self.reshape(shape).into_diag(index)
217    }
218
219    /// Returns a mutable array view for the given diagonal of the array slice,
220    /// where `index` > 0 is above and `index` < 0 is below the main diagonal.
221    ///
222    /// # Panics
223    ///
224    /// Panics if the rank is not equal to 2, or if the absolute index is larger
225    /// than the number of columns or rows.
226    #[inline]
227    pub fn diag_mut(&mut self, index: isize) -> ViewMut<'_, T, (Dyn,), Strided> {
228        let shape = self.shape().with_dims(<(S::Head, <S::Tail as Shape>::Head)>::from_dims);
229
230        self.reshape_mut(shape).into_diag(index)
231    }
232
233    /// Returns the number of elements in the specified dimension.
234    ///
235    /// # Panics
236    ///
237    /// Panics if the dimension is out of bounds.
238    #[inline]
239    pub fn dim(&self, index: usize) -> usize {
240        self.mapping().dim(index)
241    }
242
243    /// Returns an expression over the array slice.
244    #[inline]
245    pub fn expr(&self) -> View<'_, T, S, L> {
246        unsafe { View::new_unchecked(self.as_ptr(), self.mapping().clone()) }
247    }
248
249    /// Returns a mutable expression over the array slice.
250    #[inline]
251    pub fn expr_mut(&mut self) -> ViewMut<'_, T, S, L> {
252        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), self.mapping().clone()) }
253    }
254
255    /// Fills the array slice with elements by cloning `value`.
256    #[inline]
257    pub fn fill(&mut self, value: T)
258    where
259        T: Clone,
260    {
261        self.expr_mut().for_each(|x| x.clone_from(&value));
262    }
263
264    /// Fills the array slice with elements returned by calling a closure repeatedly.
265    #[inline]
266    pub fn fill_with<F: FnMut() -> T>(&mut self, mut f: F) {
267        self.expr_mut().for_each(|x| *x = f());
268    }
269
270    /// Returns a one-dimensional array view of the array slice.
271    ///
272    /// # Panics
273    ///
274    /// Panics if the array layout is not uniformly strided.
275    #[inline]
276    pub fn flatten(&self) -> View<'_, T, (Dyn,), L> {
277        self.reshape([self.len()])
278    }
279
280    /// Returns a mutable one-dimensional array view over the array slice.
281    ///
282    /// # Panics
283    ///
284    /// Panics if the array layout is not uniformly strided.
285    #[inline]
286    pub fn flatten_mut(&mut self) -> ViewMut<'_, T, (Dyn,), L> {
287        self.reshape_mut([self.len()])
288    }
289
290    /// Returns a reference to an element or a subslice, without doing bounds checking.
291    ///
292    /// # Safety
293    ///
294    /// The index must be within bounds of the array slice.
295    #[inline]
296    pub unsafe fn get_unchecked<I: SliceIndex<T, S, L>>(&self, index: I) -> &I::Output {
297        unsafe { index.get_unchecked(self) }
298    }
299
300    /// Returns a mutable reference to an element or a subslice, without doing bounds checking.
301    ///
302    /// # Safety
303    ///
304    /// The index must be within bounds of the array slice.
305    #[inline]
306    pub unsafe fn get_unchecked_mut<I: SliceIndex<T, S, L>>(&mut self, index: I) -> &mut I::Output {
307        unsafe { index.get_unchecked_mut(self) }
308    }
309
310    /// Returns `true` if the array strides are consistent with contiguous memory layout.
311    #[inline]
312    pub fn is_contiguous(&self) -> bool {
313        self.mapping().is_contiguous()
314    }
315
316    /// Returns `true` if the array contains no elements.
317    #[inline]
318    pub fn is_empty(&self) -> bool {
319        self.mapping().is_empty()
320    }
321
322    /// Returns an iterator over the array slice.
323    #[inline]
324    pub fn iter(&self) -> Iter<View<'_, T, S, L>> {
325        self.expr().into_iter()
326    }
327
328    /// Returns a mutable iterator over the array slice.
329    #[inline]
330    pub fn iter_mut(&mut self) -> Iter<ViewMut<'_, T, S, L>> {
331        self.expr_mut().into_iter()
332    }
333
334    /// Returns an expression that gives array views over the specified dimension,
335    /// iterating over the other dimensions.
336    ///
337    /// If the dimension to give array views over is know at compile time, the resulting
338    /// shape will maintain a constant-sized dimension. Furthermore, if it is the last
339    /// dimension the resulting array views have the same layout as the input.
340    ///
341    /// # Panics
342    ///
343    /// Panics if the dimension is out of bounds.
344    #[inline]
345    pub fn lanes<A: Axis>(&self, axis: A) -> Lanes<'_, T, S, L, A> {
346        Lanes::new(self, axis)
347    }
348
349    /// Returns a mutable expression that gives array views over the specified dimension,
350    /// iterating over the other dimensions.
351    ///
352    /// If the dimension to give array views over is know at compile time, the resulting
353    /// shape will maintain a constant-sized dimension. Furthermore, if it is the last
354    /// dimension the resulting array views have the same layout as the input.
355    ///
356    /// # Panics
357    ///
358    /// Panics if the dimension is out of bounds.
359    #[inline]
360    pub fn lanes_mut<A: Axis>(&mut self, axis: A) -> LanesMut<'_, T, S, L, A> {
361        LanesMut::new(self, axis)
362    }
363
364    /// Returns the number of elements in the array.
365    #[inline]
366    pub fn len(&self) -> usize {
367        self.mapping().len()
368    }
369
370    /// Returns the array layout mapping.
371    #[inline]
372    pub fn mapping(&self) -> &L::Mapping<S> {
373        if mem::size_of::<L::Mapping<S>>() > 0 {
374            RawSlice::from_slice(self).mapping()
375        } else {
376            unsafe { &*NonNull::dangling().as_ptr() }
377        }
378    }
379
380    /// Returns an expression that gives array views iterating over the first dimension.
381    ///
382    /// Iterating over the first dimension results in array views with the same layout
383    /// as the input.
384    ///
385    /// # Panics
386    ///
387    /// Panics if the rank is not at least 1.
388    #[inline]
389    pub fn outer_expr(&self) -> AxisExpr<'_, T, S, L, Const<0>> {
390        self.axis_expr(Const::<0>)
391    }
392
393    /// Returns a mutable expression that gives array views iterating over the first dimension.
394    ///
395    /// Iterating over the first dimension results in array views with the same layout
396    /// as the input.
397    ///
398    /// # Panics
399    ///
400    /// Panics if the rank is not at least 1.
401    #[inline]
402    pub fn outer_expr_mut(&mut self) -> AxisExprMut<'_, T, S, L, Const<0>> {
403        self.axis_expr_mut(Const::<0>)
404    }
405
406    /// Returns an array view with the dimensions permuted.
407    ///
408    /// If the permutation is an identity permutation and known at compile time, the
409    /// resulting array view has the same layout as the input. For example, permuting
410    /// with `(Const::<0>, Const::<1>)` will maintain the layout while permuting with
411    /// `[0, 1]` gives strided layout.
412    ///
413    /// # Panics
414    ///
415    /// Panics if the permutation is not valid.
416    #[inline]
417    pub fn permute<I: IntoShape<IntoShape: Permutation>>(
418        &self,
419        perm: I,
420    ) -> View<
421        '_,
422        T,
423        <I::IntoShape as Permutation>::Shape<S>,
424        <I::IntoShape as Permutation>::Layout<L>,
425    > {
426        let mapping = perm.into_dims(|dims| Mapping::permute(self.mapping(), dims));
427
428        unsafe { View::new_unchecked(self.as_ptr(), mapping) }
429    }
430
431    /// Returns a mutable array view with the dimensions permuted.
432    ///
433    /// If the permutation is an identity permutation and known at compile time, the
434    /// resulting array view has the same layout as the input. For example, permuting
435    /// with `(Const::<0>, Const::<1>)` will maintain the layout while permuting with
436    /// `[0, 1]` gives strided layout.
437    ///
438    /// # Panics
439    ///
440    /// Panics if the permutation is not valid.
441    #[inline]
442    pub fn permute_mut<I: IntoShape<IntoShape: Permutation>>(
443        &mut self,
444        perm: I,
445    ) -> ViewMut<
446        '_,
447        T,
448        <I::IntoShape as Permutation>::Shape<S>,
449        <I::IntoShape as Permutation>::Layout<L>,
450    > {
451        let mapping = perm.into_dims(|dims| Mapping::permute(self.mapping(), dims));
452
453        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
454    }
455
456    /// Returns the array rank, i.e. the number of dimensions.
457    #[inline]
458    pub fn rank(&self) -> usize {
459        self.mapping().rank()
460    }
461
462    /// Returns a remapped array view of the array slice.
463    ///
464    /// # Panics
465    ///
466    /// Panics if the memory layout is not compatible with the new array layout.
467    #[inline]
468    pub fn remap<R: Shape, K: Layout>(&self) -> View<'_, T, R, K> {
469        let mapping = Mapping::remap(self.mapping());
470
471        unsafe { View::new_unchecked(self.as_ptr(), mapping) }
472    }
473
474    /// Returns a mutable remapped array view of the array slice.
475    ///
476    /// # Panics
477    ///
478    /// Panics if the memory layout is not compatible with the new array layout.
479    #[inline]
480    pub fn remap_mut<R: Shape, K: Layout>(&mut self) -> ViewMut<'_, T, R, K> {
481        let mapping = Mapping::remap(self.mapping());
482
483        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
484    }
485
486    /// Returns a reordered array view of the array slice.
487    ///
488    /// This method is deprecated, use `transpose` instead.
489    #[deprecated]
490    #[inline]
491    pub fn reorder(&self) -> View<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
492        let mapping = Mapping::transpose(self.mapping());
493
494        unsafe { View::new_unchecked(self.as_ptr(), mapping) }
495    }
496
497    /// Returns a mutable reordered array view of the array slice.
498    ///
499    /// This method is deprecated, use `transpose_mut` instead.
500    #[deprecated]
501    #[inline]
502    pub fn reorder_mut(&mut self) -> ViewMut<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
503        let mapping = Mapping::transpose(self.mapping());
504
505        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
506    }
507
508    /// Returns a reshaped array view of the array slice.
509    ///
510    /// At most one dimension can have dynamic size `usize::MAX`, and is then inferred
511    /// from the other dimensions and the array length.
512    ///
513    /// # Examples
514    ///
515    /// ```
516    /// use mdarray::view;
517    ///
518    /// let v = view![[1, 2, 3], [4, 5, 6]];
519    ///
520    /// assert_eq!(v.reshape([!0, 2]), view![[1, 2], [3, 4], [5, 6]]);
521    /// ```
522    ///
523    /// # Panics
524    ///
525    /// Panics if the array length is changed, or if the memory layout is not compatible.
526    #[inline]
527    pub fn reshape<I: IntoShape>(&self, shape: I) -> View<'_, T, I::IntoShape, L> {
528        let mapping = self.mapping().reshape(shape.into_shape());
529
530        unsafe { View::new_unchecked(self.as_ptr(), mapping) }
531    }
532
533    /// Returns a mutable reshaped array view of the array slice.
534    ///
535    /// At most one dimension can have dynamic size `usize::MAX`, and is then inferred
536    /// from the other dimensions and the array length.
537    ///
538    /// See the `reshape` method above for examples.
539    ///
540    /// # Panics
541    ///
542    /// Panics if the array length is changed, or if the memory layout is not compatible.
543    #[inline]
544    pub fn reshape_mut<I: IntoShape>(&mut self, shape: I) -> ViewMut<'_, T, I::IntoShape, L> {
545        let mapping = self.mapping().reshape(shape.into_shape());
546
547        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
548    }
549
550    /// Returns an array view for the specified row.
551    ///
552    /// # Panics
553    ///
554    /// Panics if the rank is not equal to 2, or if the index is out of bounds.
555    #[inline]
556    pub fn row(&self, index: usize) -> View<'_, T, (<S::Tail as Shape>::Head,), L> {
557        let shape = self.shape().with_dims(<(S::Head, _)>::from_dims);
558
559        self.reshape(shape).into_view(index, ..)
560    }
561
562    /// Returns a mutable array view for the specified row.
563    ///
564    /// # Panics
565    ///
566    /// Panics if the rank is not equal to 2, or if the index is out of bounds.
567    #[inline]
568    pub fn row_mut(&mut self, index: usize) -> ViewMut<'_, T, (<S::Tail as Shape>::Head,), L> {
569        let shape = self.shape().with_dims(<(S::Head, _)>::from_dims);
570
571        self.reshape_mut(shape).into_view(index, ..)
572    }
573
574    /// Returns an expression that gives row views iterating over the other dimensions.
575    ///
576    /// # Panics
577    ///
578    /// Panics if the rank is not at least 1.
579    #[inline]
580    pub fn rows(&self) -> Lanes<'_, T, S, L, Rows> {
581        self.lanes(Rows)
582    }
583
584    /// Returns a mutable expression that gives row views iterating over the other dimensions.
585    ///
586    /// # Panics
587    ///
588    /// Panics if the rank is not at least 1.
589    #[inline]
590    pub fn rows_mut(&mut self) -> LanesMut<'_, T, S, L, Rows> {
591        self.lanes_mut(Rows)
592    }
593
594    /// Returns the array shape.
595    #[inline]
596    pub fn shape(&self) -> &S {
597        self.mapping().shape()
598    }
599
600    /// Divides an array slice into two at an index along the first dimension.
601    ///
602    /// # Panics
603    ///
604    /// Panics if the split point is larger than the number of elements in that dimension,
605    /// or if the rank is not at least 1.
606    #[inline]
607    pub fn split_at(
608        &self,
609        mid: usize,
610    ) -> (View<'_, T, Resize<Const<0>, S>, L>, View<'_, T, Resize<Const<0>, S>, L>) {
611        self.split_axis_at(Const::<0>, mid)
612    }
613
614    /// Divides a mutable array slice into two at an index along the first dimension.
615    ///
616    /// # Panics
617    ///
618    /// Panics if the split point is larger than the number of elements in that dimension,
619    /// or if the rank is not at least 1.
620    #[inline]
621    pub fn split_at_mut(
622        &mut self,
623        mid: usize,
624    ) -> (ViewMut<'_, T, Resize<Const<0>, S>, L>, ViewMut<'_, T, Resize<Const<0>, S>, L>) {
625        self.split_axis_at_mut(Const::<0>, mid)
626    }
627
628    /// Divides an array slice into two at an index along the specified dimension.
629    ///
630    /// If the dimension to be divided is know at compile time, the resulting array
631    /// shape will maintain constant-sized dimensions. Furthermore, if it is the first
632    /// dimension the resulting array views have the same layout as the input.
633    ///
634    /// # Panics
635    ///
636    /// Panics if the split point is larger than the number of elements in that dimension,
637    /// or if the dimension is out of bounds.
638    #[inline]
639    pub fn split_axis_at<A: Axis>(
640        &self,
641        axis: A,
642        mid: usize,
643    ) -> (View<'_, T, Resize<A, S>, Split<A, S, L>>, View<'_, T, Resize<A, S>, Split<A, S, L>>)
644    {
645        unsafe { View::split_axis_at(self.as_ptr(), self.mapping(), axis, mid) }
646    }
647
648    /// Divides a mutable array slice into two at an index along the specified dimension.
649    ///
650    /// If the dimension to be divided is know at compile time, the resulting array
651    /// shape will maintain constant-sized dimensions. Furthermore, if it is the first
652    /// dimension the resulting array views have the same layout as the input.
653    ///
654    /// # Panics
655    ///
656    /// Panics if the split point is larger than the number of elements in that dimension,
657    /// or if the dimension is out of bounds.
658    #[inline]
659    pub fn split_axis_at_mut<A: Axis>(
660        &mut self,
661        axis: A,
662        mid: usize,
663    ) -> (ViewMut<'_, T, Resize<A, S>, Split<A, S, L>>, ViewMut<'_, T, Resize<A, S>, Split<A, S, L>>)
664    {
665        unsafe { ViewMut::split_axis_at(self.as_mut_ptr(), self.mapping(), axis, mid) }
666    }
667
668    /// Returns the distance between elements in the specified dimension.
669    ///
670    /// # Panics
671    ///
672    /// Panics if the dimension is out of bounds.
673    #[inline]
674    pub fn stride(&self, index: usize) -> isize {
675        self.mapping().stride(index)
676    }
677
678    /// Swaps two elements in the array slice.
679    ///
680    /// # Panics
681    ///
682    /// Panics if `a` or `b` are out of bounds.
683    #[inline]
684    pub fn swap<I, J>(&mut self, a: I, b: J)
685    where
686        I: SliceIndex<T, S, L, Output = T>,
687        J: SliceIndex<T, S, L, Output = T>,
688    {
689        unsafe {
690            ptr::swap(&raw mut self[a], &raw mut self[b]);
691        }
692    }
693
694    /// Swaps the elements in two subarrays after indexing the specified dimension.
695    ///
696    /// # Panics
697    ///
698    /// Panics if `a` or `b` are out of bounds.
699    #[inline]
700    pub fn swap_axis<A: Axis>(&mut self, axis: A, a: usize, b: usize) {
701        let size = self.dim(axis.index(self.rank()));
702
703        if a >= size {
704            index::panic_bounds_check(a, size);
705        }
706
707        if b >= size {
708            index::panic_bounds_check(b, size);
709        }
710
711        if a != b {
712            let (mut first, mut second) = self.split_axis_at_mut(axis, a.max(b));
713
714            let first = first.axis_at_mut(axis, a.min(b));
715            let second = second.axis_at_mut(axis, 0);
716
717            first.zip(second).for_each(|(x, y)| mem::swap(x, y));
718        }
719    }
720
721    /// Copies the array slice into a new array.
722    #[inline]
723    pub fn to_array(&self) -> Array<T, S>
724    where
725        T: Clone,
726        S: ConstShape,
727    {
728        Array::from(self)
729    }
730
731    /// Copies the array slice into a new array.
732    #[inline]
733    pub fn to_tensor(&self) -> Tensor<T, S>
734    where
735        T: Clone,
736    {
737        Tensor::from(self)
738    }
739
740    /// Copies the array slice into a new array with the specified allocator.
741    #[cfg(feature = "nightly")]
742    #[inline]
743    pub fn to_tensor_in<A: Allocator>(&self, alloc: A) -> Tensor<T, S, A>
744    where
745        T: Clone,
746    {
747        Tensor::from_expr_in(self.expr().cloned(), alloc)
748    }
749
750    /// Copies the array slice into a new vector.
751    #[inline]
752    pub fn to_vec(&self) -> Vec<T>
753    where
754        T: Clone,
755    {
756        self.to_tensor().into_vec()
757    }
758
759    /// Copies the array slice into a new vector with the specified allocator.
760    #[cfg(feature = "nightly")]
761    #[inline]
762    pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
763    where
764        T: Clone,
765    {
766        self.to_tensor_in(alloc).into_vec()
767    }
768
769    /// Returns a transposed array view of the array slice, where the dimensions
770    /// are reversed.
771    #[inline]
772    pub fn transpose(&self) -> View<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
773        let mapping = Mapping::transpose(self.mapping());
774
775        unsafe { View::new_unchecked(self.as_ptr(), mapping) }
776    }
777
778    /// Returns a mutable transposed array view of the array slice, where the dimensions
779    /// are reversed.
780    #[inline]
781    pub fn transpose_mut(&mut self) -> ViewMut<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
782        let mapping = Mapping::transpose(self.mapping());
783
784        unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
785    }
786}
787
788impl<T, L: Layout> Slice<T, DynRank, L> {
789    /// Returns the number of elements in each dimension.
790    #[inline]
791    pub fn dims(&self) -> &[usize] {
792        self.mapping().dims()
793    }
794}
795
796impl<T, S: Shape> Slice<T, S, Strided> {
797    /// Returns the distance between elements in each dimension.
798    #[inline]
799    pub fn strides(&self) -> &[isize] {
800        self.mapping().strides()
801    }
802}
803
804macro_rules! impl_view {
805    (($($xyz:tt),+), ($($abc:tt),+), ($($idx:tt),+)) => {
806        impl<T, $($xyz: Dim,)+ L: Layout> Slice<T, ($($xyz,)+), L> {
807            /// Copies the specified subarray into a new array.
808            ///
809            /// # Panics
810            ///
811            /// Panics if the subarray is out of bounds.
812            #[inline]
813            pub fn array<$($abc: DimIndex),+>(
814                &self,
815                $($idx: $abc),+
816            ) -> Array<T, <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>>
817            where
818                T: Clone,
819                ($($abc,)+): ViewIndex<Shape<($($xyz,)+)>: ConstShape>,
820            {
821                self.view($($idx),+).to_array()
822            }
823
824            /// Copies the specified subarray into a new array.
825            ///
826            /// # Panics
827            ///
828            /// Panics if the subarray is out of bounds.
829            #[inline]
830            pub fn tensor<$($abc: DimIndex),+>(
831                &self,
832                $($idx: $abc),+
833            ) -> Tensor<T, <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>>
834            where
835                T: Clone,
836            {
837                self.view($($idx),+).to_tensor()
838            }
839
840            /// Returns an array view for the specified subarray.
841            ///
842            /// # Panics
843            ///
844            /// Panics if the subarray is out of bounds.
845            #[inline]
846            pub fn view<$($abc: DimIndex),+>(
847                &self,
848                $($idx: $abc),+
849            ) -> View<
850                '_,
851                T,
852                <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>,
853                <($($abc,)+) as ViewIndex>::Layout<L>,
854            > {
855                self.expr().into_view($($idx),+)
856            }
857
858            /// Returns a mutable array view for the specified subarray.
859            ///
860            /// # Panics
861            ///
862            /// Panics if the subarray is out of bounds.
863            #[inline]
864            pub fn view_mut<$($abc: DimIndex),+>(
865                &mut self,
866                $($idx: $abc),+,
867            ) -> ViewMut<
868                '_,
869                T,
870                <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>,
871                <($($abc,)+) as ViewIndex>::Layout<L>,
872            > {
873                self.expr_mut().into_view($($idx),+)
874            }
875        }
876    };
877}
878
879impl_view!((X), (A), (a));
880impl_view!((X, Y), (A, B), (a, b));
881impl_view!((X, Y, Z), (A, B, C), (a, b, c));
882impl_view!((X, Y, Z, W), (A, B, C, D), (a, b, c, d));
883impl_view!((X, Y, Z, W, U), (A, B, C, D, E), (a, b, c, d, e));
884impl_view!((X, Y, Z, W, U, V), (A, B, C, D, E, F), (a, b, c, d, e, f));
885
886impl<'a, T, U, S: Shape, L: Layout> Apply<U> for &'a Slice<T, S, L> {
887    type Output<F: FnMut(&'a T) -> U> = Map<Self::IntoExpr, F>;
888    type ZippedWith<I: IntoExpression, F: FnMut((&'a T, I::Item)) -> U> =
889        Map<Zip<Self::IntoExpr, I::IntoExpr>, F>;
890
891    #[inline]
892    fn apply<F: FnMut(&'a T) -> U>(self, f: F) -> Self::Output<F> {
893        self.expr().map(f)
894    }
895
896    #[inline]
897    fn zip_with<I: IntoExpression, F>(self, expr: I, f: F) -> Self::ZippedWith<I, F>
898    where
899        F: FnMut((&'a T, I::Item)) -> U,
900    {
901        self.expr().zip(expr).map(f)
902    }
903}
904
905impl<'a, T, U, S: Shape, L: Layout> Apply<U> for &'a mut Slice<T, S, L> {
906    type Output<F: FnMut(&'a mut T) -> U> = Map<Self::IntoExpr, F>;
907    type ZippedWith<I: IntoExpression, F: FnMut((&'a mut T, I::Item)) -> U> =
908        Map<Zip<Self::IntoExpr, I::IntoExpr>, F>;
909
910    #[inline]
911    fn apply<F: FnMut(&'a mut T) -> U>(self, f: F) -> Self::Output<F> {
912        self.expr_mut().map(f)
913    }
914
915    #[inline]
916    fn zip_with<I: IntoExpression, F>(self, expr: I, f: F) -> Self::ZippedWith<I, F>
917    where
918        F: FnMut((&'a mut T, I::Item)) -> U,
919    {
920        self.expr_mut().zip(expr).map(f)
921    }
922}
923
924impl<T, S: Shape, L: Layout> AsMut<Self> for Slice<T, S, L> {
925    #[inline]
926    fn as_mut(&mut self) -> &mut Self {
927        self
928    }
929}
930
931impl<T, D: Dim> AsMut<[T]> for Slice<T, (D,)> {
932    #[inline]
933    fn as_mut(&mut self) -> &mut [T] {
934        self.expr_mut().into()
935    }
936}
937
938impl<T, S: Shape, L: Layout> AsRef<Self> for Slice<T, S, L> {
939    #[inline]
940    fn as_ref(&self) -> &Self {
941        self
942    }
943}
944
945impl<T, D: Dim> AsRef<[T]> for Slice<T, (D,)> {
946    #[inline]
947    fn as_ref(&self) -> &[T] {
948        self.expr().into()
949    }
950}
951
952macro_rules! impl_as_mut_ref {
953    (($($xyz:tt),+), $array:tt) => {
954        impl<T, $(const $xyz: usize),+> AsMut<$array> for Slice<T, ($(Const<$xyz>,)+)> {
955            #[inline]
956            fn as_mut(&mut self) -> &mut $array {
957                unsafe { &mut *(self as *mut Self as *mut $array) }
958            }
959        }
960
961        impl<T, $(const $xyz: usize),+> AsRef<$array> for Slice<T, ($(Const<$xyz>,)+)> {
962            #[inline]
963            fn as_ref(&self) -> &$array {
964                unsafe { &*(self as *const Self as *const $array) }
965            }
966        }
967    };
968}
969
970impl_as_mut_ref!((X), [T; X]);
971impl_as_mut_ref!((X, Y), [[T; Y]; X]);
972impl_as_mut_ref!((X, Y, Z), [[[T; Z]; Y]; X]);
973impl_as_mut_ref!((X, Y, Z, W), [[[[T; W]; Z]; Y]; X]);
974impl_as_mut_ref!((X, Y, Z, W, U), [[[[[T; U]; W]; Z]; Y]; X]);
975impl_as_mut_ref!((X, Y, Z, W, U, V), [[[[[[T; V]; U]; W]; Z]; Y]; X]);
976
977impl<T: Debug, S: Shape, L: Layout> Debug for Slice<T, S, L> {
978    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
979        if self.rank() == 0 {
980            self[[]].fmt(f)
981        } else {
982            f.debug_list().entries(self.outer_expr()).finish()
983        }
984    }
985}
986
987impl<T: Hash, S: Shape, L: Layout> Hash for Slice<T, S, L> {
988    #[inline]
989    fn hash<H: Hasher>(&self, state: &mut H) {
990        for i in 0..self.rank() {
991            #[cfg(not(feature = "nightly"))]
992            state.write_usize(self.dim(i));
993            #[cfg(feature = "nightly")]
994            state.write_length_prefix(self.dim(i));
995        }
996
997        self.expr().for_each(|x| x.hash(state));
998    }
999}
1000
1001impl<T, S: Shape, L: Layout, I: SliceIndex<T, S, L>> Index<I> for Slice<T, S, L> {
1002    type Output = I::Output;
1003
1004    #[inline]
1005    fn index(&self, index: I) -> &I::Output {
1006        index.index(self)
1007    }
1008}
1009
1010impl<T, S: Shape, L: Layout, I: SliceIndex<T, S, L>> IndexMut<I> for Slice<T, S, L> {
1011    #[inline]
1012    fn index_mut(&mut self, index: I) -> &mut I::Output {
1013        index.index_mut(self)
1014    }
1015}
1016
1017impl<'a, T, S: Shape, L: Layout> IntoExpression for &'a Slice<T, S, L> {
1018    type Shape = S;
1019    type IntoExpr = View<'a, T, S, L>;
1020
1021    #[inline]
1022    fn into_expr(self) -> Self::IntoExpr {
1023        self.expr()
1024    }
1025}
1026
1027impl<'a, T, S: Shape, L: Layout> IntoExpression for &'a mut Slice<T, S, L> {
1028    type Shape = S;
1029    type IntoExpr = ViewMut<'a, T, S, L>;
1030
1031    #[inline]
1032    fn into_expr(self) -> Self::IntoExpr {
1033        self.expr_mut()
1034    }
1035}
1036
1037impl<'a, T, S: Shape, L: Layout> IntoIterator for &'a Slice<T, S, L> {
1038    type Item = &'a T;
1039    type IntoIter = Iter<View<'a, T, S, L>>;
1040
1041    #[inline]
1042    fn into_iter(self) -> Self::IntoIter {
1043        self.iter()
1044    }
1045}
1046
1047impl<'a, T, S: Shape, L: Layout> IntoIterator for &'a mut Slice<T, S, L> {
1048    type Item = &'a mut T;
1049    type IntoIter = Iter<ViewMut<'a, T, S, L>>;
1050
1051    #[inline]
1052    fn into_iter(self) -> Self::IntoIter {
1053        self.iter_mut()
1054    }
1055}
1056
1057impl<T: Clone, S: Shape> ToOwned for Slice<T, S> {
1058    type Owned = S::Owned<T>;
1059
1060    #[inline]
1061    fn to_owned(&self) -> Self::Owned {
1062        FromExpression::from_expr(self.into_expr().cloned())
1063    }
1064
1065    #[inline]
1066    fn clone_into(&self, target: &mut Self::Owned) {
1067        target.clone_from_slice(self);
1068    }
1069}
1070
1071#[inline]
1072fn contains<T: PartialEq, S: Shape, L: Layout>(this: &Slice<T, S, L>, value: &T) -> bool {
1073    if L::IS_DENSE {
1074        this.remap::<S, _>()[..].contains(value)
1075    } else if this.rank() < 2 {
1076        this.iter().any(|x| x == value)
1077    } else {
1078        this.outer_expr().into_iter().any(|x| x.contains(value))
1079    }
1080}