#[cfg(feature = "nightly")]
use alloc::alloc::Allocator;
#[cfg(not(feature = "std"))]
use alloc::borrow::ToOwned;
#[cfg(not(feature = "std"))]
use alloc::vec::Vec;
use core::fmt::{Debug, Formatter, Result};
use core::hash::{Hash, Hasher};
use core::marker::PhantomData;
use core::mem;
use core::ops::{Index, IndexMut};
use core::ptr::{self, NonNull};
use crate::array::Array;
use crate::dim::{Const, Dim, Dyn};
use crate::expr::{Apply, Expression, FromExpression, IntoExpression};
use crate::expr::{AxisExpr, AxisExprMut, Iter, Lanes, LanesMut, Map, Zip};
use crate::index::{self, Axis, Cols, Resize, Rows, Split};
use crate::index::{DimIndex, Permutation, SliceIndex, ViewIndex};
use crate::layout::{Dense, Layout, Strided};
use crate::mapping::Mapping;
use crate::raw_slice::RawSlice;
use crate::shape::{ConstShape, DynRank, IntoShape, Rank, Shape};
use crate::tensor::Tensor;
use crate::traits::{IntoCloned, Owned};
use crate::view::{View, ViewMut};
pub struct Slice<T, S: Shape = DynRank, L: Layout = Dense> {
phantom: PhantomData<(T, S, L)>,
}
pub type DSlice<T, const N: usize, L = Dense> = Slice<T, Rank<N>, L>;
impl<T, S: Shape, L: Layout> Slice<T, S, L> {
#[inline]
pub fn as_mut_ptr(&mut self) -> *mut T {
if mem::size_of::<L::Mapping<S>>() > 0 {
RawSlice::from_mut_slice(self).as_mut_ptr()
} else {
self as *mut Self as *mut T
}
}
#[inline]
pub fn as_ptr(&self) -> *const T {
if mem::size_of::<L::Mapping<S>>() > 0 {
RawSlice::from_slice(self).as_ptr()
} else {
self as *const Self as *const T
}
}
#[inline]
pub fn assign<I: IntoExpression<Item: IntoCloned<T>>>(&mut self, expr: I) {
self.expr_mut().zip(expr).for_each(|(x, y)| y.clone_to(x));
}
#[inline]
pub fn at(&self, index: usize) -> View<'_, T, S::Tail, L> {
self.axis_at(Const::<0>, index)
}
#[inline]
pub fn at_mut(&mut self, index: usize) -> ViewMut<'_, T, S::Tail, L> {
self.axis_at_mut(Const::<0>, index)
}
#[inline]
pub fn axis_at<A: Axis>(
&self,
axis: A,
index: usize,
) -> View<'_, T, A::Remove<S>, Split<A, S, L>> {
unsafe { View::axis_at(self.as_ptr(), self.mapping(), axis, index) }
}
#[inline]
pub fn axis_at_mut<A: Axis>(
&mut self,
axis: A,
index: usize,
) -> ViewMut<'_, T, A::Remove<S>, Split<A, S, L>> {
unsafe { ViewMut::axis_at(self.as_mut_ptr(), self.mapping(), axis, index) }
}
#[inline]
pub fn axis_expr<A: Axis>(&self, axis: A) -> AxisExpr<'_, T, S, L, A> {
AxisExpr::new(self, axis)
}
#[inline]
pub fn axis_expr_mut<A: Axis>(&mut self, axis: A) -> AxisExprMut<'_, T, S, L, A> {
AxisExprMut::new(self, axis)
}
#[inline]
pub fn col(&self, index: usize) -> View<'_, T, (S::Head,), Strided> {
let shape = self.shape().with_dims(<(_, <S::Tail as Shape>::Head)>::from_dims);
self.reshape(shape).into_view(.., index)
}
#[inline]
pub fn col_mut(&mut self, index: usize) -> ViewMut<'_, T, (S::Head,), Strided> {
let shape = self.shape().with_dims(<(_, <S::Tail as Shape>::Head)>::from_dims);
self.reshape_mut(shape).into_view(.., index)
}
#[inline]
pub fn cols(&self) -> Lanes<'_, T, S, L, Cols> {
self.lanes(Cols)
}
#[inline]
pub fn cols_mut(&mut self) -> LanesMut<'_, T, S, L, Cols> {
self.lanes_mut(Cols)
}
#[inline]
pub fn contains(&self, x: &T) -> bool
where
T: PartialEq,
{
contains(self, x)
}
#[inline]
pub fn diag(&self, index: isize) -> View<'_, T, (Dyn,), Strided> {
let shape = self.shape().with_dims(<(S::Head, <S::Tail as Shape>::Head)>::from_dims);
self.reshape(shape).into_diag(index)
}
#[inline]
pub fn diag_mut(&mut self, index: isize) -> ViewMut<'_, T, (Dyn,), Strided> {
let shape = self.shape().with_dims(<(S::Head, <S::Tail as Shape>::Head)>::from_dims);
self.reshape_mut(shape).into_diag(index)
}
#[inline]
pub fn dim(&self, index: usize) -> usize {
self.mapping().dim(index)
}
#[inline]
pub fn expr(&self) -> View<'_, T, S, L> {
unsafe { View::new_unchecked(self.as_ptr(), self.mapping().clone()) }
}
#[inline]
pub fn expr_mut(&mut self) -> ViewMut<'_, T, S, L> {
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), self.mapping().clone()) }
}
#[inline]
pub fn fill(&mut self, value: T)
where
T: Clone,
{
self.expr_mut().for_each(|x| x.clone_from(&value));
}
#[inline]
pub fn fill_with<F: FnMut() -> T>(&mut self, mut f: F) {
self.expr_mut().for_each(|x| *x = f());
}
#[inline]
pub fn flatten(&self) -> View<'_, T, (Dyn,), L> {
self.reshape([self.len()])
}
#[inline]
pub fn flatten_mut(&mut self) -> ViewMut<'_, T, (Dyn,), L> {
self.reshape_mut([self.len()])
}
#[inline]
pub unsafe fn get_unchecked<I: SliceIndex<T, S, L>>(&self, index: I) -> &I::Output {
unsafe { index.get_unchecked(self) }
}
#[inline]
pub unsafe fn get_unchecked_mut<I: SliceIndex<T, S, L>>(&mut self, index: I) -> &mut I::Output {
unsafe { index.get_unchecked_mut(self) }
}
#[inline]
pub fn is_contiguous(&self) -> bool {
self.mapping().is_contiguous()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.mapping().is_empty()
}
#[inline]
pub fn iter(&self) -> Iter<View<'_, T, S, L>> {
self.expr().into_iter()
}
#[inline]
pub fn iter_mut(&mut self) -> Iter<ViewMut<'_, T, S, L>> {
self.expr_mut().into_iter()
}
#[inline]
pub fn lanes<A: Axis>(&self, axis: A) -> Lanes<'_, T, S, L, A> {
Lanes::new(self, axis)
}
#[inline]
pub fn lanes_mut<A: Axis>(&mut self, axis: A) -> LanesMut<'_, T, S, L, A> {
LanesMut::new(self, axis)
}
#[inline]
pub fn len(&self) -> usize {
self.mapping().len()
}
#[inline]
pub fn mapping(&self) -> &L::Mapping<S> {
if mem::size_of::<L::Mapping<S>>() > 0 {
RawSlice::from_slice(self).mapping()
} else {
unsafe { &*NonNull::dangling().as_ptr() }
}
}
#[inline]
pub fn outer_expr(&self) -> AxisExpr<'_, T, S, L, Const<0>> {
self.axis_expr(Const::<0>)
}
#[inline]
pub fn outer_expr_mut(&mut self) -> AxisExprMut<'_, T, S, L, Const<0>> {
self.axis_expr_mut(Const::<0>)
}
#[inline]
pub fn permute<I: IntoShape<IntoShape: Permutation>>(
&self,
perm: I,
) -> View<
'_,
T,
<I::IntoShape as Permutation>::Shape<S>,
<I::IntoShape as Permutation>::Layout<L>,
> {
let mapping = perm.into_dims(|dims| Mapping::permute(self.mapping(), dims));
unsafe { View::new_unchecked(self.as_ptr(), mapping) }
}
#[inline]
pub fn permute_mut<I: IntoShape<IntoShape: Permutation>>(
&mut self,
perm: I,
) -> ViewMut<
'_,
T,
<I::IntoShape as Permutation>::Shape<S>,
<I::IntoShape as Permutation>::Layout<L>,
> {
let mapping = perm.into_dims(|dims| Mapping::permute(self.mapping(), dims));
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
}
#[inline]
pub fn rank(&self) -> usize {
self.mapping().rank()
}
#[inline]
pub fn remap<R: Shape, K: Layout>(&self) -> View<'_, T, R, K> {
let mapping = Mapping::remap(self.mapping());
unsafe { View::new_unchecked(self.as_ptr(), mapping) }
}
#[inline]
pub fn remap_mut<R: Shape, K: Layout>(&mut self) -> ViewMut<'_, T, R, K> {
let mapping = Mapping::remap(self.mapping());
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
}
#[deprecated]
#[inline]
pub fn reorder(&self) -> View<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
let mapping = Mapping::transpose(self.mapping());
unsafe { View::new_unchecked(self.as_ptr(), mapping) }
}
#[deprecated]
#[inline]
pub fn reorder_mut(&mut self) -> ViewMut<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
let mapping = Mapping::transpose(self.mapping());
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
}
#[inline]
pub fn reshape<I: IntoShape>(&self, shape: I) -> View<'_, T, I::IntoShape, L> {
let mapping = self.mapping().reshape(shape.into_shape());
unsafe { View::new_unchecked(self.as_ptr(), mapping) }
}
#[inline]
pub fn reshape_mut<I: IntoShape>(&mut self, shape: I) -> ViewMut<'_, T, I::IntoShape, L> {
let mapping = self.mapping().reshape(shape.into_shape());
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
}
#[inline]
pub fn row(&self, index: usize) -> View<'_, T, (<S::Tail as Shape>::Head,), L> {
let shape = self.shape().with_dims(<(S::Head, _)>::from_dims);
self.reshape(shape).into_view(index, ..)
}
#[inline]
pub fn row_mut(&mut self, index: usize) -> ViewMut<'_, T, (<S::Tail as Shape>::Head,), L> {
let shape = self.shape().with_dims(<(S::Head, _)>::from_dims);
self.reshape_mut(shape).into_view(index, ..)
}
#[inline]
pub fn rows(&self) -> Lanes<'_, T, S, L, Rows> {
self.lanes(Rows)
}
#[inline]
pub fn rows_mut(&mut self) -> LanesMut<'_, T, S, L, Rows> {
self.lanes_mut(Rows)
}
#[inline]
pub fn shape(&self) -> &S {
self.mapping().shape()
}
#[inline]
pub fn split_at(
&self,
mid: usize,
) -> (View<'_, T, Resize<Const<0>, S>, L>, View<'_, T, Resize<Const<0>, S>, L>) {
self.split_axis_at(Const::<0>, mid)
}
#[inline]
pub fn split_at_mut(
&mut self,
mid: usize,
) -> (ViewMut<'_, T, Resize<Const<0>, S>, L>, ViewMut<'_, T, Resize<Const<0>, S>, L>) {
self.split_axis_at_mut(Const::<0>, mid)
}
#[inline]
pub fn split_axis_at<A: Axis>(
&self,
axis: A,
mid: usize,
) -> (View<'_, T, Resize<A, S>, Split<A, S, L>>, View<'_, T, Resize<A, S>, Split<A, S, L>>)
{
unsafe { View::split_axis_at(self.as_ptr(), self.mapping(), axis, mid) }
}
#[inline]
pub fn split_axis_at_mut<A: Axis>(
&mut self,
axis: A,
mid: usize,
) -> (ViewMut<'_, T, Resize<A, S>, Split<A, S, L>>, ViewMut<'_, T, Resize<A, S>, Split<A, S, L>>)
{
unsafe { ViewMut::split_axis_at(self.as_mut_ptr(), self.mapping(), axis, mid) }
}
#[inline]
pub fn stride(&self, index: usize) -> isize {
self.mapping().stride(index)
}
#[inline]
pub fn swap<I, J>(&mut self, a: I, b: J)
where
I: SliceIndex<T, S, L, Output = T>,
J: SliceIndex<T, S, L, Output = T>,
{
unsafe {
ptr::swap(&raw mut self[a], &raw mut self[b]);
}
}
#[inline]
pub fn swap_axis<A: Axis>(&mut self, axis: A, a: usize, b: usize) {
let size = self.dim(axis.index(self.rank()));
if a >= size {
index::panic_bounds_check(a, size);
}
if b >= size {
index::panic_bounds_check(b, size);
}
if a != b {
let (mut first, mut second) = self.split_axis_at_mut(axis, a.max(b));
let first = first.axis_at_mut(axis, a.min(b));
let second = second.axis_at_mut(axis, 0);
first.zip(second).for_each(|(x, y)| mem::swap(x, y));
}
}
#[inline]
pub fn to_array(&self) -> Array<T, S>
where
T: Clone,
S: ConstShape,
{
Array::from(self)
}
#[inline]
pub fn to_tensor(&self) -> Tensor<T, S>
where
T: Clone,
{
Tensor::from(self)
}
#[cfg(feature = "nightly")]
#[inline]
pub fn to_tensor_in<A: Allocator>(&self, alloc: A) -> Tensor<T, S, A>
where
T: Clone,
{
Tensor::from_expr_in(self.expr().cloned(), alloc)
}
#[inline]
pub fn to_vec(&self) -> Vec<T>
where
T: Clone,
{
self.to_tensor().into_vec()
}
#[cfg(feature = "nightly")]
#[inline]
pub fn to_vec_in<A: Allocator>(&self, alloc: A) -> Vec<T, A>
where
T: Clone,
{
self.to_tensor_in(alloc).into_vec()
}
#[inline]
pub fn transpose(&self) -> View<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
let mapping = Mapping::transpose(self.mapping());
unsafe { View::new_unchecked(self.as_ptr(), mapping) }
}
#[inline]
pub fn transpose_mut(&mut self) -> ViewMut<'_, T, S::Reverse, <S::Tail as Shape>::Layout<L>> {
let mapping = Mapping::transpose(self.mapping());
unsafe { ViewMut::new_unchecked(self.as_mut_ptr(), mapping) }
}
}
impl<T, L: Layout> Slice<T, DynRank, L> {
#[inline]
pub fn dims(&self) -> &[usize] {
self.mapping().dims()
}
}
impl<T, S: Shape> Slice<T, S, Strided> {
#[inline]
pub fn strides(&self) -> &[isize] {
self.mapping().strides()
}
}
macro_rules! impl_view {
(($($xyz:tt),+), ($($abc:tt),+), ($($idx:tt),+)) => {
impl<T, $($xyz: Dim,)+ L: Layout> Slice<T, ($($xyz,)+), L> {
#[inline]
pub fn array<$($abc: DimIndex),+>(
&self,
$($idx: $abc),+
) -> Array<T, <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>>
where
T: Clone,
($($abc,)+): ViewIndex<Shape<($($xyz,)+)>: ConstShape>,
{
self.view($($idx),+).to_array()
}
#[inline]
pub fn tensor<$($abc: DimIndex),+>(
&self,
$($idx: $abc),+
) -> Tensor<T, <($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>>
where
T: Clone,
{
self.view($($idx),+).to_tensor()
}
#[inline]
pub fn view<$($abc: DimIndex),+>(
&self,
$($idx: $abc),+
) -> View<
'_,
T,
<($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>,
<($($abc,)+) as ViewIndex>::Layout<L>,
> {
self.expr().into_view($($idx),+)
}
#[inline]
pub fn view_mut<$($abc: DimIndex),+>(
&mut self,
$($idx: $abc),+,
) -> ViewMut<
'_,
T,
<($($abc,)+) as ViewIndex>::Shape<($($xyz,)+)>,
<($($abc,)+) as ViewIndex>::Layout<L>,
> {
self.expr_mut().into_view($($idx),+)
}
}
};
}
impl_view!((X), (A), (a));
impl_view!((X, Y), (A, B), (a, b));
impl_view!((X, Y, Z), (A, B, C), (a, b, c));
impl_view!((X, Y, Z, W), (A, B, C, D), (a, b, c, d));
impl_view!((X, Y, Z, W, U), (A, B, C, D, E), (a, b, c, d, e));
impl_view!((X, Y, Z, W, U, V), (A, B, C, D, E, F), (a, b, c, d, e, f));
impl<'a, T, U, S: Shape, L: Layout> Apply<U> for &'a Slice<T, S, L> {
type Output<F: FnMut(&'a T) -> U> = Map<Self::IntoExpr, F>;
type ZippedWith<I: IntoExpression, F: FnMut((&'a T, I::Item)) -> U> =
Map<Zip<Self::IntoExpr, I::IntoExpr>, F>;
#[inline]
fn apply<F: FnMut(&'a T) -> U>(self, f: F) -> Self::Output<F> {
self.expr().map(f)
}
#[inline]
fn zip_with<I: IntoExpression, F>(self, expr: I, f: F) -> Self::ZippedWith<I, F>
where
F: FnMut((&'a T, I::Item)) -> U,
{
self.expr().zip(expr).map(f)
}
}
impl<'a, T, U, S: Shape, L: Layout> Apply<U> for &'a mut Slice<T, S, L> {
type Output<F: FnMut(&'a mut T) -> U> = Map<Self::IntoExpr, F>;
type ZippedWith<I: IntoExpression, F: FnMut((&'a mut T, I::Item)) -> U> =
Map<Zip<Self::IntoExpr, I::IntoExpr>, F>;
#[inline]
fn apply<F: FnMut(&'a mut T) -> U>(self, f: F) -> Self::Output<F> {
self.expr_mut().map(f)
}
#[inline]
fn zip_with<I: IntoExpression, F>(self, expr: I, f: F) -> Self::ZippedWith<I, F>
where
F: FnMut((&'a mut T, I::Item)) -> U,
{
self.expr_mut().zip(expr).map(f)
}
}
impl<T, S: Shape, L: Layout> AsMut<Self> for Slice<T, S, L> {
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<T, D: Dim> AsMut<[T]> for Slice<T, (D,)> {
#[inline]
fn as_mut(&mut self) -> &mut [T] {
self.expr_mut().into()
}
}
impl<T, S: Shape, L: Layout> AsRef<Self> for Slice<T, S, L> {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<T, D: Dim> AsRef<[T]> for Slice<T, (D,)> {
#[inline]
fn as_ref(&self) -> &[T] {
self.expr().into()
}
}
macro_rules! impl_as_mut_ref {
(($($xyz:tt),+), $array:tt) => {
impl<T, $(const $xyz: usize),+> AsMut<$array> for Slice<T, ($(Const<$xyz>,)+)> {
#[inline]
fn as_mut(&mut self) -> &mut $array {
unsafe { &mut *(self as *mut Self as *mut $array) }
}
}
impl<T, $(const $xyz: usize),+> AsRef<$array> for Slice<T, ($(Const<$xyz>,)+)> {
#[inline]
fn as_ref(&self) -> &$array {
unsafe { &*(self as *const Self as *const $array) }
}
}
};
}
impl_as_mut_ref!((X), [T; X]);
impl_as_mut_ref!((X, Y), [[T; Y]; X]);
impl_as_mut_ref!((X, Y, Z), [[[T; Z]; Y]; X]);
impl_as_mut_ref!((X, Y, Z, W), [[[[T; W]; Z]; Y]; X]);
impl_as_mut_ref!((X, Y, Z, W, U), [[[[[T; U]; W]; Z]; Y]; X]);
impl_as_mut_ref!((X, Y, Z, W, U, V), [[[[[[T; V]; U]; W]; Z]; Y]; X]);
impl<T: Debug, S: Shape, L: Layout> Debug for Slice<T, S, L> {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
if self.rank() == 0 {
self[[]].fmt(f)
} else {
f.debug_list().entries(self.outer_expr()).finish()
}
}
}
impl<T: Hash, S: Shape, L: Layout> Hash for Slice<T, S, L> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
for i in 0..self.rank() {
#[cfg(not(feature = "nightly"))]
state.write_usize(self.dim(i));
#[cfg(feature = "nightly")]
state.write_length_prefix(self.dim(i));
}
self.expr().for_each(|x| x.hash(state));
}
}
impl<T, S: Shape, L: Layout, I: SliceIndex<T, S, L>> Index<I> for Slice<T, S, L> {
type Output = I::Output;
#[inline]
fn index(&self, index: I) -> &I::Output {
index.index(self)
}
}
impl<T, S: Shape, L: Layout, I: SliceIndex<T, S, L>> IndexMut<I> for Slice<T, S, L> {
#[inline]
fn index_mut(&mut self, index: I) -> &mut I::Output {
index.index_mut(self)
}
}
impl<'a, T, S: Shape, L: Layout> IntoExpression for &'a Slice<T, S, L> {
type Shape = S;
type IntoExpr = View<'a, T, S, L>;
#[inline]
fn into_expr(self) -> Self::IntoExpr {
self.expr()
}
}
impl<'a, T, S: Shape, L: Layout> IntoExpression for &'a mut Slice<T, S, L> {
type Shape = S;
type IntoExpr = ViewMut<'a, T, S, L>;
#[inline]
fn into_expr(self) -> Self::IntoExpr {
self.expr_mut()
}
}
impl<'a, T, S: Shape, L: Layout> IntoIterator for &'a Slice<T, S, L> {
type Item = &'a T;
type IntoIter = Iter<View<'a, T, S, L>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T, S: Shape, L: Layout> IntoIterator for &'a mut Slice<T, S, L> {
type Item = &'a mut T;
type IntoIter = Iter<ViewMut<'a, T, S, L>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter_mut()
}
}
impl<T: Clone, S: Shape> ToOwned for Slice<T, S> {
type Owned = S::Owned<T>;
#[inline]
fn to_owned(&self) -> Self::Owned {
FromExpression::from_expr(self.into_expr().cloned())
}
#[inline]
fn clone_into(&self, target: &mut Self::Owned) {
target.clone_from_slice(self);
}
}
#[inline]
fn contains<T: PartialEq, S: Shape, L: Layout>(this: &Slice<T, S, L>, value: &T) -> bool {
if L::IS_DENSE {
this.remap::<S, _>()[..].contains(value)
} else if this.rank() < 2 {
this.iter().any(|x| x == value)
} else {
this.outer_expr().into_iter().any(|x| x.contains(value))
}
}