1#![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
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 = 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
313pub trait MatrixIndex<'a, T, R: Dim, C: Dim, S: RawStorage<T, R, C>>: Sized {
315 type Output: 'a;
317
318 #[doc(hidden)]
320 fn contained_by(&self, matrix: &Matrix<T, R, C, S>) -> bool;
321
322 #[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 #[doc(hidden)]
337 unsafe fn get_unchecked(self, matrix: &'a Matrix<T, R, C, S>) -> Self::Output;
338
339 #[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
348pub trait MatrixIndexMut<'a, T, R: Dim, C: Dim, S: RawStorageMut<T, R, C>>:
350 MatrixIndex<'a, T, R, C, S>
351{
352 type OutputMut: 'a;
354
355 #[doc(hidden)]
358 unsafe fn get_unchecked_mut(self, matrix: &'a mut Matrix<T, R, C, S>) -> Self::OutputMut;
359
360 #[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 #[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
381impl<T, R: Dim, C: Dim, S: RawStorage<T, R, C>> Matrix<T, R, C, S> {
481 #[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 #[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 #[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 #[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 #[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 #[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
550impl<'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
599impl<'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}