nalgebra/base/
matrix_view.rs

1use std::marker::PhantomData;
2use std::ops::{Range, RangeFrom, RangeFull, RangeInclusive, RangeTo};
3use std::slice;
4
5use crate::base::allocator::Allocator;
6use crate::base::default_allocator::DefaultAllocator;
7use crate::base::dimension::{Const, Dim, DimName, Dyn, IsNotStaticOne, U1};
8use crate::base::iter::MatrixIter;
9use crate::base::storage::{IsContiguous, Owned, RawStorage, RawStorageMut, Storage};
10use crate::base::{Matrix, Scalar};
11use crate::constraint::{DimEq, ShapeConstraint};
12use crate::ReshapableStorage;
13
14macro_rules! view_storage_impl (
15    ($doc: expr; $Storage: ident as $SRef: ty; $legacy_name:ident => $T: ident.$get_addr: ident ($Ptr: ty as $Ref: ty)) => {
16        #[doc = $doc]
17        #[derive(Debug)]
18        pub struct $T<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>  {
19            ptr:       $Ptr,
20            shape:     (R, C),
21            strides:   (RStride, CStride),
22            _phantoms: PhantomData<$Ref>,
23        }
24
25        #[doc = $doc]
26        ///
27        /// This type alias exists only for legacy purposes and is deprecated. It will be removed
28        /// in a future release. Please use
29        /// [`
30        #[doc = stringify!($T)]
31        /// `] instead. See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076)
32        /// for the rationale.
33        #[deprecated = "Use ViewStorage(Mut) instead."]
34        pub type $legacy_name<'a, T, R, C, RStride, CStride> = $T<'a, T, R, C, RStride, CStride>;
35
36        unsafe impl<'a, T: Send, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Send
37            for $T<'a, T, R, C, RStride, CStride>
38        {}
39
40        unsafe impl<'a, T: Sync, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Sync
41            for $T<'a, T, R, C, RStride, CStride>
42        {}
43
44        impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> $T<'a, T, R, C, RStride, CStride> {
45            /// Create a new matrix view without bounds checking and from a raw pointer.
46            ///
47            /// # Safety
48            ///
49            /// `*ptr` must point to memory that is valid `[T; R * C]`.
50            #[inline]
51            pub unsafe fn from_raw_parts(ptr:     $Ptr,
52                                         shape:   (R, C),
53                                         strides: (RStride, CStride))
54                                        -> Self
55                where RStride: Dim,
56                      CStride: Dim {
57
58                $T {
59                    ptr,
60                    shape,
61                    strides,
62                    _phantoms: PhantomData
63                }
64            }
65        }
66
67        // Dyn is arbitrary. It's just to be able to call the constructors with `Slice::`
68        impl<'a, T, R: Dim, C: Dim> $T<'a, T, R, C, Dyn, Dyn> {
69            /// Create a new matrix view without bounds checking.
70            ///
71            /// # Safety
72            ///
73            /// `storage` contains sufficient elements beyond `start + R * C` such that all
74            /// accesses are within bounds.
75            #[inline]
76            pub unsafe fn new_unchecked<RStor, CStor, S>(storage: $SRef, start: (usize, usize), shape: (R, C))
77                -> $T<'a, T, R, C, S::RStride, S::CStride>
78                where RStor: Dim,
79                      CStor: Dim,
80                      S:     $Storage<T, RStor, CStor> {
81
82                let strides = storage.strides();
83                $T::new_with_strides_unchecked(storage, start, shape, strides)
84            }
85
86            /// Create a new matrix view without bounds checking.
87            ///
88            /// # Safety
89            ///
90            /// `strides` must be a valid stride indexing.
91            #[inline]
92            pub unsafe fn new_with_strides_unchecked<S, RStor, CStor, RStride, CStride>(storage: $SRef,
93                                                                                        start:   (usize, usize),
94                                                                                        shape:   (R, C),
95                                                                                        strides: (RStride, CStride))
96                -> $T<'a, T, R, C, RStride, CStride>
97                where RStor: Dim,
98                      CStor: Dim,
99                      S: $Storage<T, RStor, CStor>,
100                      RStride: Dim,
101                      CStride: Dim {
102                $T::from_raw_parts(storage.$get_addr(start.0, start.1), shape, strides)
103            }
104        }
105
106        impl <'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
107            $T<'a, T, R, C, RStride, CStride>
108        where
109            Self: RawStorage<T, R, C> + IsContiguous
110        {
111            /// Extracts the original slice from this storage.
112            pub fn into_slice(self) -> &'a [T] {
113                let (nrows, ncols) = self.shape();
114                if nrows.value() != 0 && ncols.value() != 0 {
115                    let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1);
116                    unsafe { slice::from_raw_parts(self.ptr, sz + 1) }
117                } else {
118                    unsafe { slice::from_raw_parts(self.ptr, 0) }
119                }
120            }
121        }
122    }
123);
124
125view_storage_impl!("A matrix data storage for a matrix view. Only contains an internal reference \
126                     to another matrix data storage.";
127    RawStorage as &'a S; SliceStorage => ViewStorage.get_address_unchecked(*const T as &'a T));
128
129view_storage_impl!("A mutable matrix data storage for mutable matrix view. Only contains an \
130                     internal mutable reference to another matrix data storage.";
131    RawStorageMut as &'a mut S; SliceStorageMut => ViewStorageMut.get_address_unchecked_mut(*mut T as &'a mut T)
132);
133
134impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Copy
135    for ViewStorage<'a, T, R, C, RStride, CStride>
136{
137}
138
139impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Clone
140    for ViewStorage<'a, T, R, C, RStride, CStride>
141{
142    #[inline]
143    fn clone(&self) -> Self {
144        *self
145    }
146}
147
148impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
149    ViewStorageMut<'a, T, R, C, RStride, CStride>
150where
151    Self: RawStorageMut<T, R, C> + IsContiguous,
152{
153    /// Extracts the original slice from this storage
154    pub fn into_slice_mut(self) -> &'a mut [T] {
155        let (nrows, ncols) = self.shape();
156        if nrows.value() != 0 && ncols.value() != 0 {
157            let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1);
158            unsafe { slice::from_raw_parts_mut(self.ptr, sz + 1) }
159        } else {
160            unsafe { slice::from_raw_parts_mut(self.ptr, 0) }
161        }
162    }
163}
164
165macro_rules! storage_impl(
166    ($($T: ident),* $(,)*) => {$(
167        unsafe impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> RawStorage<T, R, C>
168            for $T<'a, T, R, C, RStride, CStride> {
169
170            type RStride = RStride;
171            type CStride = CStride;
172
173            #[inline]
174            fn ptr(&self) -> *const T {
175                self.ptr
176            }
177
178            #[inline]
179            fn shape(&self) -> (R, C) {
180                self.shape
181            }
182
183            #[inline]
184            fn strides(&self) -> (Self::RStride, Self::CStride) {
185                self.strides
186            }
187
188            #[inline]
189            fn is_contiguous(&self) -> bool {
190                // Common cases that can be deduced at compile-time even if one of the dimensions
191                // is Dyn.
192                if (RStride::is::<U1>() && C::is::<U1>()) || // Column vector.
193                   (CStride::is::<U1>() && R::is::<U1>()) {  // Row vector.
194                    true
195                }
196                else {
197                    let (nrows, _)     = self.shape();
198                    let (srows, scols) = self.strides();
199
200                    srows.value() == 1 && scols.value() == nrows.value()
201                }
202            }
203
204            #[inline]
205            unsafe fn as_slice_unchecked(&self) -> &[T] {
206                let (nrows, ncols) = self.shape();
207                if nrows.value() != 0 && ncols.value() != 0 {
208                    let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1);
209                    slice::from_raw_parts(self.ptr, sz + 1)
210                }
211                else {
212                    slice::from_raw_parts(self.ptr, 0)
213                }
214            }
215        }
216
217        unsafe impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> Storage<T, R, C>
218            for $T<'a, T, R, C, RStride, CStride> {
219            #[inline]
220            fn into_owned(self) -> Owned<T, R, C>
221                where DefaultAllocator: Allocator<R, C> {
222                self.clone_owned()
223            }
224
225            #[inline]
226            fn clone_owned(&self) -> Owned<T, R, C>
227                where DefaultAllocator: Allocator<R, C> {
228                let (nrows, ncols) = self.shape();
229                let it = MatrixIter::new(self).cloned();
230                DefaultAllocator::allocate_from_iterator(nrows, ncols, it)
231            }
232
233            #[inline]
234            fn forget_elements(self) {
235                // No cleanup required.
236            }
237        }
238    )*}
239);
240
241storage_impl!(ViewStorage, ViewStorageMut);
242
243unsafe impl<'a, T, R: Dim, C: Dim, RStride: Dim, CStride: Dim> RawStorageMut<T, R, C>
244    for ViewStorageMut<'a, T, R, C, RStride, CStride>
245{
246    #[inline]
247    fn ptr_mut(&mut self) -> *mut T {
248        self.ptr
249    }
250
251    #[inline]
252    unsafe fn as_mut_slice_unchecked(&mut self) -> &mut [T] {
253        let (nrows, ncols) = self.shape();
254        if nrows.value() != 0 && ncols.value() != 0 {
255            let sz = self.linear_index(nrows.value() - 1, ncols.value() - 1);
256            slice::from_raw_parts_mut(self.ptr, sz + 1)
257        } else {
258            slice::from_raw_parts_mut(self.ptr, 0)
259        }
260    }
261}
262
263unsafe impl<'a, T, R: Dim, CStride: Dim> IsContiguous for ViewStorage<'a, T, R, U1, U1, CStride> {}
264unsafe impl<'a, T, R: Dim, CStride: Dim> IsContiguous
265    for ViewStorageMut<'a, T, R, U1, U1, CStride>
266{
267}
268
269unsafe impl<'a, T, R: DimName, C: Dim + IsNotStaticOne> IsContiguous
270    for ViewStorage<'a, T, R, C, U1, R>
271{
272}
273unsafe impl<'a, T, R: DimName, C: Dim + IsNotStaticOne> IsContiguous
274    for ViewStorageMut<'a, T, R, C, U1, R>
275{
276}
277
278impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
279    #[inline]
280    fn assert_view_index(
281        &self,
282        start: (usize, usize),
283        shape: (usize, usize),
284        steps: (usize, usize),
285    ) {
286        let my_shape = self.shape();
287        // NOTE: we don't do any subtraction to avoid underflow for zero-sized matrices.
288        //
289        // Terms that would have been negative are moved to the other side of the inequality
290        // instead.
291        assert!(
292            start.0 + (steps.0 + 1) * shape.0 <= my_shape.0 + steps.0,
293            "Matrix slicing out of bounds."
294        );
295        assert!(
296            start.1 + (steps.1 + 1) * shape.1 <= my_shape.1 + steps.1,
297            "Matrix slicing out of bounds."
298        );
299    }
300}
301
302macro_rules! matrix_view_impl (
303    ($me: ident: $Me: ty, $MatrixView: ident, $ViewStorage: ident, $Storage: ident.$get_addr: ident (), $data: expr;
304     $row: ident,
305     $row_part: ident,
306     $rows: ident,
307     $rows_with_step: ident,
308     $fixed_rows: ident,
309     $fixed_rows_with_step: ident,
310     $rows_generic: ident,
311     $rows_generic_with_step: ident,
312     $column: ident,
313     $column_part: ident,
314     $columns: ident,
315     $columns_with_step: ident,
316     $fixed_columns: ident,
317     $fixed_columns_with_step: ident,
318     $columns_generic: ident,
319     $columns_generic_with_step: ident,
320     $slice: ident => $view:ident,
321     $slice_with_steps: ident => $view_with_steps:ident,
322     $fixed_slice: ident => $fixed_view:ident,
323     $fixed_slice_with_steps: ident => $fixed_view_with_steps:ident,
324     $generic_slice: ident => $generic_view:ident,
325     $generic_slice_with_steps: ident => $generic_view_with_steps:ident,
326     $rows_range_pair: ident,
327     $columns_range_pair: ident) => {
328        /*
329         *
330         * Row slicing.
331         *
332         */
333        /// Returns a view containing the i-th row of this matrix.
334        #[inline]
335        pub fn $row($me: $Me, i: usize) -> $MatrixView<'_, T, U1, C, S::RStride, S::CStride> {
336            $me.$fixed_rows::<1>(i)
337        }
338
339        /// Returns a view containing the `n` first elements of the i-th row of this matrix.
340        #[inline]
341        pub fn $row_part($me: $Me, i: usize, n: usize) -> $MatrixView<'_, T, U1, Dyn, S::RStride, S::CStride> {
342            $me.$generic_view((i, 0), (Const::<1>, Dyn(n)))
343        }
344
345        /// Extracts from this matrix a set of consecutive rows.
346        #[inline]
347        pub fn $rows($me: $Me, first_row: usize, nrows: usize)
348            -> $MatrixView<'_, T, Dyn, C, S::RStride, S::CStride> {
349
350            $me.$rows_generic(first_row, Dyn(nrows))
351        }
352
353        /// Extracts from this matrix a set of consecutive rows regularly skipping `step` rows.
354        #[inline]
355        pub fn $rows_with_step($me: $Me, first_row: usize, nrows: usize, step: usize)
356            -> $MatrixView<'_, T, Dyn, C, Dyn, S::CStride> {
357
358            $me.$rows_generic_with_step(first_row, Dyn(nrows), step)
359        }
360
361        /// Extracts a compile-time number of consecutive rows from this matrix.
362        #[inline]
363        pub fn $fixed_rows<const RVIEW: usize>($me: $Me, first_row: usize)
364            -> $MatrixView<'_, T, Const<RVIEW>, C, S::RStride, S::CStride> {
365
366            $me.$rows_generic(first_row, Const::<RVIEW>)
367        }
368
369        /// Extracts from this matrix a compile-time number of rows regularly skipping `step`
370        /// rows.
371        #[inline]
372        pub fn $fixed_rows_with_step<const RVIEW: usize>($me: $Me, first_row: usize, step: usize)
373            -> $MatrixView<'_, T, Const<RVIEW>, C, Dyn, S::CStride> {
374
375            $me.$rows_generic_with_step(first_row, Const::<RVIEW>, step)
376        }
377
378        /// Extracts from this matrix `nrows` rows regularly skipping `step` rows. Both
379        /// argument may or may not be values known at compile-time.
380        #[inline]
381        pub fn $rows_generic<RView: Dim>($me: $Me, row_start: usize, nrows: RView)
382            -> $MatrixView<'_, T, RView, C, S::RStride, S::CStride> {
383
384            let my_shape   = $me.shape_generic();
385            $me.assert_view_index((row_start, 0), (nrows.value(), my_shape.1.value()), (0, 0));
386
387            let shape = (nrows, my_shape.1);
388
389            unsafe {
390                let data = $ViewStorage::new_unchecked($data, (row_start, 0), shape);
391                Matrix::from_data_statically_unchecked(data)
392            }
393        }
394
395        /// Extracts from this matrix `nrows` rows regularly skipping `step` rows. Both
396        /// argument may or may not be values known at compile-time.
397        #[inline]
398        pub fn $rows_generic_with_step<RView>($me: $Me, row_start: usize, nrows: RView, step: usize)
399            -> $MatrixView<'_, T, RView, C, Dyn, S::CStride>
400            where RView: Dim {
401
402            let my_shape   = $me.shape_generic();
403            let my_strides = $me.data.strides();
404            $me.assert_view_index((row_start, 0), (nrows.value(), my_shape.1.value()), (step, 0));
405
406            let strides = (Dyn((step + 1) * my_strides.0.value()), my_strides.1);
407            let shape   = (nrows, my_shape.1);
408
409            unsafe {
410                let data = $ViewStorage::new_with_strides_unchecked($data, (row_start, 0), shape, strides);
411                Matrix::from_data_statically_unchecked(data)
412            }
413        }
414
415        /*
416         *
417         * Column slicing.
418         *
419         */
420        /// Returns a view containing the i-th column of this matrix.
421        #[inline]
422        pub fn $column($me: $Me, i: usize) -> $MatrixView<'_, T, R, U1, S::RStride, S::CStride> {
423            $me.$fixed_columns::<1>(i)
424        }
425
426        /// Returns a view containing the `n` first elements of the i-th column of this matrix.
427        #[inline]
428        pub fn $column_part($me: $Me, i: usize, n: usize) -> $MatrixView<'_, T, Dyn, U1, S::RStride, S::CStride> {
429            $me.$generic_view((0, i), (Dyn(n), Const::<1>))
430        }
431
432        /// Extracts from this matrix a set of consecutive columns.
433        #[inline]
434        pub fn $columns($me: $Me, first_col: usize, ncols: usize)
435            -> $MatrixView<'_, T, R, Dyn, S::RStride, S::CStride> {
436
437            $me.$columns_generic(first_col, Dyn(ncols))
438        }
439
440        /// Extracts from this matrix a set of consecutive columns regularly skipping `step`
441        /// columns.
442        #[inline]
443        pub fn $columns_with_step($me: $Me, first_col: usize, ncols: usize, step: usize)
444            -> $MatrixView<'_, T, R, Dyn, S::RStride, Dyn> {
445
446            $me.$columns_generic_with_step(first_col, Dyn(ncols), step)
447        }
448
449        /// Extracts a compile-time number of consecutive columns from this matrix.
450        #[inline]
451        pub fn $fixed_columns<const CVIEW: usize>($me: $Me, first_col: usize)
452            -> $MatrixView<'_, T, R, Const<CVIEW>, S::RStride, S::CStride> {
453
454            $me.$columns_generic(first_col, Const::<CVIEW>)
455        }
456
457        /// Extracts from this matrix a compile-time number of columns regularly skipping
458        /// `step` columns.
459        #[inline]
460        pub fn $fixed_columns_with_step<const CVIEW: usize>($me: $Me, first_col: usize, step: usize)
461            -> $MatrixView<'_, T, R, Const<CVIEW>, S::RStride, Dyn> {
462
463            $me.$columns_generic_with_step(first_col, Const::<CVIEW>, step)
464        }
465
466        /// Extracts from this matrix `ncols` columns. The number of columns may or may not be
467        /// known at compile-time.
468        #[inline]
469        pub fn $columns_generic<CView: Dim>($me: $Me, first_col: usize, ncols: CView)
470            -> $MatrixView<'_, T, R, CView, S::RStride, S::CStride> {
471
472            let my_shape = $me.shape_generic();
473            $me.assert_view_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, 0));
474            let shape = (my_shape.0, ncols);
475
476            unsafe {
477                let data = $ViewStorage::new_unchecked($data, (0, first_col), shape);
478                Matrix::from_data_statically_unchecked(data)
479            }
480        }
481
482
483        /// Extracts from this matrix `ncols` columns skipping `step` columns. Both argument may
484        /// or may not be values known at compile-time.
485        #[inline]
486        pub fn $columns_generic_with_step<CView: Dim>($me: $Me, first_col: usize, ncols: CView, step: usize)
487            -> $MatrixView<'_, T, R, CView, S::RStride, Dyn> {
488
489            let my_shape   = $me.shape_generic();
490            let my_strides = $me.data.strides();
491
492            $me.assert_view_index((0, first_col), (my_shape.0.value(), ncols.value()), (0, step));
493
494            let strides = (my_strides.0, Dyn((step + 1) * my_strides.1.value()));
495            let shape   = (my_shape.0, ncols);
496
497            unsafe {
498                let data = $ViewStorage::new_with_strides_unchecked($data, (0, first_col), shape, strides);
499                Matrix::from_data_statically_unchecked(data)
500            }
501        }
502
503        /*
504         *
505         * General slicing.
506         *
507         */
508        /// Slices this matrix starting at its component `(irow, icol)` and with `(nrows, ncols)`
509        /// consecutive elements.
510        #[inline]
511        #[deprecated = slice_deprecation_note!($view)]
512        pub fn $slice($me: $Me, start: (usize, usize), shape: (usize, usize))
513            -> $MatrixView<'_, T, Dyn, Dyn, S::RStride, S::CStride> {
514            $me.$view(start, shape)
515        }
516
517        /// Return a view of this matrix starting at its component `(irow, icol)` and with `(nrows, ncols)`
518        /// consecutive elements.
519        #[inline]
520        pub fn $view($me: $Me, start: (usize, usize), shape: (usize, usize))
521            -> $MatrixView<'_, T, Dyn, Dyn, S::RStride, S::CStride> {
522
523            $me.assert_view_index(start, shape, (0, 0));
524            let shape = (Dyn(shape.0), Dyn(shape.1));
525
526            unsafe {
527                let data = $ViewStorage::new_unchecked($data, start, shape);
528                Matrix::from_data_statically_unchecked(data)
529            }
530        }
531
532        /// Slices this matrix starting at its component `(start.0, start.1)` and with
533        /// `(shape.0, shape.1)` components. Each row (resp. column) of the sliced matrix is
534        /// separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of the
535        /// original matrix.
536        #[inline]
537        #[deprecated = slice_deprecation_note!($view_with_steps)]
538        pub fn $slice_with_steps($me: $Me, start: (usize, usize), shape: (usize, usize), steps: (usize, usize))
539            -> $MatrixView<'_, T, Dyn, Dyn, Dyn, Dyn> {
540            $me.$view_with_steps(start, shape, steps)
541        }
542
543        /// Return a view of this matrix starting at its component `(start.0, start.1)` and with
544        /// `(shape.0, shape.1)` components. Each row (resp. column) of the matrix view is
545        /// separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of the
546        /// original matrix.
547        #[inline]
548        pub fn $view_with_steps($me: $Me, start: (usize, usize), shape: (usize, usize), steps: (usize, usize))
549            -> $MatrixView<'_, T, Dyn, Dyn, Dyn, Dyn> {
550            let shape = (Dyn(shape.0), Dyn(shape.1));
551            $me.$generic_view_with_steps(start, shape, steps)
552        }
553
554        /// Slices this matrix starting at its component `(irow, icol)` and with `(RVIEW, CVIEW)`
555        /// consecutive components.
556        #[inline]
557        #[deprecated = slice_deprecation_note!($fixed_view)]
558        pub fn $fixed_slice<const RVIEW: usize, const CVIEW: usize>($me: $Me, irow: usize, icol: usize)
559            -> $MatrixView<'_, T, Const<RVIEW>, Const<CVIEW>, S::RStride, S::CStride> {
560            $me.$fixed_view(irow, icol)
561        }
562
563        /// Return a view of this matrix starting at its component `(irow, icol)` and with
564        /// `(RVIEW, CVIEW)` consecutive components.
565        #[inline]
566        pub fn $fixed_view<const RVIEW: usize, const CVIEW: usize>($me: $Me, irow: usize, icol: usize)
567            -> $MatrixView<'_, T, Const<RVIEW>, Const<CVIEW>, S::RStride, S::CStride> {
568
569            $me.assert_view_index((irow, icol), (RVIEW, CVIEW), (0, 0));
570            let shape = (Const::<RVIEW>, Const::<CVIEW>);
571
572            unsafe {
573                let data = $ViewStorage::new_unchecked($data, (irow, icol), shape);
574                Matrix::from_data_statically_unchecked(data)
575            }
576        }
577
578        /// Slices this matrix starting at its component `(start.0, start.1)` and with
579        /// `(RVIEW, CVIEW)` components. Each row (resp. column) of the sliced
580        /// matrix is separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of
581        /// the original matrix.
582        #[inline]
583        #[deprecated = slice_deprecation_note!($fixed_view_with_steps)]
584        pub fn $fixed_slice_with_steps<const RVIEW: usize, const CVIEW: usize>($me: $Me, start: (usize, usize), steps: (usize, usize))
585            -> $MatrixView<'_, T, Const<RVIEW>, Const<CVIEW>, Dyn, Dyn> {
586            $me.$fixed_view_with_steps(start, steps)
587        }
588
589        /// Returns a view of this matrix starting at its component `(start.0, start.1)` and with
590        /// `(RVIEW, CVIEW)` components. Each row (resp. column) of the matrix view
591        /// is separated by `steps.0` (resp. `steps.1`) ignored rows (resp. columns) of
592        /// the original matrix.
593        #[inline]
594        pub fn $fixed_view_with_steps<const RVIEW: usize, const CVIEW: usize>($me: $Me, start: (usize, usize), steps: (usize, usize))
595            -> $MatrixView<'_, T, Const<RVIEW>, Const<CVIEW>, Dyn, Dyn> {
596            let shape = (Const::<RVIEW>, Const::<CVIEW>);
597            $me.$generic_view_with_steps(start, shape, steps)
598        }
599
600        /// Creates a slice that may or may not have a fixed size and stride.
601        #[inline]
602        #[deprecated = slice_deprecation_note!($generic_view)]
603        pub fn $generic_slice<RView, CView>($me: $Me, start: (usize, usize), shape: (RView, CView))
604            -> $MatrixView<'_, T, RView, CView, S::RStride, S::CStride>
605            where RView: Dim,
606                  CView: Dim {
607            $me.$generic_view(start, shape)
608        }
609
610        /// Creates a matrix view that may or may not have a fixed size and stride.
611        #[inline]
612        pub fn $generic_view<RView, CView>($me: $Me, start: (usize, usize), shape: (RView, CView))
613            -> $MatrixView<'_, T, RView, CView, S::RStride, S::CStride>
614            where RView: Dim,
615                  CView: Dim {
616
617            $me.assert_view_index(start, (shape.0.value(), shape.1.value()), (0, 0));
618
619            unsafe {
620                let data = $ViewStorage::new_unchecked($data, start, shape);
621                Matrix::from_data_statically_unchecked(data)
622            }
623        }
624
625        /// Creates a slice that may or may not have a fixed size and stride.
626        #[inline]
627        #[deprecated = slice_deprecation_note!($generic_view_with_steps)]
628        pub fn $generic_slice_with_steps<RView, CView>($me: $Me,
629                                                         start: (usize, usize),
630                                                         shape: (RView, CView),
631                                                         steps: (usize, usize))
632            -> $MatrixView<'_, T, RView, CView, Dyn, Dyn>
633            where RView: Dim,
634                  CView: Dim {
635            $me.$generic_view_with_steps(start, shape, steps)
636        }
637
638        /// Creates a matrix view that may or may not have a fixed size and stride.
639        #[inline]
640        pub fn $generic_view_with_steps<RView, CView>($me: $Me,
641                                                         start: (usize, usize),
642                                                         shape: (RView, CView),
643                                                         steps: (usize, usize))
644            -> $MatrixView<'_, T, RView, CView, Dyn, Dyn>
645            where RView: Dim,
646                  CView: Dim {
647
648            $me.assert_view_index(start, (shape.0.value(), shape.1.value()), steps);
649
650            let my_strides = $me.data.strides();
651            let strides    = (Dyn((steps.0 + 1) * my_strides.0.value()),
652                              Dyn((steps.1 + 1) * my_strides.1.value()));
653
654            unsafe {
655                let data = $ViewStorage::new_with_strides_unchecked($data, start, shape, strides);
656                Matrix::from_data_statically_unchecked(data)
657            }
658        }
659
660        /*
661         *
662         * Splitting.
663         *
664         */
665        /// Splits this `NxM` matrix into two parts delimited by two ranges.
666        ///
667        /// Panics if the ranges overlap or if the first range is empty.
668        #[inline]
669        pub fn $rows_range_pair<Range1: DimRange<R>, Range2: DimRange<R>>($me: $Me, r1: Range1, r2: Range2)
670            -> ($MatrixView<'_, T, Range1::Size, C, S::RStride, S::CStride>,
671                $MatrixView<'_, T, Range2::Size, C, S::RStride, S::CStride>) {
672
673            let (nrows, ncols) = $me.shape_generic();
674            let strides        = $me.data.strides();
675
676            let start1 = r1.begin(nrows);
677            let start2 = r2.begin(nrows);
678
679            let end1 = r1.end(nrows);
680            let end2 = r2.end(nrows);
681
682            let nrows1 = r1.size(nrows);
683            let nrows2 = r2.size(nrows);
684
685            assert!(start2 >= end1 || start1 >= end2, "Rows range pair: the ranges must not overlap.");
686            assert!(end2 <= nrows.value(), "Rows range pair: index out of range.");
687
688            unsafe {
689                let ptr1 = $data.$get_addr(start1, 0);
690                let ptr2 = $data.$get_addr(start2, 0);
691
692                let data1  = $ViewStorage::from_raw_parts(ptr1, (nrows1, ncols), strides);
693                let data2  = $ViewStorage::from_raw_parts(ptr2, (nrows2, ncols), strides);
694                let view1 = Matrix::from_data_statically_unchecked(data1);
695                let view2 = Matrix::from_data_statically_unchecked(data2);
696
697                (view1, view2)
698            }
699        }
700
701        /// Splits this `NxM` matrix into two parts delimited by two ranges.
702        ///
703        /// Panics if the ranges overlap or if the first range is empty.
704        #[inline]
705        pub fn $columns_range_pair<Range1: DimRange<C>, Range2: DimRange<C>>($me: $Me, r1: Range1, r2: Range2)
706            -> ($MatrixView<'_, T, R, Range1::Size, S::RStride, S::CStride>,
707                $MatrixView<'_, T, R, Range2::Size, S::RStride, S::CStride>) {
708
709            let (nrows, ncols) = $me.shape_generic();
710            let strides        = $me.data.strides();
711
712            let start1 = r1.begin(ncols);
713            let start2 = r2.begin(ncols);
714
715            let end1 = r1.end(ncols);
716            let end2 = r2.end(ncols);
717
718            let ncols1 = r1.size(ncols);
719            let ncols2 = r2.size(ncols);
720
721            assert!(start2 >= end1 || start1 >= end2, "Columns range pair: the ranges must not overlap.");
722            assert!(end2 <= ncols.value(), "Columns range pair: index out of range.");
723
724            unsafe {
725                let ptr1 = $data.$get_addr(0, start1);
726                let ptr2 = $data.$get_addr(0, start2);
727
728                let data1  = $ViewStorage::from_raw_parts(ptr1, (nrows, ncols1), strides);
729                let data2  = $ViewStorage::from_raw_parts(ptr2, (nrows, ncols2), strides);
730                let view1 = Matrix::from_data_statically_unchecked(data1);
731                let view2 = Matrix::from_data_statically_unchecked(data2);
732
733                (view1, view2)
734            }
735        }
736    }
737);
738
739/// A matrix slice.
740///
741/// This type alias exists only for legacy purposes and is deprecated. It will be removed
742/// in a future release. Please use [`MatrixView`] instead.
743/// See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076)
744/// for the rationale.
745#[deprecated = "Use MatrixView instead."]
746pub type MatrixSlice<'a, T, R, C, RStride = U1, CStride = R> =
747    MatrixView<'a, T, R, C, RStride, CStride>;
748
749/// A matrix view.
750pub type MatrixView<'a, T, R, C, RStride = U1, CStride = R> =
751    Matrix<T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>;
752
753/// A mutable matrix slice.
754///
755/// This type alias exists only for legacy purposes and is deprecated. It will be removed
756/// in a future release. Please use [`MatrixViewMut`] instead.
757/// See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076)
758/// for the rationale.
759#[deprecated = "Use MatrixViewMut instead."]
760pub type MatrixSliceMut<'a, T, R, C, RStride = U1, CStride = R> =
761    MatrixViewMut<'a, T, R, C, RStride, CStride>;
762
763/// A mutable matrix view.
764pub type MatrixViewMut<'a, T, R, C, RStride = U1, CStride = R> =
765    Matrix<T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>;
766
767/// # Views based on index and length
768impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
769    matrix_view_impl!(
770     self: &Self, MatrixView, ViewStorage, RawStorage.get_address_unchecked(), &self.data;
771     row,
772     row_part,
773     rows,
774     rows_with_step,
775     fixed_rows,
776     fixed_rows_with_step,
777     rows_generic,
778     rows_generic_with_step,
779     column,
780     column_part,
781     columns,
782     columns_with_step,
783     fixed_columns,
784     fixed_columns_with_step,
785     columns_generic,
786     columns_generic_with_step,
787     slice => view,
788     slice_with_steps => view_with_steps,
789     fixed_slice => fixed_view,
790     fixed_slice_with_steps => fixed_view_with_steps,
791     generic_slice => generic_view,
792     generic_slice_with_steps => generic_view_with_steps,
793     rows_range_pair,
794     columns_range_pair);
795}
796
797/// # Mutable views based on index and length
798impl<T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> Matrix<T, R, C, S> {
799    matrix_view_impl!(
800     self: &mut Self, MatrixViewMut, ViewStorageMut, RawStorageMut.get_address_unchecked_mut(), &mut self.data;
801     row_mut,
802     row_part_mut,
803     rows_mut,
804     rows_with_step_mut,
805     fixed_rows_mut,
806     fixed_rows_with_step_mut,
807     rows_generic_mut,
808     rows_generic_with_step_mut,
809     column_mut,
810     column_part_mut,
811     columns_mut,
812     columns_with_step_mut,
813     fixed_columns_mut,
814     fixed_columns_with_step_mut,
815     columns_generic_mut,
816     columns_generic_with_step_mut,
817     slice_mut => view_mut,
818     slice_with_steps_mut => view_with_steps_mut,
819     fixed_slice_mut => fixed_view_mut,
820     fixed_slice_with_steps_mut => fixed_view_with_steps_mut,
821     generic_slice_mut => generic_view_mut,
822     generic_slice_with_steps_mut => generic_view_with_steps_mut,
823     rows_range_pair_mut,
824     columns_range_pair_mut);
825}
826
827/// A range with a size that may be known at compile-time.
828///
829/// This may be:
830/// * A single `usize` index, e.g., `4`
831/// * A left-open range `std::ops::RangeTo`, e.g., `.. 4`
832/// * A right-open range `std::ops::RangeFrom`, e.g., `4 ..`
833/// * A full range `std::ops::RangeFull`, e.g., `..`
834pub trait DimRange<D: Dim> {
835    /// Type of the range size. May be a type-level integer.
836    type Size: Dim;
837
838    /// The start index of the range.
839    fn begin(&self, shape: D) -> usize;
840    // NOTE: this is the index immediately after the last index.
841    /// The index immediately after the last index inside of the range.
842    fn end(&self, shape: D) -> usize;
843    /// The number of elements of the range, i.e., `self.end - self.begin`.
844    fn size(&self, shape: D) -> Self::Size;
845}
846
847/// A range with a size that may be known at compile-time.
848///
849/// This is merely a legacy trait alias to minimize breakage. Use the [`DimRange`] trait instead.
850#[deprecated = slice_deprecation_note!(DimRange)]
851pub trait SliceRange<D: Dim>: DimRange<D> {}
852
853#[allow(deprecated)]
854impl<R: DimRange<D>, D: Dim> SliceRange<D> for R {}
855
856impl<D: Dim> DimRange<D> for usize {
857    type Size = U1;
858
859    #[inline(always)]
860    fn begin(&self, _: D) -> usize {
861        *self
862    }
863
864    #[inline(always)]
865    fn end(&self, _: D) -> usize {
866        *self + 1
867    }
868
869    #[inline(always)]
870    fn size(&self, _: D) -> Self::Size {
871        Const::<1>
872    }
873}
874
875impl<D: Dim> DimRange<D> for Range<usize> {
876    type Size = Dyn;
877
878    #[inline(always)]
879    fn begin(&self, _: D) -> usize {
880        self.start
881    }
882
883    #[inline(always)]
884    fn end(&self, _: D) -> usize {
885        self.end
886    }
887
888    #[inline(always)]
889    fn size(&self, _: D) -> Self::Size {
890        Dyn(self.end - self.start)
891    }
892}
893
894impl<D: Dim> DimRange<D> for RangeFrom<usize> {
895    type Size = Dyn;
896
897    #[inline(always)]
898    fn begin(&self, _: D) -> usize {
899        self.start
900    }
901
902    #[inline(always)]
903    fn end(&self, dim: D) -> usize {
904        dim.value()
905    }
906
907    #[inline(always)]
908    fn size(&self, dim: D) -> Self::Size {
909        Dyn(dim.value() - self.start)
910    }
911}
912
913impl<D: Dim> DimRange<D> for RangeTo<usize> {
914    type Size = Dyn;
915
916    #[inline(always)]
917    fn begin(&self, _: D) -> usize {
918        0
919    }
920
921    #[inline(always)]
922    fn end(&self, _: D) -> usize {
923        self.end
924    }
925
926    #[inline(always)]
927    fn size(&self, _: D) -> Self::Size {
928        Dyn(self.end)
929    }
930}
931
932impl<D: Dim> DimRange<D> for RangeFull {
933    type Size = D;
934
935    #[inline(always)]
936    fn begin(&self, _: D) -> usize {
937        0
938    }
939
940    #[inline(always)]
941    fn end(&self, dim: D) -> usize {
942        dim.value()
943    }
944
945    #[inline(always)]
946    fn size(&self, dim: D) -> Self::Size {
947        dim
948    }
949}
950
951impl<D: Dim> DimRange<D> for RangeInclusive<usize> {
952    type Size = Dyn;
953
954    #[inline(always)]
955    fn begin(&self, _: D) -> usize {
956        *self.start()
957    }
958
959    #[inline(always)]
960    fn end(&self, _: D) -> usize {
961        *self.end() + 1
962    }
963
964    #[inline(always)]
965    fn size(&self, _: D) -> Self::Size {
966        Dyn(*self.end() + 1 - *self.start())
967    }
968}
969
970// TODO: see how much of this overlaps with the general indexing
971// methods from indexing.rs.
972impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
973    /// Slices a sub-matrix containing the rows indexed by the range `rows` and the columns indexed
974    /// by the range `cols`.
975    #[inline]
976    #[must_use]
977    #[deprecated = slice_deprecation_note!(view_range)]
978    pub fn slice_range<RowRange, ColRange>(
979        &self,
980        rows: RowRange,
981        cols: ColRange,
982    ) -> MatrixView<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
983    where
984        RowRange: DimRange<R>,
985        ColRange: DimRange<C>,
986    {
987        let (nrows, ncols) = self.shape_generic();
988        self.generic_view(
989            (rows.begin(nrows), cols.begin(ncols)),
990            (rows.size(nrows), cols.size(ncols)),
991        )
992    }
993
994    /// Returns a view containing the rows indexed by the range `rows` and the columns indexed
995    /// by the range `cols`.
996    #[inline]
997    #[must_use]
998    pub fn view_range<RowRange, ColRange>(
999        &self,
1000        rows: RowRange,
1001        cols: ColRange,
1002    ) -> MatrixView<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
1003    where
1004        RowRange: DimRange<R>,
1005        ColRange: DimRange<C>,
1006    {
1007        let (nrows, ncols) = self.shape_generic();
1008        self.generic_view(
1009            (rows.begin(nrows), cols.begin(ncols)),
1010            (rows.size(nrows), cols.size(ncols)),
1011        )
1012    }
1013
1014    /// View containing all the rows indexed by the range `rows`.
1015    #[inline]
1016    #[must_use]
1017    pub fn rows_range<RowRange: DimRange<R>>(
1018        &self,
1019        rows: RowRange,
1020    ) -> MatrixView<'_, T, RowRange::Size, C, S::RStride, S::CStride> {
1021        self.view_range(rows, ..)
1022    }
1023
1024    /// View containing all the columns indexed by the range `rows`.
1025    #[inline]
1026    #[must_use]
1027    pub fn columns_range<ColRange: DimRange<C>>(
1028        &self,
1029        cols: ColRange,
1030    ) -> MatrixView<'_, T, R, ColRange::Size, S::RStride, S::CStride> {
1031        self.view_range(.., cols)
1032    }
1033}
1034
1035// TODO: see how much of this overlaps with the general indexing
1036// methods from indexing.rs.
1037impl<T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> Matrix<T, R, C, S> {
1038    /// Slices a mutable sub-matrix containing the rows indexed by the range `rows` and the columns
1039    /// indexed by the range `cols`.
1040    #[deprecated = slice_deprecation_note!(view_range_mut)]
1041    pub fn slice_range_mut<RowRange, ColRange>(
1042        &mut self,
1043        rows: RowRange,
1044        cols: ColRange,
1045    ) -> MatrixViewMut<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
1046    where
1047        RowRange: DimRange<R>,
1048        ColRange: DimRange<C>,
1049    {
1050        self.view_range_mut(rows, cols)
1051    }
1052
1053    /// Return a mutable view containing the rows indexed by the range `rows` and the columns
1054    /// indexed by the range `cols`.
1055    pub fn view_range_mut<RowRange, ColRange>(
1056        &mut self,
1057        rows: RowRange,
1058        cols: ColRange,
1059    ) -> MatrixViewMut<'_, T, RowRange::Size, ColRange::Size, S::RStride, S::CStride>
1060    where
1061        RowRange: DimRange<R>,
1062        ColRange: DimRange<C>,
1063    {
1064        let (nrows, ncols) = self.shape_generic();
1065        self.generic_view_mut(
1066            (rows.begin(nrows), cols.begin(ncols)),
1067            (rows.size(nrows), cols.size(ncols)),
1068        )
1069    }
1070
1071    /// Mutable view containing all the rows indexed by the range `rows`.
1072    #[inline]
1073    pub fn rows_range_mut<RowRange: DimRange<R>>(
1074        &mut self,
1075        rows: RowRange,
1076    ) -> MatrixViewMut<'_, T, RowRange::Size, C, S::RStride, S::CStride> {
1077        self.view_range_mut(rows, ..)
1078    }
1079
1080    /// Mutable view containing all the columns indexed by the range `cols`.
1081    #[inline]
1082    pub fn columns_range_mut<ColRange: DimRange<C>>(
1083        &mut self,
1084        cols: ColRange,
1085    ) -> MatrixViewMut<'_, T, R, ColRange::Size, S::RStride, S::CStride> {
1086        self.view_range_mut(.., cols)
1087    }
1088}
1089
1090impl<'a, T, R, C, RStride, CStride> From<MatrixViewMut<'a, T, R, C, RStride, CStride>>
1091    for MatrixView<'a, T, R, C, RStride, CStride>
1092where
1093    R: Dim,
1094    C: Dim,
1095    RStride: Dim,
1096    CStride: Dim,
1097{
1098    fn from(view_mut: MatrixViewMut<'a, T, R, C, RStride, CStride>) -> Self {
1099        let data = ViewStorage {
1100            ptr: view_mut.data.ptr,
1101            shape: view_mut.data.shape,
1102            strides: view_mut.data.strides,
1103            _phantoms: PhantomData,
1104        };
1105
1106        unsafe { Matrix::from_data_statically_unchecked(data) }
1107    }
1108}
1109
1110impl<T, R, C, S> Matrix<T, R, C, S>
1111where
1112    R: Dim,
1113    C: Dim,
1114    S: RawStorage<T, R, C>,
1115{
1116    /// Returns this matrix as a view.
1117    ///
1118    /// The returned view type is generally ambiguous unless specified.
1119    /// This is particularly useful when working with functions or methods that take
1120    /// matrix views as input.
1121    ///
1122    /// # Panics
1123    /// Panics if the dimensions of the view and the matrix are not compatible and this cannot
1124    /// be proven at compile-time. This might happen, for example, when constructing a static
1125    /// view of size 3x3 from a dynamically sized matrix of dimension 5x5.
1126    ///
1127    /// # Examples
1128    /// ```
1129    /// use nalgebra::{DMatrixSlice, SMatrixView};
1130    ///
1131    /// fn consume_view(_: DMatrixSlice<f64>) {}
1132    ///
1133    /// let matrix = nalgebra::Matrix3::zeros();
1134    /// consume_view(matrix.as_view());
1135    ///
1136    /// let dynamic_view: DMatrixSlice<f64> = matrix.as_view();
1137    /// let static_view_from_dyn: SMatrixView<f64, 3, 3> = dynamic_view.as_view();
1138    /// ```
1139    pub fn as_view<RView, CView, RViewStride, CViewStride>(
1140        &self,
1141    ) -> MatrixView<'_, T, RView, CView, RViewStride, CViewStride>
1142    where
1143        RView: Dim,
1144        CView: Dim,
1145        RViewStride: Dim,
1146        CViewStride: Dim,
1147        ShapeConstraint: DimEq<R, RView>
1148            + DimEq<C, CView>
1149            + DimEq<RViewStride, S::RStride>
1150            + DimEq<CViewStride, S::CStride>,
1151    {
1152        // Defer to (&matrix).into()
1153        self.into()
1154    }
1155}
1156
1157impl<T, R, C, S> Matrix<T, R, C, S>
1158where
1159    R: Dim,
1160    C: Dim,
1161    S: RawStorageMut<T, R, C>,
1162{
1163    /// Returns this matrix as a mutable view.
1164    ///
1165    /// The returned view type is generally ambiguous unless specified.
1166    /// This is particularly useful when working with functions or methods that take
1167    /// matrix views as input.
1168    ///
1169    /// # Panics
1170    /// Panics if the dimensions of the view and the matrix are not compatible and this cannot
1171    /// be proven at compile-time. This might happen, for example, when constructing a static
1172    /// view of size 3x3 from a dynamically sized matrix of dimension 5x5.
1173    ///
1174    /// # Examples
1175    /// ```
1176    /// use nalgebra::{DMatrixViewMut, SMatrixViewMut};
1177    ///
1178    /// fn consume_view(_: DMatrixViewMut<f64>) {}
1179    ///
1180    /// let mut matrix = nalgebra::Matrix3::zeros();
1181    /// consume_view(matrix.as_view_mut());
1182    ///
1183    /// let mut dynamic_view: DMatrixViewMut<f64> = matrix.as_view_mut();
1184    /// let static_view_from_dyn: SMatrixViewMut<f64, 3, 3> = dynamic_view.as_view_mut();
1185    /// ```
1186    pub fn as_view_mut<RView, CView, RViewStride, CViewStride>(
1187        &mut self,
1188    ) -> MatrixViewMut<'_, T, RView, CView, RViewStride, CViewStride>
1189    where
1190        RView: Dim,
1191        CView: Dim,
1192        RViewStride: Dim,
1193        CViewStride: Dim,
1194        ShapeConstraint: DimEq<R, RView>
1195            + DimEq<C, CView>
1196            + DimEq<RViewStride, S::RStride>
1197            + DimEq<CViewStride, S::CStride>,
1198    {
1199        // Defer to (&mut matrix).into()
1200        self.into()
1201    }
1202}
1203
1204// TODO: Arbitrary strides?
1205impl<'a, T, R1, C1, R2, C2> ReshapableStorage<T, R1, C1, R2, C2>
1206    for ViewStorage<'a, T, R1, C1, U1, R1>
1207where
1208    T: Scalar,
1209    R1: Dim,
1210    C1: Dim,
1211    R2: Dim,
1212    C2: Dim,
1213{
1214    type Output = ViewStorage<'a, T, R2, C2, U1, R2>;
1215
1216    fn reshape_generic(self, nrows: R2, ncols: C2) -> Self::Output {
1217        let (r1, c1) = self.shape();
1218        assert_eq!(nrows.value() * ncols.value(), r1.value() * c1.value());
1219        let ptr = self.ptr();
1220        let new_shape = (nrows, ncols);
1221        let strides = (U1::name(), nrows);
1222        unsafe { ViewStorage::from_raw_parts(ptr, new_shape, strides) }
1223    }
1224}
1225
1226// TODO: Arbitrary strides?
1227impl<'a, T, R1, C1, R2, C2> ReshapableStorage<T, R1, C1, R2, C2>
1228    for ViewStorageMut<'a, T, R1, C1, U1, R1>
1229where
1230    T: Scalar,
1231    R1: Dim,
1232    C1: Dim,
1233    R2: Dim,
1234    C2: Dim,
1235{
1236    type Output = ViewStorageMut<'a, T, R2, C2, U1, R2>;
1237
1238    fn reshape_generic(mut self, nrows: R2, ncols: C2) -> Self::Output {
1239        let (r1, c1) = self.shape();
1240        assert_eq!(nrows.value() * ncols.value(), r1.value() * c1.value());
1241        let ptr = self.ptr_mut();
1242        let new_shape = (nrows, ncols);
1243        let strides = (U1::name(), nrows);
1244        unsafe { ViewStorageMut::from_raw_parts(ptr, new_shape, strides) }
1245    }
1246}