1#![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
11trait DimRange<D: Dim> {
13 type Length: Dim;
15
16 fn lower(&self, dimension: D) -> usize;
18
19 fn length(&self, dimension: D) -> Self::Length;
21
22 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
307pub trait MatrixIndex<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>>: Sized {
309 type Output: 'a;
311
312 #[doc(hidden)]
314 fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool;
315
316 #[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 #[doc(hidden)]
331 unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output;
332
333 #[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
342pub trait MatrixIndexMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>>:
344 MatrixIndex<'a, T, R, C, S>
345{
346 type OutputMut: 'a;
348
349 #[doc(hidden)]
352 unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut;
353
354 #[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 #[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
375impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
475 #[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 #[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 #[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 #[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 #[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 unsafe { index.get_unchecked(self) }
533 }
534
535 #[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 unsafe { index.get_unchecked_mut(self) }
548 }
549}
550
551impl<'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 unsafe {
572 let nrows = matrix.shape().0;
573 let row = self % nrows;
574 let col = self / nrows;
575 matrix.data.get_unchecked(row, col)
576 }
577 }
578}
579
580impl<'a, T, R, C, S> MatrixIndexMut<'a, T, R, C, S> for usize
581where
582 T: Scalar,
583 R: Dim,
584 C: Dim,
585 S: RawStorageMut<T, R, C>,
586{
587 type OutputMut = &'a mut T;
588
589 #[doc(hidden)]
590 #[inline(always)]
591 unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
592 where
593 S: RawStorageMut<T, R, C>,
594 {
595 unsafe {
596 let nrows = matrix.shape().0;
597 let row = self % nrows;
598 let col = self / nrows;
599 matrix.data.get_unchecked_mut(row, col)
600 }
601 }
602}
603
604impl<'a, T: 'a, R, C, S> MatrixIndex<'a, T, R, C, S> for (usize, usize)
607where
608 R: Dim,
609 C: Dim,
610 S: RawStorage<T, R, C>,
611{
612 type Output = &'a T;
613
614 #[doc(hidden)]
615 #[inline(always)]
616 fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool {
617 let (rows, cols) = self;
618 let (nrows, ncols) = matrix.shape_generic();
619 DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
620 }
621
622 #[doc(hidden)]
623 #[inline(always)]
624 unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output {
625 unsafe {
626 let (row, col) = self;
627 matrix.data.get_unchecked(row, col)
628 }
629 }
630}
631
632impl<'a, T: 'a, R, C, S> MatrixIndexMut<'a, T, R, C, S> for (usize, usize)
633where
634 R: Dim,
635 C: Dim,
636 S: RawStorageMut<T, R, C>,
637{
638 type OutputMut = &'a mut T;
639
640 #[doc(hidden)]
641 #[inline(always)]
642 unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut
643 where
644 S: RawStorageMut<T, R, C>,
645 {
646 unsafe {
647 let (row, col) = self;
648 matrix.data.get_unchecked_mut(row, col)
649 }
650 }
651}
652
653macro_rules! impl_index_pair {
654 (
655 $R: ident,
656 $C: ident,
657 [<$($RTyP: ident : $RTyPB: ty,)*> usize => $ROut: ty
658 $(where $RConstraintType: ty: $RConstraintBound: ident<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)*],
659 [<$($CTyP: ident : $CTyPB: ty,)*> usize => $COut: ty
660 $(where $CConstraintType: ty: $CConstraintBound: ident<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)*]
661 ) => {};
662
663 (
664 $R: ident,
665 $C: ident,
666 [<$($RTyP: ident: $RTyPB: tt),*> $RIdx: ty => $ROut: ty
667 $(where $RConstraintType: ty: $RConstraintBound: ident $(<$($RConstraintBoundParams: ty $( = $REqBound: ty )*),*>)* )*],
668 [<$($CTyP: ident: $CTyPB: tt),*> $CIdx: ty => $COut: ty
669 $(where $CConstraintType: ty: $CConstraintBound: ident $(<$($CConstraintBoundParams: ty $( = $CEqBound: ty )*),*>)* )*]
670 ) =>
671 {
672 impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndex<'a, T, $R, $C, S> for ($RIdx, $CIdx)
673 where
674 T: Scalar,
675 $R: Dim,
676 $C: Dim,
677 S: RawStorage<T, R, C>,
678 $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
679 $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
680 {
681 type Output = MatrixView<'a, T, $ROut, $COut, S::RStride, S::CStride>;
682
683 #[doc(hidden)]
684 #[inline(always)]
685 fn contained_by(&self, matrix: &Matrix<T, $R, $C, S>) -> bool {
686 let (rows, cols) = self;
687 let (nrows, ncols) = matrix.shape_generic();
688 DimRange::contained_by(rows, nrows) && DimRange::contained_by(cols, ncols)
689 }
690
691 #[doc(hidden)]
692 #[inline(always)]
693 unsafe fn get_unchecked(self, matrix: &'a Matrix<T, $R, $C, S>) -> Self::Output { unsafe {
694 use crate::base::ViewStorage;
695
696 let (rows, cols) = self;
697 let (nrows, ncols) = matrix.shape_generic();
698
699 let data =
700 ViewStorage::new_unchecked(&matrix.data,
701 (rows.lower(nrows), cols.lower(ncols)),
702 (rows.length(nrows), cols.length(ncols)));
703
704 Matrix::from_data_statically_unchecked(data)
705 }}
706 }
707
708 impl<'a, T, $R, $C, S, $($RTyP : $RTyPB,)* $($CTyP : $CTyPB),*> MatrixIndexMut<'a, T, $R, $C, S> for ($RIdx, $CIdx)
709 where
710 T: Scalar,
711 $R: Dim,
712 $C: Dim,
713 S: RawStorageMut<T, R, C>,
714 $( $RConstraintType: $RConstraintBound $(<$( $RConstraintBoundParams $( = $REqBound )*),*>)* ,)*
715 $( $CConstraintType: $CConstraintBound $(<$( $CConstraintBoundParams $( = $CEqBound )*),*>)* ),*
716 {
717 type OutputMut = MatrixViewMut<'a, T, $ROut, $COut, S::RStride, S::CStride>;
718
719 #[doc(hidden)]
720 #[inline(always)]
721 unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, $R, $C, S>) -> Self::OutputMut { unsafe {
722 use crate::base::ViewStorageMut;
723
724 let (rows, cols) = self;
725 let (nrows, ncols) = matrix.shape_generic();
726
727 let data =
728 ViewStorageMut::new_unchecked(&mut matrix.data,
729 (rows.lower(nrows), cols.lower(ncols)),
730 (rows.length(nrows), cols.length(ncols)));
731
732 Matrix::from_data_statically_unchecked(data)
733 }}
734 }
735 }
736}
737
738macro_rules! impl_index_pairs {
739 (index $R: ident with {} index $C: ident with {$($r: tt,)* }) => {};
740
741 (index $R: ident with {$lh : tt, $($lt : tt,)*}
742 index $C: ident with { $($r: tt,)* }) =>
743 {
744 $(
745 impl_index_pair!{$R, $C, $lh, $r}
746 )*
747 impl_index_pairs!{index $R with {$($lt,)*} index $C with {$($r,)*}}
748 }
749}
750
751impl_index_pairs! {
752 index R with {
753 [<> usize => U1],
754 [<> ops::Range<usize> => Dyn],
755 [<> ops::RangeFrom<usize> => Dyn],
756 [<> ops::RangeFull => R],
757 [<> ops::RangeInclusive<usize> => Dyn],
758 [<> ops::RangeTo<usize> => Dyn],
759 [<> ops::RangeToInclusive<usize> => Dyn],
760
761 [<I: Dim> ops::RangeFrom<I>
762 => DimDiff<R, I>
763 where R: DimSub<I>],
764 }
765 index C with {
766 [<> usize => U1],
767 [<> ops::Range<usize> => Dyn],
768 [<> ops::RangeFrom<usize> => Dyn],
769 [<> ops::RangeFull => C],
770 [<> ops::RangeInclusive<usize> => Dyn],
771 [<> ops::RangeTo<usize> => Dyn],
772 [<> ops::RangeToInclusive<usize> => Dyn],
773
774 [<J: DimName> ops::RangeFrom<J>
775 => DimDiff<C, J>
776 where C: DimSub<J>],
777 }
778}