use std::marker::PhantomData; use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo}; use std::slice; use crate::base::allocator::Allocator; use crate::base::default_allocator::DefaultAllocator; use crate::base::dimension::{Const, Dim, DimName, Dynamic, IsNotStaticOne, U1}; use crate::base::iter::MatrixIter; use crate::base::storage::{IsContiguous, Owned, RawStorage, RawStorageMut, Storage}; use crate::base::{Matrix, Scalar}; macro_rules! view_storage_impl ( ($doc: expr; $Storage: ident as $SRef: ty; $legacy_name:ident => $T: ident.$get_addr: ident ($Ptr: ty as $Ref: ty)) => { #[doc = $doc] #[derive(Debug)] pub struct $T<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> { ptr: $Ptr, shape: (R, C), strides: (RStride, CStride), _phantoms: PhantomData<$Ref>, } #[doc = $doc] /// /// This type alias exists only for legacy purposes and is deprecated. It will be removed /// in a future release. Please use /// [` #[doc = stringify!($T)] /// `] instead. See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076) /// for the rationale. #[deprecated = "Use ViewStorage(Mut) instead."] pub type $legacy_name<'a, T, R, C, RStride, CStride> = $T<'a, T, R, C, RStride, CStride>; unsafe impl<'a, T: Send, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Send for $T<'a, T, R, C, RStride, CStride> {} unsafe impl<'a, T: Sync, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Sync for $T<'a, T, R, C, RStride, CStride> {} impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> $T<'a, T, R, C, RStride, CStride> { /// Create a new matrix view without bounds checking and from a raw pointer. #[inline] pub unsafe fn from_raw_parts(ptr: $Ptr, shape: (R, C), strides: (RStride, CStride)) -> Self where RStride: Dim, CStride: Dim { $T { ptr, shape, strides, _phantoms: PhantomData } } } // Dynamic is arbitrary. It's just to be able to call the constructors with `Slice::` impl<'a, T, R: Dim, C: Dim> $T<'a, T, R, C, Dynamic, Dynamic> { /// Create a new matrix view without bounds checking. #[inline] pub unsafe fn new_unchecked(storage: $SRef, start: (usize, usize), shape: (R, C)) -> $T<'a, T, R, C, S::RStride, S::CStride> where RStor: Dim, CStor: Dim, S: $Storage { let strides = storage.strides(); $T::new_with_strides_unchecked(storage, start, shape, strides) } /// Create a new matrix view without bounds checking. #[inline] pub unsafe fn new_with_strides_unchecked(storage: $SRef, start: (usize, usize), shape: (R, C), strides: (RStride, CStride)) -> $T<'a, T, R, C, RStride, CStride> where RStor: Dim, CStor: Dim, S: $Storage, RStride: Dim, CStride: Dim { $T::from_raw_parts(storage.$get_addr(start.0, start.1), shape, strides) } } impl <'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> $T<'a, T, R, C, RStride, CStride> where Self: RawStorage + IsContiguous { /// Extracts the original slice from this storage. pub fn into_slice(self) -> &'a [T] { let (nrows, ncols) = self.shape(); if nrows.value() != 0 && ncols.value() != 0 { let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); unsafe { slice::from_raw_parts(self.ptr, sz + 1) } } else { unsafe { slice::from_raw_parts(self.ptr, 0) } } } } } ); view_storage_impl!("A matrix data storage for a matrix view. Only contains an internal reference \ to another matrix data storage."; RawStorage as &'a S; SliceStorage => ViewStorage.get_address_unchecked(*const T as &'a T)); view_storage_impl!("A mutable matrix data storage for mutable matrix view. Only contains an \ internal mutable reference to another matrix data storage."; RawStorageMut as &'a mut S; SliceStorageMut => ViewStorageMut.get_address_unchecked_mut(*mut T as &'a mut T) ); impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Copy for ViewStorage<'a, T, R, C, RStride, CStride> { } impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Clone for ViewStorage<'a, T, R, C, RStride, CStride> { #[inline] fn clone(&self) -> Self { Self { ptr: self.ptr, shape: self.shape, strides: self.strides, _phantoms: PhantomData, } } } impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> ViewStorageMut<'a, T, R, C, RStride, CStride> where Self: RawStorageMut + IsContiguous, { /// Extracts the original slice from this storage pub fn into_slice_mut(self) -> &'a mut [T] { let (nrows, ncols) = self.shape(); if nrows.value() != 0 && ncols.value() != 0 { let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); unsafe { slice::from_raw_parts_mut(self.ptr, sz + 1) } } else { unsafe { slice::from_raw_parts_mut(self.ptr, 0) } } } } macro_rules! storage_impl( ($($T: ident),* $(,)*) => {$( unsafe impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> RawStorage for $T<'a, T, R, C, RStride, CStride> { type RStride = RStride; type CStride = CStride; #[inline] fn ptr(&self) -> *const T { self.ptr } #[inline] fn shape(&self) -> (R, C) { self.shape } #[inline] fn strides(&self) -> (Self::RStride, Self::CStride) { self.strides } #[inline] fn is_contiguous(&self) -> bool { // Common cases that can be deduced at compile-time even if one of the dimensions // is Dynamic. if (RStride::is::() && C::is::()) || // Column vector. (CStride::is::() && R::is::()) { // Row vector. true } else { let (nrows, _) = self.shape(); let (srows, scols) = self.strides(); srows.value() == 1 && scols.value() == nrows.value() } } #[inline] unsafe fn as_slice_unchecked(&self) -> &[T] { let (nrows, ncols) = self.shape(); if nrows.value() != 0 && ncols.value() != 0 { let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); slice::from_raw_parts(self.ptr, sz + 1) } else { slice::from_raw_parts(self.ptr, 0) } } } unsafe impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Storage for $T<'a, T, R, C, RStride, CStride> { #[inline] fn into_owned(self) -> Owned where DefaultAllocator: Allocator { self.clone_owned() } #[inline] fn clone_owned(&self) -> Owned where DefaultAllocator: Allocator { let (nrows, ncols) = self.shape(); let it = MatrixIter::new(self).cloned(); DefaultAllocator::allocate_from_iterator(nrows, ncols, it) } } )*} ); storage_impl!(ViewStorage, ViewStorageMut); unsafe impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> RawStorageMut for ViewStorageMut<'a, T, R, C, RStride, CStride> { #[inline] fn ptr_mut(&mut self) -> *mut T { self.ptr } #[inline] unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T] { let (nrows, ncols) = self.shape(); if nrows.value() != 0 && ncols.value() != 0 { let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1); slice::from_raw_parts_mut(self.ptr, sz + 1) } else { slice::from_raw_parts_mut(self.ptr, 0) } } } unsafe impl<'a, T, R: Dim, CStride: Dim> IsContiguous for ViewStorage<'a, T, R, U1, U1, CStride> {} unsafe impl<'a, T, R: Dim, CStride: Dim> IsContiguous for ViewStorageMut<'a, T, R, U1, U1, CStride> { } unsafe impl<'a, T, R: DimName, C: Dim + IsNotStaticOne> IsContiguous for ViewStorage<'a, T, R, C, U1, R> { } unsafe impl<'a, T, R: DimName, C: Dim + IsNotStaticOne> IsContiguous for ViewStorageMut<'a, T, R, C, U1, R> { } impl> Matrix { #[inline] fn assert_slice_index( &self, start: (usize, usize), shape: (usize, usize), steps: (usize, usize), ) { let my_shape = self.shape(); // NOTE: we don't do any subtraction to avoid underflow for zero-sized matrices. // // Terms that would have been negative are moved to the other side of the inequality // instead. assert!( start.0 + (steps.0 + 1) * shape.0 <= my_shape.0 + steps.0, "Matrix slicing out of bounds." ); assert!( start.1 + (steps.1 + 1) * shape.1 <= my_shape.1 + steps.1, "Matrix slicing out of bounds." ); } } macro_rules! matrix_view_impl ( ($me: ident: $Me: ty, $MatrixView: ident, $ViewStorage: ident, $Storage: ident.$get_addr: ident (), $data: expr; $row: ident, $row_part: ident, $rows: ident, $rows_with_step: ident, $fixed_rows: ident, $fixed_rows_with_step: ident, $rows_generic: ident, $rows_generic_with_step: ident, $column: ident, $column_part: ident, $columns: ident, $columns_with_step: ident, $fixed_columns: ident, $fixed_columns_with_step: ident, $columns_generic: ident, $columns_generic_with_step: ident, $slice: ident => $view:ident, $slice_with_steps: ident => $view_with_steps:ident, $fixed_slice: ident => $fixed_view:ident, $fixed_slice_with_steps: ident => $fixed_view_with_steps:ident, $generic_slice: ident => $generic_view:ident, $generic_slice_with_steps: ident => $generic_view_with_steps:ident, $rows_range_pair: ident, $columns_range_pair: ident) => { /* * * Row slicing. * */ /// Returns a view containing the i-th row of this matrix. #[inline] pub fn $row($me: $Me, i: usize) -> $MatrixView<'_, T, U1, C, S::RStride, S::CStride> { $me.$fixed_rows::<1>(i) } /// Returns a view containing the `n` first elements of the i-th row of this matrix. #[inline] pub fn $row_part($me: $Me, i: usize, n: usize) -> $MatrixView<'_, T, U1, Dynamic, S::RStride, S::CStride> { $me.$generic_slice((i, 0), (Const::<1>, Dynamic::new(n))) } /// Extracts from this matrix a set of consecutive rows. #[inline] pub fn $rows($me: $Me, first_row: usize, nrows: usize) -> $MatrixView<'_, T, Dynamic, C, S::RStride, S::CStride> { $me.$rows_generic(first_row, Dynamic::new(nrows)) } /// Extracts from this matrix a set of consecutive rows regularly skipping `step` rows. #[inline] pub fn $rows_with_step($me: $Me, first_row: usize, nrows: usize, step: usize) -> $MatrixView<'_, T, Dynamic, C, Dynamic, S::CStride> { $me.$rows_generic_with_step(first_row, Dynamic::new(nrows), step) } /// Extracts a compile-time number of consecutive rows from this matrix. #[inline] pub fn $fixed_rows($me: $Me, first_row: usize) -> $MatrixView<'_, T, Const, C, S::RStride, S::CStride> { $me.$rows_generic(first_row, Const::) } /// Extracts from this matrix a compile-time number of rows regularly skipping `step` /// rows. #[inline] pub fn $fixed_rows_with_step($me: $Me, first_row: usize, step: usize) -> $MatrixView<'_, T, Const, C, Dynamic, S::CStride> { $me.$rows_generic_with_step(first_row, Const::, step) } /// Extracts from this matrix `nrows` rows regularly skipping `step` rows. Both /// argument may or may not be values known at compile-time. #[inline] pub fn $rows_generic($me: $Me, row_start: usize, nrows: RView) -> $MatrixView<'_, T, RView, C, S::RStride, S::CStride> { let my_shape = $me.shape_generic(); $me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (0, 0)); let shape = (nrows, my_shape.1); unsafe { let data = $ViewStorage::new_unchecked($data, (row_start, 0), shape); Matrix::from_data_statically_unchecked(data) } } /// Extracts from this matrix `nrows` rows regularly skipping `step` rows. Both /// argument may or may not be values known at compile-time. #[inline] pub fn $rows_generic_with_step($me: $Me, row_start: usize, nrows: RView, step: usize) -> $MatrixView<'_, T, RView, C, Dynamic, S::CStride> where RView: Dim { let my_shape = $me.shape_generic(); let my_strides = $me.data.strides(); $me.assert_slice_index((row_start, 0), (nrows.value(), my_shape.1.value()), (step, 0)); let strides = (Dynamic::new((step + 1) * my_strides.0.value()), my_strides.1); let shape = (nrows, my_shape.1); unsafe { let data = $ViewStorage::new_with_strides_unchecked($data, (row_start, 0), shape, strides); Matrix::from_data_statically_unchecked(data) } } /* * * Column slicing. * */ /// Returns a view containing the i-th column of this matrix. #[inline] pub fn $column($me: $Me, i: usize) -> $MatrixView<'_, T, R, U1, S::RStride, S::CStride> { $me.$fixed_columns::<1>(i) } /// Returns a view containing the `n` first elements of the i-th column of this matrix. #[inline] pub fn $column_part($me: $Me, i: usize, n: usize) -> $MatrixView<'_, T, Dynamic, U1, S::RStride, S::CStride> { $me.$generic_view((0, i), (Dynamic::new(n), Const::<1>)) } /// Extracts from this matrix a set of consecutive columns. #[inline] pub fn $columns($me: $Me, first_col: usize, ncols: usize) -> $MatrixView<'_, T, R, Dynamic, S::RStride, S::CStride> { $me.$columns_generic(first_col, Dynamic::new(ncols)) } /// Extracts from this matrix a set of consecutive columns regularly skipping `step` /// columns. #[inline] pub fn $columns_with_step($me: $Me, first_col: usize, ncols: usize, step: usize) -> $MatrixView<'_, T, R, Dynamic, S::RStride, Dynamic> { $me.$columns_generic_with_step(first_col, Dynamic::new(ncols), step) } /// Extracts a compile-time number of consecutive columns from this matrix. #[inline] pub fn $fixed_columns($me: $Me, first_col: usize) -> $MatrixView<'_, T, R, Const, S::RStride, S::CStride> { $me.$columns_generic(first_col, Const::) } /// Extracts from this matrix a compile-time number of columns regularly skipping /// `step` columns. #[inline] pub fn $fixed_columns_with_step($me: $Me, first_col: usize, step: usize) -> $MatrixView<'_, T, R, Const, S::RStride, Dynamic> { $me.$columns_generic_with_step(first_col, Const::, step) } /// Extracts from this matrix `ncols` columns. The number of columns may or may not be /// known at compile-time. #[inline] pub fn $columns_generic($me: $Me, first_col: usize, ncols: CView) -> $MatrixView<'_, T, R, CView, S::RStride, S::CStride> { let my_shape = $me.shape_generic(); $me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, 0)); let shape = (my_shape.0, ncols); unsafe { let data = $ViewStorage::new_unchecked($data, (0, first_col), shape); Matrix::from_data_statically_unchecked(data) } } /// Extracts from this matrix `ncols` columns skipping `step` columns. Both argument may /// or may not be values known at compile-time. #[inline] pub fn $columns_generic_with_step($me: $Me, first_col: usize, ncols: CView, step: usize) -> $MatrixView<'_, T, R, CView, S::RStride, Dynamic> { let my_shape = $me.shape_generic(); let my_strides = $me.data.strides(); $me.assert_slice_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, step)); let strides = (my_strides.0, Dynamic::new((step + 1) * my_strides.1.value())); let shape = (my_shape.0, ncols); unsafe { let data = $ViewStorage::new_with_strides_unchecked($data, (0, first_col), shape, strides); Matrix::from_data_statically_unchecked(data) } } /* * * General slicing. * */ /// Slices this matrix starting at its component `(irow, icol)` and with `(nrows, ncols)` /// consecutive elements. #[inline] #[deprecated = slice_deprecation_note!($view)] pub fn $slice($me: $Me, start: (usize, usize), shape: (usize, usize)) -> $MatrixView<'_, T, Dynamic, Dynamic, S::RStride, S::CStride> { $me.$view(start, shape) } /// Return a view of this matrix starting at its component `(irow, icol)` and with `(nrows, ncols)` /// consecutive elements. #[inline] pub fn $view($me: $Me, start: (usize, usize), shape: (usize, usize)) -> $MatrixView<'_, T, Dynamic, Dynamic, S::RStride, S::CStride> { $me.assert_slice_index(start, shape, (0, 0)); let shape = (Dynamic::new(shape.0), Dynamic::new(shape.1)); unsafe { let data = $ViewStorage::new_unchecked($data, start, shape); Matrix::from_data_statically_unchecked(data) } } /// Slices this matrix starting at its component `(start.0, start.1)` and with /// `(shape.0, shape.1)` components. Each row (resp. column) of the sliced matrix is /// separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of the /// original matrix. #[inline] #[deprecated = slice_deprecation_note!($view_with_steps)] pub fn $slice_with_steps($me: $Me, start: (usize, usize), shape: (usize, usize), steps: (usize, usize)) -> $MatrixView<'_, T, Dynamic, Dynamic, Dynamic, Dynamic> { $me.$view_with_steps(start, shape, steps) } /// Return a view of this matrix starting at its component `(start.0, start.1)` and with /// `(shape.0, shape.1)` components. Each row (resp. column) of the matrix view is /// separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of the /// original matrix. #[inline] pub fn $view_with_steps($me: $Me, start: (usize, usize), shape: (usize, usize), steps: (usize, usize)) -> $MatrixView<'_, T, Dynamic, Dynamic, Dynamic, Dynamic> { let shape = (Dynamic::new(shape.0), Dynamic::new(shape.1)); $me.$generic_view_with_steps(start, shape, steps) } /// Slices this matrix starting at its component `(irow, icol)` and with `(R::dim(), /// CView::dim())` consecutive components. #[inline] #[deprecated = slice_deprecation_note!($fixed_view)] pub fn $fixed_slice($me: $Me, irow: usize, icol: usize) -> $MatrixView<'_, T, Const, Const, S::RStride, S::CStride> { $me.$fixed_view(irow, icol) } /// Return a view of this matrix starting at its component `(irow, icol)` and with `(R::dim(), /// CView::dim())` consecutive components. #[inline] pub fn $fixed_view($me: $Me, irow: usize, icol: usize) -> $MatrixView<'_, T, Const, Const, S::RStride, S::CStride> { $me.assert_slice_index((irow, icol), (RVIEW, CVIEW), (0, 0)); let shape = (Const::, Const::); unsafe { let data = $ViewStorage::new_unchecked($data, (irow, icol), shape); Matrix::from_data_statically_unchecked(data) } } /// Slices this matrix starting at its component `(start.0, start.1)` and with /// `(RVIEW, CVIEW)` components. Each row (resp. column) of the sliced /// matrix is separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of /// the original matrix. #[inline] #[deprecated = slice_deprecation_note!($fixed_view_with_steps)] pub fn $fixed_slice_with_steps($me: $Me, start: (usize, usize), steps: (usize, usize)) -> $MatrixView<'_, T, Const, Const, Dynamic, Dynamic> { $me.$fixed_view_with_steps(start, steps) } /// Returns a view of this matrix starting at its component `(start.0, start.1)` and with /// `(RVIEW, CVIEW)` components. Each row (resp. column) of the matrix view /// is separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of /// the original matrix. #[inline] pub fn $fixed_view_with_steps($me: $Me, start: (usize, usize), steps: (usize, usize)) -> $MatrixView<'_, T, Const, Const, Dynamic, Dynamic> { let shape = (Const::, Const::); $me.$generic_view_with_steps(start, shape, steps) } /// Creates a slice that may or may not have a fixed size and stride. #[inline] #[deprecated = slice_deprecation_note!($generic_view)] pub fn $generic_slice($me: $Me, start: (usize, usize), shape: (RView, CView)) -> $MatrixView<'_, T, RView, CView, S::RStride, S::CStride> where RView: Dim, CView: Dim { $me.$generic_view(start, shape) } /// Creates a matrix view that may or may not have a fixed size and stride. #[inline] pub fn $generic_view($me: $Me, start: (usize, usize), shape: (RView, CView)) -> $MatrixView<'_, T, RView, CView, S::RStride, S::CStride> where RView: Dim, CView: Dim { $me.assert_slice_index(start, (shape.0.value(), shape.1.value()), (0, 0)); unsafe { let data = $ViewStorage::new_unchecked($data, start, shape); Matrix::from_data_statically_unchecked(data) } } /// Creates a slice that may or may not have a fixed size and stride. #[inline] #[deprecated = slice_deprecation_note!($generic_view_with_steps)] pub fn $generic_slice_with_steps($me: $Me, start: (usize, usize), shape: (RView, CView), steps: (usize, usize)) -> $MatrixView<'_, T, RView, CView, Dynamic, Dynamic> where RView: Dim, CView: Dim { $me.$generic_view_with_steps(start, shape, steps) } /// Creates a matrix view that may or may not have a fixed size and stride. #[inline] pub fn $generic_view_with_steps($me: $Me, start: (usize, usize), shape: (RView, CView), steps: (usize, usize)) -> $MatrixView<'_, T, RView, CView, Dynamic, Dynamic> where RView: Dim, CView: Dim { $me.assert_slice_index(start, (shape.0.value(), shape.1.value()), steps); let my_strides = $me.data.strides(); let strides = (Dynamic::new((steps.0 + 1) * my_strides.0.value()), Dynamic::new((steps.1 + 1) * my_strides.1.value())); unsafe { let data = $ViewStorage::new_with_strides_unchecked($data, start, shape, strides); Matrix::from_data_statically_unchecked(data) } } /* * * Splitting. * */ /// Splits this `NxM` matrix into two parts delimited by two ranges. /// /// Panics if the ranges overlap or if the first range is empty. #[inline] pub fn $rows_range_pair, Range2: SliceRange>($me: $Me, r1: Range1, r2: Range2) -> ($MatrixView<'_, T, Range1::Size, C, S::RStride, S::CStride>, $MatrixView<'_, T, Range2::Size, C, S::RStride, S::CStride>) { let (nrows, ncols) = $me.shape_generic(); let strides = $me.data.strides(); let start1 = r1.begin(nrows); let start2 = r2.begin(nrows); let end1 = r1.end(nrows); let end2 = r2.end(nrows); let nrows1 = r1.size(nrows); let nrows2 = r2.size(nrows); assert!(start2 >= end1 || start1 >= end2, "Rows range pair: the slice ranges must not overlap."); assert!(end2 <= nrows.value(), "Rows range pair: index out of range."); unsafe { let ptr1 = $data.$get_addr(start1, 0); let ptr2 = $data.$get_addr(start2, 0); let data1 = $ViewStorage::from_raw_parts(ptr1, (nrows1, ncols), strides); let data2 = $ViewStorage::from_raw_parts(ptr2, (nrows2, ncols), strides); let view1 = Matrix::from_data_statically_unchecked(data1); let view2 = Matrix::from_data_statically_unchecked(data2); (view1, view2) } } /// Splits this `NxM` matrix into two parts delimited by two ranges. /// /// Panics if the ranges overlap or if the first range is empty. #[inline] pub fn $columns_range_pair, Range2: SliceRange>($me: $Me, r1: Range1, r2: Range2) -> ($MatrixView<'_, T, R, Range1::Size, S::RStride, S::CStride>, $MatrixView<'_, T, R, Range2::Size, S::RStride, S::CStride>) { let (nrows, ncols) = $me.shape_generic(); let strides = $me.data.strides(); let start1 = r1.begin(ncols); let start2 = r2.begin(ncols); let end1 = r1.end(ncols); let end2 = r2.end(ncols); let ncols1 = r1.size(ncols); let ncols2 = r2.size(ncols); assert!(start2 >= end1 || start1 >= end2, "Columns range pair: the slice ranges must not overlap."); assert!(end2 <= ncols.value(), "Columns range pair: index out of range."); unsafe { let ptr1 = $data.$get_addr(0, start1); let ptr2 = $data.$get_addr(0, start2); let data1 = $ViewStorage::from_raw_parts(ptr1, (nrows, ncols1), strides); let data2 = $ViewStorage::from_raw_parts(ptr2, (nrows, ncols2), strides); let view1 = Matrix::from_data_statically_unchecked(data1); let view2 = Matrix::from_data_statically_unchecked(data2); (view1, view2) } } } ); /// A matrix slice. /// /// This type alias exists only for legacy purposes and is deprecated. It will be removed /// in a future release. Please use [`MatrixView`] instead. /// See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076) /// for the rationale. #[deprecated = "Use MatrixView instead."] pub type MatrixSlice<'a, T, R, C, RStride = U1, CStride = R> = MatrixView<'a, T, R, C, RStride, CStride>; /// A matrix view. pub type MatrixView<'a, T, R, C, RStride = U1, CStride = R> = Matrix>; /// A mutable matrix slice. /// /// This type alias exists only for legacy purposes and is deprecated. It will be removed /// in a future release. Please use [`MatrixViewMut`] instead. /// See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076) /// for the rationale. #[deprecated = "Use MatrixViewMut instead."] pub type MatrixSliceMut<'a, T, R, C, RStride = U1, CStride = R> = MatrixViewMut<'a, T, R, C, RStride, CStride>; /// A mutable matrix view. pub type MatrixViewMut<'a, T, R, C, RStride = U1, CStride = R> = Matrix>; /// # Views based on index and length impl> Matrix { matrix_view_impl!( self: &Self, MatrixView, ViewStorage, RawStorage.get_address_unchecked(), &self.data; row, row_part, rows, rows_with_step, fixed_rows, fixed_rows_with_step, rows_generic, rows_generic_with_step, column, column_part, columns, columns_with_step, fixed_columns, fixed_columns_with_step, columns_generic, columns_generic_with_step, slice => view, slice_with_steps => view_with_steps, fixed_slice => fixed_view, fixed_slice_with_steps => fixed_view_with_steps, generic_slice => generic_view, generic_slice_with_steps => generic_view_with_steps, rows_range_pair, columns_range_pair); } /// # Mutable views based on index and length impl> Matrix { matrix_view_impl!( self: &mut Self, MatrixViewMut, ViewStorageMut, RawStorageMut.get_address_unchecked_mut(), &mut self.data; row_mut, row_part_mut, rows_mut, rows_with_step_mut, fixed_rows_mut, fixed_rows_with_step_mut, rows_generic_mut, rows_generic_with_step_mut, column_mut, column_part_mut, columns_mut, columns_with_step_mut, fixed_columns_mut, fixed_columns_with_step_mut, columns_generic_mut, columns_generic_with_step_mut, slice_mut => view_mut, slice_with_steps_mut => view_with_steps_mut, fixed_slice_mut => fixed_view_mut, fixed_slice_with_steps_mut => fixed_view_with_steps_mut, generic_slice_mut => generic_view_mut, generic_slice_with_steps_mut => generic_view_with_steps_mut, rows_range_pair_mut, columns_range_pair_mut); } /// A range with a size that may be known at compile-time. /// /// This may be: /// * A single `usize` index, e.g., `4` /// * A left-open range `std::ops::RangeTo`, e.g., `.. 4` /// * A right-open range `std::ops::RangeFrom`, e.g., `4 ..` /// * A full range `std::ops::RangeFull`, e.g., `..` pub trait SliceRange { /// Type of the range size. May be a type-level integer. type Size: Dim; /// The start index of the range. fn begin(&self, shape: D) -> usize; // NOTE: this is the index immediately after the last index. /// The index immediately after the last index inside of the range. fn end(&self, shape: D) -> usize; /// The number of elements of the range, i.e., `self.end - self.begin`. fn size(&self, shape: D) -> Self::Size; } impl SliceRange for usize { type Size = U1; #[inline(always)] fn begin(&self, _: D) -> usize { *self } #[inline(always)] fn end(&self, _: D) -> usize { *self + 1 } #[inline(always)] fn size(&self, _: D) -> Self::Size { Const::<1> } } impl SliceRange for Range { type Size = Dynamic; #[inline(always)] fn begin(&self, _: D) -> usize { self.start } #[inline(always)] fn end(&self, _: D) -> usize { self.end } #[inline(always)] fn size(&self, _: D) -> Self::Size { Dynamic::new(self.end - self.start) } } impl SliceRange for RangeFrom { type Size = Dynamic; #[inline(always)] fn begin(&self, _: D) -> usize { self.start } #[inline(always)] fn end(&self, dim: D) -> usize { dim.value() } #[inline(always)] fn size(&self, dim: D) -> Self::Size { Dynamic::new(dim.value() - self.start) } } impl SliceRange for RangeTo { type Size = Dynamic; #[inline(always)] fn begin(&self, _: D) -> usize { 0 } #[inline(always)] fn end(&self, _: D) -> usize { self.end } #[inline(always)] fn size(&self, _: D) -> Self::Size { Dynamic::new(self.end) } } impl SliceRange for RangeFull { type Size = D; #[inline(always)] fn begin(&self, _: D) -> usize { 0 } #[inline(always)] fn end(&self, dim: D) -> usize { dim.value() } #[inline(always)] fn size(&self, dim: D) -> Self::Size { dim } } impl SliceRange for RangeInclusive { type Size = Dynamic; #[inline(always)] fn begin(&self, _: D) -> usize { *self.start() } #[inline(always)] fn end(&self, _: D) -> usize { *self.end() + 1 } #[inline(always)] fn size(&self, _: D) -> Self::Size { Dynamic::new(*self.end() + 1 - *self.start()) } } // TODO: see how much of this overlaps with the general indexing // methods from indexing.rs. impl> Matrix { /// Slices a sub-matrix containing the rows indexed by the range `rows` and the columns indexed /// by the range `cols`. #[inline] #[must_use] #[deprecated = slice_deprecation_note!(view_range)] pub fn slice_range( &self, rows: RowRange, cols: ColRange, ) -> MatrixView<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride> where RowRange: SliceRange, ColRange: SliceRange, { let (nrows, ncols) = self.shape_generic(); self.generic_slice( (rows.begin(nrows), cols.begin(ncols)), (rows.size(nrows), cols.size(ncols)), ) } /// Returns a view containing the rows indexed by the range `rows` and the columns indexed /// by the range `cols`. #[inline] #[must_use] pub fn view_range( &self, rows: RowRange, cols: ColRange, ) -> MatrixView<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride> where RowRange: SliceRange, ColRange: SliceRange, { let (nrows, ncols) = self.shape_generic(); self.generic_view( (rows.begin(nrows), cols.begin(ncols)), (rows.size(nrows), cols.size(ncols)), ) } /// View containing all the rows indexed by the range `rows`. #[inline] #[must_use] pub fn rows_range>( &self, rows: RowRange, ) -> MatrixView<'_, T, RowRange::Size, C, S::RStride, S::CStride> { self.view_range(rows, ..) } /// View containing all the columns indexed by the range `rows`. #[inline] #[must_use] pub fn columns_range>( &self, cols: ColRange, ) -> MatrixView<'_, T, R, ColRange::Size, S::RStride, S::CStride> { self.view_range(.., cols) } } // TODO: see how much of this overlaps with the general indexing // methods from indexing.rs. impl> Matrix { /// Slices a mutable sub-matrix containing the rows indexed by the range `rows` and the columns /// indexed by the range `cols`. #[deprecated = slice_deprecation_note!(view_range_mut)] pub fn slice_range_mut( &mut self, rows: RowRange, cols: ColRange, ) -> MatrixViewMut<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride> where RowRange: SliceRange, ColRange: SliceRange, { self.view_range_mut(rows, cols) } /// Return a mutable view containing the rows indexed by the range `rows` and the columns /// indexed by the range `cols`. pub fn view_range_mut( &mut self, rows: RowRange, cols: ColRange, ) -> MatrixViewMut<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride> where RowRange: SliceRange, ColRange: SliceRange, { let (nrows, ncols) = self.shape_generic(); self.generic_view_mut( (rows.begin(nrows), cols.begin(ncols)), (rows.size(nrows), cols.size(ncols)), ) } /// Mutable view containing all the rows indexed by the range `rows`. #[inline] pub fn rows_range_mut>( &mut self, rows: RowRange, ) -> MatrixViewMut<'_, T, RowRange::Size, C, S::RStride, S::CStride> { self.view_range_mut(rows, ..) } /// Mutable view containing all the columns indexed by the range `cols`. #[inline] pub fn columns_range_mut>( &mut self, cols: ColRange, ) -> MatrixViewMut<'_, T, R, ColRange::Size, S::RStride, S::CStride> { self.view_range_mut(.., cols) } } impl<'a, T, R, C, RStride, CStride> From> for MatrixView<'a, T, R, C, RStride, CStride> where R: Dim, C: Dim, RStride: Dim, CStride: Dim, { fn from(view_mut: MatrixViewMut<'a, T, R, C, RStride, CStride>) -> Self { let data = ViewStorage { ptr: view_mut.data.ptr, shape: view_mut.data.shape, strides: view_mut.data.strides, _phantoms: PhantomData, }; unsafe { Matrix::from_data_statically_unchecked(data) } } }