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