nalgebra/base/
matrix_view.rs

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