Skip to main content

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