nalgebra/base/
indexing.rs

1//! Indexing
2#![allow(clippy::reversed_empty_ranges)]
3
4use crate::base::storage::{RawStorage, RawStorageMut};
5use crate::base::{
6    Const, Dim, DimDiff, DimName, DimSub, Dyn, Matrix, MatrixView, MatrixViewMut, Scalar, U1,
7};
8
9use std::ops;
10
11// N.B.: Not a public trait!
12trait DimRange<D: Dim> {
13    /// The number of elements indexed by this range.
14    type Length: Dim;
15
16    /// The lower bound of the range, inclusive.
17    fn lower(&self, dimension: D) -> usize;
18
19    /// The number of elements included in the range.
20    fn length(&self, dimension: D) -> Self::Length;
21
22    /// Produces true if `Self` is contained within `dimension`.
23    fn contained_by(&self, dimension: D) -> bool;
24}
25
26impl<D: Dim> DimRange<D> for usize {
27    type Length = U1;
28
29    #[inline(always)]
30    fn lower(&self, _: D) -> usize {
31        *self
32    }
33
34    #[inline(always)]
35    fn length(&self, _: D) -> Self::Length {
36        Const::<1>
37    }
38
39    #[inline(always)]
40    fn contained_by(&self, dimension: D) -> bool {
41        *self < dimension.value()
42    }
43}
44
45#[test]
46fn dimrange_usize() {
47    assert!(!DimRange::contained_by(&0, Const::<0>));
48    assert!(DimRange::contained_by(&0, Const::<1>));
49}
50
51impl<D: Dim> DimRange<D> for ops::Range<usize> {
52    type Length = Dyn;
53
54    #[inline(always)]
55    fn lower(&self, _: D) -> usize {
56        self.start
57    }
58
59    #[inline(always)]
60    fn length(&self, _: D) -> Self::Length {
61        Dyn(self.end.saturating_sub(self.start))
62    }
63
64    #[inline(always)]
65    fn contained_by(&self, dimension: D) -> bool {
66        (self.start < dimension.value()) && (self.end <= dimension.value())
67    }
68}
69
70#[test]
71fn dimrange_range_usize() {
72    assert!(!DimRange::contained_by(&(0..0), Const::<0>));
73    assert!(!DimRange::contained_by(&(0..1), Const::<0>));
74    assert!(DimRange::contained_by(&(0..1), Const::<1>));
75    assert!(DimRange::contained_by(
76        &((usize::MAX - 1)..usize::MAX),
77        Dyn(usize::MAX)
78    ));
79    assert_eq!(
80        DimRange::length(&((usize::MAX - 1)..usize::MAX), Dyn(usize::MAX)),
81        Dyn(1)
82    );
83    assert_eq!(
84        DimRange::length(&(usize::MAX..(usize::MAX - 1)), Dyn(usize::MAX)),
85        Dyn(0)
86    );
87    assert_eq!(
88        DimRange::length(&(usize::MAX..usize::MAX), Dyn(usize::MAX)),
89        Dyn(0)
90    );
91}
92
93impl<D: Dim> DimRange<D> for ops::RangeFrom<usize> {
94    type Length = Dyn;
95
96    #[inline(always)]
97    fn lower(&self, _: D) -> usize {
98        self.start
99    }
100
101    #[inline(always)]
102    fn length(&self, dimension: D) -> Self::Length {
103        (self.start..dimension.value()).length(dimension)
104    }
105
106    #[inline(always)]
107    fn contained_by(&self, dimension: D) -> bool {
108        self.start < dimension.value()
109    }
110}
111
112#[test]
113fn dimrange_rangefrom_usize() {
114    assert!(!DimRange::contained_by(&(0..), Const::<0>));
115    assert!(!DimRange::contained_by(&(0..), Const::<0>));
116    assert!(DimRange::contained_by(&(0..), Const::<1>));
117    assert!(DimRange::contained_by(
118        &((usize::MAX - 1)..),
119        Dyn(usize::MAX)
120    ));
121    assert_eq!(
122        DimRange::length(&((usize::MAX - 1)..), Dyn(usize::MAX)),
123        Dyn(1)
124    );
125    assert_eq!(DimRange::length(&(usize::MAX..), Dyn(usize::MAX)), Dyn(0));
126}
127
128impl<D: Dim, T: Dim> DimRange<D> for ops::RangeFrom<T>
129where
130    D: DimSub<T>,
131{
132    type Length = DimDiff<D, T>;
133
134    #[inline(always)]
135    fn lower(&self, _: D) -> usize {
136        self.start.value()
137    }
138
139    #[inline(always)]
140    fn length(&self, dimension: D) -> Self::Length {
141        dimension.sub(self.start)
142    }
143
144    #[inline(always)]
145    fn contained_by(&self, _: D) -> bool {
146        true
147    }
148}
149
150#[test]
151fn dimrange_rangefrom_dimname() {
152    assert_eq!(DimRange::length(&(Const::<1>..), Const::<5>), Const::<4>);
153}
154
155impl<D: Dim> DimRange<D> for ops::RangeFull {
156    type Length = D;
157
158    #[inline(always)]
159    fn lower(&self, _: D) -> usize {
160        0
161    }
162
163    #[inline(always)]
164    fn length(&self, dimension: D) -> Self::Length {
165        dimension
166    }
167
168    #[inline(always)]
169    fn contained_by(&self, _: D) -> bool {
170        true
171    }
172}
173
174#[test]
175fn dimrange_rangefull() {
176    assert!(DimRange::contained_by(&(..), Const::<0>));
177    assert_eq!(DimRange::length(&(..), Const::<1>), Const::<1>);
178}
179
180impl<D: Dim> DimRange<D> for ops::RangeInclusive<usize> {
181    type Length = Dyn;
182
183    #[inline(always)]
184    fn lower(&self, _: D) -> usize {
185        *self.start()
186    }
187
188    #[inline(always)]
189    fn length(&self, _: D) -> Self::Length {
190        Dyn(if self.end() < self.start() {
191            0
192        } else {
193            self.end().wrapping_sub(self.start().wrapping_sub(1))
194        })
195    }
196
197    #[inline(always)]
198    fn contained_by(&self, dimension: D) -> bool {
199        (*self.start() < dimension.value()) && (*self.end() < dimension.value())
200    }
201}
202
203#[test]
204fn dimrange_rangeinclusive_usize() {
205    assert!(!DimRange::contained_by(&(0..=0), Const::<0>));
206    assert!(DimRange::contained_by(&(0..=0), Const::<1>));
207    assert!(!DimRange::contained_by(
208        &(usize::MAX..=usize::MAX),
209        Dyn(usize::MAX)
210    ));
211    assert!(!DimRange::contained_by(
212        &((usize::MAX - 1)..=usize::MAX),
213        Dyn(usize::MAX)
214    ));
215    assert!(DimRange::contained_by(
216        &((usize::MAX - 1)..=(usize::MAX - 1)),
217        Dyn(usize::MAX)
218    ));
219    assert_eq!(DimRange::length(&(0..=0), Const::<1>), Dyn(1));
220    assert_eq!(
221        DimRange::length(&((usize::MAX - 1)..=usize::MAX), Dyn(usize::MAX)),
222        Dyn(2)
223    );
224    assert_eq!(
225        DimRange::length(&(usize::MAX..=(usize::MAX - 1)), Dyn(usize::MAX)),
226        Dyn(0)
227    );
228    assert_eq!(
229        DimRange::length(&(usize::MAX..=usize::MAX), Dyn(usize::MAX)),
230        Dyn(1)
231    );
232}
233
234impl<D: Dim> DimRange<D> for ops::RangeTo<usize> {
235    type Length = Dyn;
236
237    #[inline(always)]
238    fn lower(&self, _: D) -> usize {
239        0
240    }
241
242    #[inline(always)]
243    fn length(&self, _: D) -> Self::Length {
244        Dyn(self.end)
245    }
246
247    #[inline(always)]
248    fn contained_by(&self, dimension: D) -> bool {
249        self.end <= dimension.value()
250    }
251}
252
253#[test]
254fn dimrange_rangeto_usize() {
255    assert!(DimRange::contained_by(&(..0), Const::<0>));
256    assert!(!DimRange::contained_by(&(..1), Const::<0>));
257    assert!(DimRange::contained_by(&(..0), Const::<1>));
258    assert!(DimRange::contained_by(
259        &(..(usize::MAX - 1)),
260        Dyn(usize::MAX)
261    ));
262    assert_eq!(
263        DimRange::length(&(..(usize::MAX - 1)), Dyn(usize::MAX)),
264        Dyn(usize::MAX - 1)
265    );
266    assert_eq!(
267        DimRange::length(&(..usize::MAX), Dyn(usize::MAX)),
268        Dyn(usize::MAX)
269    );
270}
271
272impl<D: Dim> DimRange<D> for ops::RangeToInclusive<usize> {
273    type Length = Dyn;
274
275    #[inline(always)]
276    fn lower(&self, _: D) -> usize {
277        0
278    }
279
280    #[inline(always)]
281    fn length(&self, _: D) -> Self::Length {
282        Dyn(self.end + 1)
283    }
284
285    #[inline(always)]
286    fn contained_by(&self, dimension: D) -> bool {
287        self.end < dimension.value()
288    }
289}
290
291#[test]
292fn dimrange_rangetoinclusive_usize() {
293    assert!(!DimRange::contained_by(&(..=0), Const::<0>));
294    assert!(!DimRange::contained_by(&(..=1), Const::<0>));
295    assert!(DimRange::contained_by(&(..=0), Const::<1>));
296    assert!(!DimRange::contained_by(&(..=(usize::MAX)), Dyn(usize::MAX)));
297    assert!(DimRange::contained_by(
298        &(..=(usize::MAX - 1)),
299        Dyn(usize::MAX)
300    ));
301    assert_eq!(
302        DimRange::length(&(..=(usize::MAX - 1)), Dyn(usize::MAX)),
303        Dyn(usize::MAX)
304    );
305}
306
307/// A helper trait used for indexing operations.
308pub trait MatrixIndex<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>>: Sized {
309    /// The output type returned by methods.
310    type Output: 'a;
311
312    /// Produces true if the given matrix is contained by this index.
313    #[doc(hidden)]
314    fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool;
315
316    /// Produces a shared view of the data at this location if in bounds,
317    /// or `None`, otherwise.
318    #[doc(hidden)]
319    #[inline(always)]
320    fn get(self, matrix: &'a Matrix<T, R, C, S>) -> Option<Self::Output> {
321        if self.contained_by(matrix) {
322            Some(unsafe { self.get_unchecked(matrix) })
323        } else {
324            None
325        }
326    }
327
328    /// Produces a shared view of the data at this location if in bounds
329    /// without any bounds checking.
330    #[doc(hidden)]
331    unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output;
332
333    /// Produces a shared view to the data at this location, or panics
334    /// if out of bounds.
335    #[doc(hidden)]
336    #[inline(always)]
337    fn index(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
338        self.get(matrix).expect("Index out of bounds.")
339    }
340}
341
342/// A helper trait used for indexing operations.
343pub trait MatrixIndexMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>>:
344    MatrixIndex<'a, T, R, C, S>
345{
346    /// The output type returned by methods.
347    type OutputMut: 'a;
348
349    /// Produces a mutable view of the data at this location, without
350    /// performing any bounds checking.
351    #[doc(hidden)]
352    unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut;
353
354    /// Produces a mutable view of the data at this location, if in
355    /// bounds.
356    #[doc(hidden)]
357    #[inline(always)]
358    fn get_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Option<Self::OutputMut> {
359        if self.contained_by(matrix) {
360            Some(unsafe { self.get_unchecked_mut(matrix) })
361        } else {
362            None
363        }
364    }
365
366    /// Produces a mutable view of the data at this location, or panics
367    /// if out of bounds.
368    #[doc(hidden)]
369    #[inline(always)]
370    fn index_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut {
371        self.get_mut(matrix).expect("Index out of bounds.")
372    }
373}
374
375/// # Views based on ranges
376/// ## Indices to Individual Elements
377/// ### Two-Dimensional Indices
378/// ```
379/// # use nalgebra::*;
380/// let matrix = Matrix2::new(0, 2,
381///                           1, 3);
382///
383/// assert_eq!(matrix.index((0, 0)), &0);
384/// assert_eq!(matrix.index((1, 0)), &1);
385/// assert_eq!(matrix.index((0, 1)), &2);
386/// assert_eq!(matrix.index((1, 1)), &3);
387/// ```
388///
389/// ### Linear Address Indexing
390/// ```
391/// # use nalgebra::*;
392/// let matrix = Matrix2::new(0, 2,
393///                           1, 3);
394///
395/// assert_eq!(matrix.get(0), Some(&0));
396/// assert_eq!(matrix.get(1), Some(&1));
397/// assert_eq!(matrix.get(2), Some(&2));
398/// assert_eq!(matrix.get(3), Some(&3));
399/// ```
400///
401/// ## Indices to Individual Rows and Columns
402/// ### Index to a Row
403/// ```
404/// # use nalgebra::*;
405/// let matrix = Matrix2::new(0, 2,
406///                           1, 3);
407///
408/// assert!(matrix.index((0, ..))
409///     .eq(&Matrix1x2::new(0, 2)));
410/// ```
411///
412/// ### Index to a Column
413/// ```
414/// # use nalgebra::*;
415/// let matrix = Matrix2::new(0, 2,
416///                           1, 3);
417///
418/// assert!(matrix.index((.., 0))
419///     .eq(&Matrix2x1::new(0,
420///                         1)));
421/// ```
422///
423/// ## Indices to Parts of Individual Rows and Columns
424/// ### Index to a Partial Row
425/// ```
426/// # use nalgebra::*;
427/// let matrix = Matrix3::new(0, 3, 6,
428///                           1, 4, 7,
429///                           2, 5, 8);
430///
431/// assert!(matrix.index((0, ..2))
432///     .eq(&Matrix1x2::new(0, 3)));
433/// ```
434///
435/// ### Index to a Partial Column
436/// ```
437/// # use nalgebra::*;
438/// let matrix = Matrix3::new(0, 3, 6,
439///                           1, 4, 7,
440///                           2, 5, 8);
441///
442/// assert!(matrix.index((..2, 0))
443///     .eq(&Matrix2x1::new(0,
444///                         1)));
445///
446/// assert!(matrix.index((Const::<1>.., 0))
447///     .eq(&Matrix2x1::new(1,
448///                         2)));
449/// ```
450/// ## Indices to Ranges of Rows and Columns
451/// ### Index to a Range of Rows
452/// ```
453/// # use nalgebra::*;
454/// let matrix = Matrix3::new(0, 3, 6,
455///                           1, 4, 7,
456///                           2, 5, 8);
457///
458/// assert!(matrix.index((1..3, ..))
459///     .eq(&Matrix2x3::new(1, 4, 7,
460///                         2, 5, 8)));
461/// ```
462/// ### Index to a Range of Columns
463/// ```
464/// # use nalgebra::*;
465/// let matrix = Matrix3::new(0, 3, 6,
466///                           1, 4, 7,
467///                           2, 5, 8);
468///
469/// assert!(matrix.index((.., 1..3))
470///     .eq(&Matrix3x2::new(3, 6,
471///                         4, 7,
472///                         5, 8)));
473/// ```
474impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
475    /// Produces a view of the data at the given index, or
476    /// `None` if the index is out of bounds.
477    #[inline]
478    #[must_use]
479    pub fn get<'a, I>(&'a self, index: I) -> Option<I::Output>
480    where
481        I: MatrixIndex<'a, T, R, C, S>,
482    {
483        index.get(self)
484    }
485
486    /// Produces a mutable view of the data at the given index, or
487    /// `None` if the index is out of bounds.
488    #[inline]
489    #[must_use]
490    pub fn get_mut<'a, I>(&'a mut self, index: I) -> Option<I::OutputMut>
491    where
492        S: RawStorageMut<T, R, C>,
493        I: MatrixIndexMut<'a, T, R, C, S>,
494    {
495        index.get_mut(self)
496    }
497
498    /// Produces a view of the data at the given index, or
499    /// panics if the index is out of bounds.
500    #[inline]
501    #[must_use]
502    pub fn index<'a, I>(&'a self, index: I) -> I::Output
503    where
504        I: MatrixIndex<'a, T, R, C, S>,
505    {
506        index.index(self)
507    }
508
509    /// Produces a mutable view of the data at the given index, or
510    /// panics if the index is out of bounds.
511    #[inline]
512    pub fn index_mut<'a, I>(&'a mut self, index: I) -> I::OutputMut
513    where
514        S: RawStorageMut<T, R, C>,
515        I: MatrixIndexMut<'a, T, R, C, S>,
516    {
517        index.index_mut(self)
518    }
519
520    /// Produces a view of the data at the given index, without doing
521    /// any bounds checking.
522    ///
523    /// # Safety
524    ///
525    /// `index` must within bounds of the array.
526    #[inline]
527    #[must_use]
528    pub unsafe fn get_unchecked<'a, I>(&'a self, index: I) -> I::Output
529    where
530        I: MatrixIndex<'a, T, R, C, S>,
531    {
532        index.get_unchecked(self)
533    }
534
535    /// Returns a mutable view of the data at the given index, without doing
536    /// any bounds checking.
537    /// # Safety
538    ///
539    /// `index` must within bounds of the array.
540    #[inline]
541    #[must_use]
542    pub unsafe fn get_unchecked_mut<'a, I>(&'a mut self, index: I) -> I::OutputMut
543    where
544        S: RawStorageMut<T, R, C>,
545        I: MatrixIndexMut<'a, T, R, C, S>,
546    {
547        index.get_unchecked_mut(self)
548    }
549}
550
551// EXTRACT A SINGLE ELEMENT BY 1D LINEAR ADDRESS
552
553impl<'a, T, R, C, S> MatrixIndex<'a, T, R, C, S> for usize
554where
555    T: Scalar,
556    R: Dim,
557    C: Dim,
558    S: RawStorage<T, R, C>,
559{
560    type Output = &'a T;
561
562    #[doc(hidden)]
563    #[inline(always)]
564    fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool {
565        *self < matrix.len()
566    }
567
568    #[doc(hidden)]
569    #[inline(always)]
570    unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
571        let nrows = matrix.shape().0;
572        let row = self % nrows;
573        let col = self / nrows;
574        matrix.data.get_unchecked(row, col)
575    }
576}
577
578impl<'a, T, R, C, S> MatrixIndexMut<'a, T, R, C, S> for usize
579where
580    T: Scalar,
581    R: Dim,
582    C: Dim,
583    S: RawStorageMut<T, R, C>,
584{
585    type OutputMut = &'a mut T;
586
587    #[doc(hidden)]
588    #[inline(always)]
589    unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
590    where
591        S: RawStorageMut<T, R, C>,
592    {
593        let nrows = matrix.shape().0;
594        let row = self % nrows;
595        let col = self / nrows;
596        matrix.data.get_unchecked_mut(row, col)
597    }
598}
599
600// EXTRACT A SINGLE ELEMENT BY 2D COORDINATES
601
602impl<'a, T: 'a, R, C, S> MatrixIndex<'a, T, R, C, S> for (usize, usize)
603where
604    R: Dim,
605    C: Dim,
606    S: RawStorage<T, R, C>,
607{
608    type Output = &'a T;
609
610    #[doc(hidden)]
611    #[inline(always)]
612    fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool {
613        let (rows, cols) = self;
614        let (nrows, ncols) = matrix.shape_generic();
615        DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
616    }
617
618    #[doc(hidden)]
619    #[inline(always)]
620    unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
621        let (row, col) = self;
622        matrix.data.get_unchecked(row, col)
623    }
624}
625
626impl<'a, T: 'a, R, C, S> MatrixIndexMut<'a, T, R, C, S> for (usize, usize)
627where
628    R: Dim,
629    C: Dim,
630    S: RawStorageMut<T, R, C>,
631{
632    type OutputMut = &'a mut T;
633
634    #[doc(hidden)]
635    #[inline(always)]
636    unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
637    where
638        S: RawStorageMut<T, R, C>,
639    {
640        let (row, col) = self;
641        matrix.data.get_unchecked_mut(row, col)
642    }
643}
644
645macro_rules! impl_index_pair {
646    (
647      $R: ident,
648      $C: ident,
649      [<$($RTyP: ident : $RTyPB: ty,)*> usize => $ROut: ty
650        $(where $RConstraintType: ty: $RConstraintBound: ident<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)*],
651      [<$($CTyP: ident : $CTyPB: ty,)*> usize => $COut: ty
652        $(where $CConstraintType: ty: $CConstraintBound: ident<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)*]
653    ) => {};
654
655    (
656      $R: ident,
657      $C: ident,
658      [<$($RTyP: ident: $RTyPB: tt),*> $RIdx: ty => $ROut: ty
659        $(where $RConstraintType: ty: $RConstraintBound: ident $(<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)* )*],
660      [<$($CTyP: ident: $CTyPB: tt),*> $CIdx: ty => $COut: ty
661        $(where $CConstraintType: ty: $CConstraintBound: ident $(<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)* )*]
662    ) =>
663    {
664        impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndex<'a, T, $R, $C, S> for ($RIdx, $CIdx)
665        where
666            T: Scalar,
667            $R: Dim,
668            $C: Dim,
669            S: RawStorage<T, R, C>,
670            $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
671            $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
672        {
673            type Output = MatrixView<'a, T, $ROut, $COut, S::RStride, S::CStride>;
674
675            #[doc(hidden)]
676            #[inline(always)]
677            fn contained_by(&self, matrix: &Matrix<T, $R, $C, S>) -> bool {
678                let (rows, cols) = self;
679                let (nrows, ncols) = matrix.shape_generic();
680                DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
681            }
682
683            #[doc(hidden)]
684            #[inline(always)]
685            unsafe fn get_unchecked(self, matrix: &'a Matrix<T, $R, $C, S>) -> Self::Output {
686                use crate::base::ViewStorage;
687
688                let (rows, cols) = self;
689                let (nrows, ncols) = matrix.shape_generic();
690
691                let data =
692                    ViewStorage::new_unchecked(&matrix.data,
693                        (rows.lower(nrows),  cols.lower(ncols)),
694                        (rows.length(nrows), cols.length(ncols)));
695
696                Matrix::from_data_statically_unchecked(data)
697            }
698        }
699
700        impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndexMut<'a, T, $R, $C, S> for ($RIdx, $CIdx)
701        where
702            T: Scalar,
703            $R: Dim,
704            $C: Dim,
705            S: RawStorageMut<T, R, C>,
706            $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
707            $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
708        {
709            type OutputMut = MatrixViewMut<'a, T, $ROut, $COut, S::RStride, S::CStride>;
710
711            #[doc(hidden)]
712            #[inline(always)]
713            unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, $R, $C, S>) -> Self::OutputMut {
714                use crate::base::ViewStorageMut;
715
716                let (rows, cols) = self;
717                let (nrows, ncols) = matrix.shape_generic();
718
719                let data =
720                    ViewStorageMut::new_unchecked(&mut matrix.data,
721                        (rows.lower(nrows),  cols.lower(ncols)),
722                        (rows.length(nrows), cols.length(ncols)));
723
724                Matrix::from_data_statically_unchecked(data)
725            }
726        }
727    }
728}
729
730macro_rules! impl_index_pairs {
731    (index $R: ident with {} index $C: ident with {$($r: tt,)* }) => {};
732
733    (index $R: ident with {$lh : tt, $($lt : tt,)*}
734     index $C: ident with { $($r: tt,)* }) =>
735    {
736        $(
737            impl_index_pair!{$R, $C, $lh, $r}
738        )*
739        impl_index_pairs!{index $R with {$($lt,)*} index $C with {$($r,)*}}
740    }
741}
742
743impl_index_pairs! {
744    index R with {
745        [<> usize                         =>  U1],
746        [<> ops::Range<usize>             =>  Dyn],
747        [<> ops::RangeFrom<usize>         =>  Dyn],
748        [<> ops::RangeFull                =>  R],
749        [<> ops::RangeInclusive<usize>    =>  Dyn],
750        [<> ops::RangeTo<usize>           =>  Dyn],
751        [<> ops::RangeToInclusive<usize>  =>  Dyn],
752
753        [<I: Dim> ops::RangeFrom<I>
754          =>  DimDiff<R, I>
755          where R: DimSub<I>],
756    }
757    index C with {
758        [<> usize                         =>  U1],
759        [<> ops::Range<usize>             =>  Dyn],
760        [<> ops::RangeFrom<usize>         =>  Dyn],
761        [<> ops::RangeFull                =>  C],
762        [<> ops::RangeInclusive<usize>    =>  Dyn],
763        [<> ops::RangeTo<usize>           =>  Dyn],
764        [<> ops::RangeToInclusive<usize>  =>  Dyn],
765
766        [<J: DimName> ops::RangeFrom<J>
767          =>  DimDiff<C, J>
768          where C: DimSub<J>],
769    }
770}