use core::marker::PhantomData;
use super::TensorView;
use crate::tensor::error::TensorError;
use crate::tensor::layout::{ColMajor, RowMajor};
impl<'a, 'b, T, L> TensorView<'a, T, 2, L, &'b [T]> {
#[inline]
pub fn row_view(
&self,
i: usize,
) -> Result<TensorView<'a, T, 1, RowMajor, &'b [T]>, TensorError> {
if i >= self.shape[0] {
return Err(TensorError::IndexOutOfBounds);
}
let row_start = i * self.strides[0];
let row_len = self.shape[1];
let full_slice: &'b [T] = unsafe { &*self.ptr };
let row_data = &full_slice[row_start..row_start + row_len];
TensorView::new(row_data, [row_len])
}
#[inline]
pub fn iter_rows(&self) -> Result<impl Iterator<Item = &'b [T]>, TensorError> {
if !self.is_contiguous() {
return Err(TensorError::NotContiguous);
}
let ncols = self.shape[1];
let full_slice: &'b [T] = unsafe { &*self.ptr };
Ok((0..self.shape[0]).map(move |i| {
let start = i * ncols;
&full_slice[start..start + ncols]
}))
}
#[inline]
pub fn transpose_view(&self) -> TensorView<'a, T, 2, ColMajor, &'b [T]> {
TensorView {
ptr: self.ptr,
shape: [self.shape[1], self.shape[0]],
strides: [self.strides[1], self.strides[0]],
_layout: PhantomData,
}
}
#[inline]
pub fn col_iter(&self, j: usize) -> Result<impl Iterator<Item = T> + '_, TensorError>
where
T: Copy,
{
if j >= self.shape[1] {
return Err(TensorError::IndexOutOfBounds);
}
let nrows = self.shape[0];
let row_str = self.strides[0];
let slice = self.as_slice();
Ok((0..nrows).map(move |i| slice[j + i * row_str]))
}
#[inline]
pub fn diag_iter(&self) -> impl Iterator<Item = T> + '_
where
T: Copy,
{
let diag_len = self.shape[0].min(self.shape[1]);
let diag_str = self.strides[0] + self.strides[1];
let slice = self.as_slice();
(0..diag_len).map(move |i| slice[i * diag_str])
}
}
impl<'a, T, L> TensorView<'a, T, 2, L, &mut [T]> {
#[inline]
pub fn row_view_mut(
&mut self,
i: usize,
) -> Result<TensorView<'a, T, 1, RowMajor, &mut [T]>, TensorError> {
if i >= self.shape[0] {
return Err(TensorError::IndexOutOfBounds);
}
let row_start = i * self.strides[0];
let row_len = self.shape[1];
let slice = unsafe { &mut *self.ptr };
let row_data = &mut slice[row_start..row_start + row_len];
TensorView::new_mut(row_data, [row_len])
}
#[inline]
pub fn iter_rows_mut(&mut self) -> Result<impl Iterator<Item = &mut [T]>, TensorError> {
if !self.is_contiguous() {
return Err(TensorError::NotContiguous);
}
let ncols = self.shape[1];
let slice = unsafe { &mut *self.ptr };
Ok(slice.chunks_exact_mut(ncols))
}
}
impl<'a, T, L> TensorView<'a, T, 3, L, &'a [T]> {
#[inline]
pub fn matrix_at(
&self,
b: usize,
) -> Result<TensorView<'_, T, 2, RowMajor, &'_ [T]>, TensorError> {
if !self.is_contiguous() {
return Err(TensorError::NotContiguous);
}
if b >= self.shape[0] {
return Err(TensorError::IndexOutOfBounds);
}
let rows = self.shape[1];
let cols = self.shape[2];
let start = b * rows * cols;
let full_slice: &[T] = self.as_slice();
let slice = &full_slice[start..start + rows * cols];
TensorView::<'_, T, 2, RowMajor, &'_ [T]>::new(slice, [rows, cols])
}
}
impl<'a, T, L> TensorView<'a, T, 3, L, &'a mut [T]> {
#[inline]
pub fn matrix_at_mut(
&mut self,
b: usize,
) -> Result<TensorView<'_, T, 2, RowMajor, &'_ mut [T]>, TensorError> {
if !self.is_contiguous() {
return Err(TensorError::NotContiguous);
}
if b >= self.shape[0] {
return Err(TensorError::IndexOutOfBounds);
}
let rows = self.shape[1];
let cols = self.shape[2];
let start = b * rows * cols;
let slice = unsafe { &mut *self.ptr };
let sub_slice = &mut slice[start..start + rows * cols];
TensorView::<'_, T, 2, RowMajor, &'_ mut [T]>::new_mut(sub_slice, [rows, cols])
}
}
impl<'a, T, Ref> TensorView<'a, T, 2, RowMajor, Ref> {
#[inline]
pub fn transpose(self) -> TensorView<'a, T, 2, ColMajor, Ref> {
TensorView {
ptr: self.ptr,
shape: [self.shape[1], self.shape[0]],
strides: [self.strides[1], self.strides[0]],
_layout: PhantomData,
}
}
}
impl<'a, T, Ref> TensorView<'a, T, 2, ColMajor, Ref> {
#[inline]
pub fn transpose(self) -> TensorView<'a, T, 2, RowMajor, Ref> {
TensorView {
ptr: self.ptr,
shape: [self.shape[1], self.shape[0]],
strides: [self.strides[1], self.strides[0]],
_layout: PhantomData,
}
}
}