1#![allow(missing_docs)]
2
3use core::marker::PhantomData;
4
5use crate::col::{Col, ColMut, ColRef};
6use crate::mat::{Mat, MatMut, MatRef};
7use crate::row::{Row, RowMut, RowRef};
8use crate::{ContiguousFwd, Idx, Shape, Stride, Unbind};
9use equator::{assert, debug_assert};
10use reborrow::*;
11
12pub trait IntoView {
13 type Target;
14
15 fn into_view(self) -> Self::Target;
16}
17
18impl<'a, T, Rows: Shape, Cols: Shape> IntoView for &'a mut Mat<T, Rows, Cols> {
19 type Target = MatMut<'a, T, Rows, Cols, ContiguousFwd>;
20
21 #[inline]
22 fn into_view(self) -> Self::Target {
23 self.as_mut().try_as_col_major_mut().unwrap()
24 }
25}
26impl<'a, T, Rows: Shape, Cols: Shape> IntoView for &'a Mat<T, Rows, Cols> {
27 type Target = MatRef<'a, T, Rows, Cols, ContiguousFwd>;
28
29 #[inline]
30 fn into_view(self) -> Self::Target {
31 self.as_ref().try_as_col_major().unwrap()
32 }
33}
34
35impl<'a, T, Len: Shape> IntoView for &'a mut Col<T, Len> {
36 type Target = ColMut<'a, T, Len, ContiguousFwd>;
37
38 #[inline]
39 fn into_view(self) -> Self::Target {
40 self.as_mut().try_as_col_major_mut().unwrap()
41 }
42}
43impl<'a, T, Len: Shape> IntoView for &'a Col<T, Len> {
44 type Target = ColRef<'a, T, Len, ContiguousFwd>;
45
46 #[inline]
47 fn into_view(self) -> Self::Target {
48 self.as_ref().try_as_col_major().unwrap()
49 }
50}
51
52impl<'a, T, Len: Shape> IntoView for &'a mut Row<T, Len> {
53 type Target = RowMut<'a, T, Len, ContiguousFwd>;
54
55 #[inline]
56 fn into_view(self) -> Self::Target {
57 self.as_mut().try_as_row_major_mut().unwrap()
58 }
59}
60impl<'a, T, Len: Shape> IntoView for &'a Row<T, Len> {
61 type Target = RowRef<'a, T, Len, ContiguousFwd>;
62
63 #[inline]
64 fn into_view(self) -> Self::Target {
65 self.as_ref().try_as_row_major().unwrap()
66 }
67}
68
69impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for MatMut<'a, T, Rows, Cols, RStride, CStride> {
70 type Target = Self;
71
72 #[inline]
73 fn into_view(self) -> Self::Target {
74 self
75 }
76}
77impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for MatRef<'a, T, Rows, Cols, RStride, CStride> {
78 type Target = Self;
79
80 #[inline]
81 fn into_view(self) -> Self::Target {
82 self
83 }
84}
85
86impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a MatMut<'_, T, Rows, Cols, RStride, CStride> {
87 type Target = MatRef<'a, T, Rows, Cols, RStride, CStride>;
88
89 #[inline]
90 fn into_view(self) -> Self::Target {
91 self.rb()
92 }
93}
94impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a MatRef<'_, T, Rows, Cols, RStride, CStride> {
95 type Target = MatRef<'a, T, Rows, Cols, RStride, CStride>;
96
97 #[inline]
98 fn into_view(self) -> Self::Target {
99 *self
100 }
101}
102
103impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a mut MatMut<'_, T, Rows, Cols, RStride, CStride> {
104 type Target = MatMut<'a, T, Rows, Cols, RStride, CStride>;
105
106 #[inline]
107 fn into_view(self) -> Self::Target {
108 self.rb_mut()
109 }
110}
111impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a mut MatRef<'_, T, Rows, Cols, RStride, CStride> {
112 type Target = MatRef<'a, T, Rows, Cols, RStride, CStride>;
113
114 #[inline]
115 fn into_view(self) -> Self::Target {
116 *self
117 }
118}
119
120impl<'a, T, Rows: Shape, RStride: Stride> IntoView for ColMut<'a, T, Rows, RStride> {
121 type Target = Self;
122
123 #[inline]
124 fn into_view(self) -> Self::Target {
125 self
126 }
127}
128impl<'a, T, Rows: Shape, RStride: Stride> IntoView for ColRef<'a, T, Rows, RStride> {
129 type Target = Self;
130
131 #[inline]
132 fn into_view(self) -> Self::Target {
133 self
134 }
135}
136
137impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a ColMut<'_, T, Rows, RStride> {
138 type Target = ColRef<'a, T, Rows, RStride>;
139
140 #[inline]
141 fn into_view(self) -> Self::Target {
142 self.rb()
143 }
144}
145impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a ColRef<'_, T, Rows, RStride> {
146 type Target = ColRef<'a, T, Rows, RStride>;
147
148 #[inline]
149 fn into_view(self) -> Self::Target {
150 *self
151 }
152}
153
154impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a mut ColMut<'_, T, Rows, RStride> {
155 type Target = ColMut<'a, T, Rows, RStride>;
156
157 #[inline]
158 fn into_view(self) -> Self::Target {
159 self.rb_mut()
160 }
161}
162impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a mut ColRef<'_, T, Rows, RStride> {
163 type Target = ColRef<'a, T, Rows, RStride>;
164
165 #[inline]
166 fn into_view(self) -> Self::Target {
167 *self
168 }
169}
170
171impl<'a, T, Cols: Shape, CStride: Stride> IntoView for RowMut<'a, T, Cols, CStride> {
172 type Target = Self;
173
174 #[inline]
175 fn into_view(self) -> Self::Target {
176 self
177 }
178}
179impl<'a, T, Cols: Shape, CStride: Stride> IntoView for RowRef<'a, T, Cols, CStride> {
180 type Target = Self;
181
182 #[inline]
183 fn into_view(self) -> Self::Target {
184 self
185 }
186}
187
188impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a RowMut<'_, T, Cols, CStride> {
189 type Target = RowRef<'a, T, Cols, CStride>;
190
191 #[inline]
192 fn into_view(self) -> Self::Target {
193 self.rb()
194 }
195}
196impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a RowRef<'_, T, Cols, CStride> {
197 type Target = RowRef<'a, T, Cols, CStride>;
198
199 #[inline]
200 fn into_view(self) -> Self::Target {
201 *self
202 }
203}
204
205impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a mut RowMut<'_, T, Cols, CStride> {
206 type Target = RowMut<'a, T, Cols, CStride>;
207
208 #[inline]
209 fn into_view(self) -> Self::Target {
210 self.rb_mut()
211 }
212}
213impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a mut RowRef<'_, T, Cols, CStride> {
214 type Target = RowRef<'a, T, Cols, CStride>;
215
216 #[inline]
217 fn into_view(self) -> Self::Target {
218 *self
219 }
220}
221
222#[derive(Copy, Clone, Debug, PartialEq, Eq)]
223pub enum Diag {
224 Skip,
225 Include,
226}
227
228#[derive(Copy, Clone)]
230pub enum MatLayoutTransform {
231 None,
233 ReverseRows,
235 Transpose,
237 TransposeReverseRows,
239}
240
241#[derive(Copy, Clone)]
243pub enum VecLayoutTransform {
244 None,
246 Reverse,
248}
249
250pub trait MatIndex {
252 type Rows: Copy + Eq + core::fmt::Debug;
254 type Cols: Copy + Eq + core::fmt::Debug;
256 fn nrows(this: &Self) -> Self::Rows;
258 fn ncols(this: &Self) -> Self::Cols;
260
261 type Index: Copy;
263 type LayoutTransform: Copy;
265
266 type Item;
268
269 type Dyn: MatIndex<Dyn = Self::Dyn, LayoutTransform = Self::LayoutTransform, Item = Self::Item, Slice = Self::Slice>;
271
272 type Slice: for<'a> SliceFamily<'a, Self::Item>;
273
274 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice;
276
277 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index;
279
280 unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item;
282 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item;
284
285 fn is_contiguous(this: &Self) -> bool;
287 fn preferred_layout(this: &Self) -> Self::LayoutTransform;
289 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn;
291}
292
293pub trait SliceFamily<'a, T, Outlives = &'a Self> {
294 type Slice;
295}
296pub struct Slice<T>(pub T);
297pub struct SliceRef<'b, T>(pub &'b T);
298pub struct SliceMut<'b, T>(pub &'b mut T);
299
300impl<'a, T> SliceFamily<'a, T> for Slice<T> {
301 type Slice = &'a [T];
302}
303impl<'a, 'b, T> SliceFamily<'a, &'b T> for SliceRef<'b, T> {
304 type Slice = &'b [T];
305}
306impl<'a, 'b, T> SliceFamily<'a, &'b mut T> for SliceMut<'b, T> {
307 type Slice = &'b mut [T];
308}
309impl<'a, T, F: SliceFamily<'a, T>> SliceFamily<'a, Last<T>> for Last<F> {
310 type Slice = Last<F::Slice>;
311}
312impl<'a, T, U, F: SliceFamily<'a, T>, G: SliceFamily<'a, U>> SliceFamily<'a, Zip<T, U>> for Zip<F, G> {
313 type Slice = Zip<F::Slice, G::Slice>;
314}
315
316#[derive(Copy, Clone, Debug)]
318pub struct LastEq<Rows, Cols, Mat>(pub Mat, pub PhantomData<(Rows, Cols)>);
319
320#[derive(Copy, Clone, Debug)]
322pub struct Last<Mat>(pub Mat);
323
324#[derive(Copy, Clone, Debug)]
326pub struct ZipEq<Rows, Cols, Head, Tail>(pub Head, pub Tail, PhantomData<(Rows, Cols)>);
327
328#[derive(Copy, Clone, Debug)]
330pub struct Zip<Head, Tail>(pub Head, pub Tail);
331
332impl<
334 Rows: Copy + Eq + core::fmt::Debug,
335 Cols: Copy + Eq + core::fmt::Debug,
336 Head: MatIndex<Rows = Rows, Cols = Cols>,
337 Tail: MatIndex<Rows = Rows, Cols = Cols>,
338> ZipEq<Rows, Cols, Head, Tail>
339{
340 #[inline(always)]
342 #[track_caller]
343 pub fn new(head: Head, tail: Tail) -> Self {
344 assert!(all(Head::nrows(&head) == Tail::nrows(&tail), Head::ncols(&head) == Tail::ncols(&tail),));
345 Self(head, tail, PhantomData)
346 }
347
348 #[inline(always)]
350 #[track_caller]
351 pub fn new_unchecked(head: Head, tail: Tail) -> Self {
352 debug_assert!(all(Head::nrows(&head) == Tail::nrows(&tail), Head::ncols(&head) == Tail::ncols(&tail),));
353 Self(head, tail, PhantomData)
354 }
355}
356
357impl<Rows: Copy + Eq + core::fmt::Debug, Cols: Copy + Eq + core::fmt::Debug, Mat: MatIndex<Rows = Rows, Cols = Cols>> MatIndex
358 for LastEq<Rows, Cols, Mat>
359{
360 type Cols = Mat::Cols;
361 type Dyn = LastEq<<Mat::Dyn as MatIndex>::Rows, <Mat::Dyn as MatIndex>::Cols, Mat::Dyn>;
362 type Index = Mat::Index;
363 type Item = Last<Mat::Item>;
364 type LayoutTransform = Mat::LayoutTransform;
365 type Rows = Mat::Rows;
366 type Slice = Last<Mat::Slice>;
367
368 #[inline(always)]
369 fn nrows(this: &Self) -> Self::Rows {
370 Mat::nrows(&this.0)
371 }
372
373 #[inline(always)]
374 fn ncols(this: &Self) -> Self::Cols {
375 Mat::ncols(&this.0)
376 }
377
378 #[inline]
379 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
380 Last(Mat::get_slice_unchecked(&mut this.0, idx, n_elems))
381 }
382
383 #[inline]
384 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
385 Mat::from_dyn_idx(idx)
386 }
387
388 #[inline]
389 unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item {
390 Last(Mat::get_unchecked(&mut this.0, index))
391 }
392
393 #[inline]
394 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
395 Last(Mat::next_unchecked(&mut slice.0))
396 }
397
398 #[inline]
399 fn is_contiguous(this: &Self) -> bool {
400 Mat::is_contiguous(&this.0)
401 }
402
403 #[inline]
404 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
405 Mat::preferred_layout(&this.0)
406 }
407
408 #[inline]
409 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
410 LastEq(Mat::with_layout(this.0, layout), PhantomData)
411 }
412}
413
414impl<
415 Rows: Copy + Eq + core::fmt::Debug,
416 Cols: Copy + Eq + core::fmt::Debug,
417 L: MatIndex<Rows = Rows, Cols = Cols>,
418 R: MatIndex<Rows = Rows, Cols = Cols, Index = L::Index, LayoutTransform = L::LayoutTransform>,
419> MatIndex for ZipEq<Rows, Cols, L, R>
420where
421 R::Dyn: MatIndex<Rows = <L::Dyn as MatIndex>::Rows, Cols = <L::Dyn as MatIndex>::Cols, Index = <L::Dyn as MatIndex>::Index>,
422{
423 type Cols = L::Cols;
424 type Dyn = ZipEq<<L::Dyn as MatIndex>::Rows, <L::Dyn as MatIndex>::Cols, L::Dyn, R::Dyn>;
425 type Index = L::Index;
426 type Item = Zip<L::Item, R::Item>;
427 type LayoutTransform = L::LayoutTransform;
428 type Rows = L::Rows;
429 type Slice = Zip<L::Slice, R::Slice>;
430
431 #[inline(always)]
432 fn nrows(this: &Self) -> Self::Rows {
433 L::nrows(&this.0)
434 }
435
436 #[inline(always)]
437 fn ncols(this: &Self) -> Self::Cols {
438 L::ncols(&this.0)
439 }
440
441 #[inline]
442 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
443 Zip(
444 L::get_slice_unchecked(&mut this.0, idx, n_elems),
445 R::get_slice_unchecked(&mut this.1, idx, n_elems),
446 )
447 }
448
449 #[inline]
450 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
451 L::from_dyn_idx(idx)
452 }
453
454 #[inline]
455 unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item {
456 Zip(L::get_unchecked(&mut this.0, index), R::get_unchecked(&mut this.1, index))
457 }
458
459 #[inline]
460 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
461 Zip(L::next_unchecked(&mut slice.0), R::next_unchecked(&mut slice.1))
462 }
463
464 #[inline]
465 fn is_contiguous(this: &Self) -> bool {
466 L::is_contiguous(&this.0) && R::is_contiguous(&this.1)
467 }
468
469 #[inline]
470 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
471 L::preferred_layout(&this.0)
472 }
473
474 #[inline]
475 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
476 ZipEq(L::with_layout(this.0, layout), R::with_layout(this.1, layout), PhantomData)
477 }
478}
479
480impl<'b, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> MatIndex for MatMut<'b, T, Rows, Cols, RStride, CStride> {
481 type Cols = Cols;
482 type Dyn = MatMut<'b, T, usize, usize, isize, isize>;
483 type Index = (Idx<Rows>, Idx<Cols>);
484 type Item = &'b mut T;
485 type LayoutTransform = MatLayoutTransform;
486 type Rows = Rows;
487 type Slice = SliceMut<'b, T>;
488
489 #[inline]
490 fn nrows(this: &Self) -> Self::Rows {
491 this.nrows()
492 }
493
494 #[inline]
495 fn ncols(this: &Self) -> Self::Cols {
496 this.ncols()
497 }
498
499 #[inline]
500 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
501 let ptr = this.ptr_inbounds_at_mut(idx.0, idx.1);
502 core::slice::from_raw_parts_mut(ptr, n_elems)
503 }
504
505 #[inline]
506 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
507 (Idx::<Rows>::new_unbound(idx.0), Idx::<Cols>::new_unbound(idx.1))
508 }
509
510 #[inline]
511 unsafe fn get_unchecked(this: &mut Self, (i, j): Self::Index) -> Self::Item {
512 let ptr = this.rb().ptr_inbounds_at_mut(i, j);
513 &mut *ptr
514 }
515
516 #[inline(always)]
517 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
518 let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
519 *slice = tail;
520 head
521 }
522
523 #[inline(always)]
524 fn is_contiguous(this: &Self) -> bool {
525 this.row_stride().element_stride() == 1
526 }
527
528 #[inline(always)]
529 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
530 let rs = this.row_stride().element_stride();
531 let cs = this.col_stride().element_stride();
532 let nrows = this.nrows().unbound();
533 let ncols = this.ncols().unbound();
534
535 if nrows > 1 && rs == 1 {
536 MatLayoutTransform::None
537 } else if nrows > 1 && rs == -1 {
538 MatLayoutTransform::ReverseRows
539 } else if ncols > 1 && cs == 1 {
540 MatLayoutTransform::Transpose
541 } else if ncols > 1 && cs == -1 {
542 MatLayoutTransform::TransposeReverseRows
543 } else {
544 MatLayoutTransform::None
545 }
546 }
547
548 #[inline(always)]
549 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
550 use MatLayoutTransform::*;
551 let this = this.as_dyn_mut().as_dyn_stride_mut();
552 match layout {
553 None => this,
554 ReverseRows => this.reverse_rows_mut(),
555 Transpose => this.transpose_mut(),
556 TransposeReverseRows => this.transpose_mut().reverse_rows_mut(),
557 }
558 }
559}
560
561impl<'b, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> MatIndex for MatRef<'b, T, Rows, Cols, RStride, CStride> {
562 type Cols = Cols;
563 type Dyn = MatRef<'b, T, usize, usize, isize, isize>;
564 type Index = (Idx<Rows>, Idx<Cols>);
565 type Item = &'b T;
566 type LayoutTransform = MatLayoutTransform;
567 type Rows = Rows;
568 type Slice = SliceRef<'b, T>;
569
570 #[inline]
571 fn nrows(this: &Self) -> Self::Rows {
572 this.nrows()
573 }
574
575 #[inline]
576 fn ncols(this: &Self) -> Self::Cols {
577 this.ncols()
578 }
579
580 #[inline]
581 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
582 let ptr = this.ptr_inbounds_at(idx.0, idx.1);
583 core::slice::from_raw_parts(ptr, n_elems)
584 }
585
586 #[inline]
587 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
588 (Idx::<Rows>::new_unbound(idx.0), Idx::<Cols>::new_unbound(idx.1))
589 }
590
591 #[inline]
592 unsafe fn get_unchecked(this: &mut Self, (i, j): Self::Index) -> Self::Item {
593 let ptr = this.rb().ptr_inbounds_at(i, j);
594 &*ptr
595 }
596
597 #[inline(always)]
598 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
599 let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
600 *slice = tail;
601 head
602 }
603
604 #[inline(always)]
605 fn is_contiguous(this: &Self) -> bool {
606 this.row_stride().element_stride() == 1
607 }
608
609 #[inline(always)]
610 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
611 let rs = this.row_stride().element_stride();
612 let cs = this.col_stride().element_stride();
613 let nrows = this.nrows().unbound();
614 let ncols = this.ncols().unbound();
615
616 if nrows > 1 && rs == 1 {
617 MatLayoutTransform::None
618 } else if nrows > 1 && rs == -1 {
619 MatLayoutTransform::ReverseRows
620 } else if ncols > 1 && cs == 1 {
621 MatLayoutTransform::Transpose
622 } else if ncols > 1 && cs == -1 {
623 MatLayoutTransform::TransposeReverseRows
624 } else {
625 MatLayoutTransform::None
626 }
627 }
628
629 #[inline(always)]
630 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
631 use MatLayoutTransform::*;
632 let this = this.as_dyn().as_dyn_stride();
633 match layout {
634 None => this,
635 ReverseRows => this.reverse_rows(),
636 Transpose => this.transpose(),
637 TransposeReverseRows => this.transpose().reverse_rows(),
638 }
639 }
640}
641
642impl<'b, T, Len: Shape, Strd: Stride> MatIndex for ColMut<'b, T, Len, Strd> {
643 type Cols = ();
644 type Dyn = ColMut<'b, T, usize, isize>;
645 type Index = Idx<Len>;
646 type Item = &'b mut T;
647 type LayoutTransform = VecLayoutTransform;
648 type Rows = Len;
649 type Slice = SliceMut<'b, T>;
650
651 #[inline]
652 fn nrows(this: &Self) -> Self::Rows {
653 this.nrows()
654 }
655
656 #[inline]
657 fn ncols(_: &Self) -> Self::Cols {
658 ()
659 }
660
661 #[inline]
662 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
663 let ptr = this.ptr_inbounds_at_mut(idx);
664 core::slice::from_raw_parts_mut(ptr, n_elems)
665 }
666
667 #[inline]
668 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
669 Idx::<Len>::new_unbound(idx)
670 }
671
672 #[inline]
673 unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
674 let ptr = this.rb().ptr_inbounds_at_mut(i);
675 &mut *ptr
676 }
677
678 #[inline(always)]
679 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
680 let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
681 *slice = tail;
682 head
683 }
684
685 #[inline(always)]
686 fn is_contiguous(this: &Self) -> bool {
687 this.row_stride().element_stride() == 1
688 }
689
690 #[inline(always)]
691 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
692 let strd = this.row_stride().element_stride();
693 let len = this.nrows().unbound();
694
695 if len > 1 && strd == 1 {
696 VecLayoutTransform::None
697 } else if len > 1 && strd == -1 {
698 VecLayoutTransform::Reverse
699 } else {
700 VecLayoutTransform::None
701 }
702 }
703
704 #[inline(always)]
705 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
706 use VecLayoutTransform::*;
707 let this = this.as_dyn_rows_mut().as_dyn_stride_mut();
708 match layout {
709 None => this,
710 Reverse => this.reverse_rows_mut(),
711 }
712 }
713}
714
715impl<'b, T, Len: Shape, Strd: Stride> MatIndex for RowMut<'b, T, Len, Strd> {
716 type Cols = Len;
717 type Dyn = RowMut<'b, T, usize, isize>;
718 type Index = Idx<Len>;
719 type Item = &'b mut T;
720 type LayoutTransform = VecLayoutTransform;
721 type Rows = ();
722 type Slice = SliceMut<'b, T>;
723
724 #[inline]
725 fn nrows(_: &Self) -> Self::Rows {
726 ()
727 }
728
729 #[inline]
730 fn ncols(this: &Self) -> Self::Cols {
731 this.ncols()
732 }
733
734 #[inline]
735 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
736 let ptr = this.ptr_inbounds_at_mut(idx);
737 core::slice::from_raw_parts_mut(ptr, n_elems)
738 }
739
740 #[inline]
741 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
742 Idx::<Len>::new_unbound(idx)
743 }
744
745 #[inline]
746 unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
747 let ptr = this.rb().ptr_inbounds_at_mut(i);
748 &mut *ptr
749 }
750
751 #[inline(always)]
752 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
753 let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
754 *slice = tail;
755 head
756 }
757
758 #[inline(always)]
759 fn is_contiguous(this: &Self) -> bool {
760 this.col_stride().element_stride() == 1
761 }
762
763 #[inline(always)]
764 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
765 let strd = this.col_stride().element_stride();
766 let len = this.ncols().unbound();
767
768 if len > 1 && strd == 1 {
769 VecLayoutTransform::None
770 } else if len > 1 && strd == -1 {
771 VecLayoutTransform::Reverse
772 } else {
773 VecLayoutTransform::None
774 }
775 }
776
777 #[inline(always)]
778 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
779 use VecLayoutTransform::*;
780 let this = this.as_dyn_cols_mut().as_dyn_stride_mut();
781 match layout {
782 None => this,
783 Reverse => this.reverse_cols_mut(),
784 }
785 }
786}
787
788impl<'b, T, Len: Shape, Strd: Stride> MatIndex for ColRef<'b, T, Len, Strd> {
789 type Cols = ();
790 type Dyn = ColRef<'b, T, usize, isize>;
791 type Index = Idx<Len>;
792 type Item = &'b T;
793 type LayoutTransform = VecLayoutTransform;
794 type Rows = Len;
795 type Slice = SliceRef<'b, T>;
796
797 #[inline]
798 fn nrows(this: &Self) -> Self::Rows {
799 this.nrows()
800 }
801
802 #[inline]
803 fn ncols(_: &Self) -> Self::Cols {
804 ()
805 }
806
807 #[inline]
808 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
809 let ptr = this.ptr_inbounds_at(idx);
810 core::slice::from_raw_parts(ptr, n_elems)
811 }
812
813 #[inline]
814 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
815 Idx::<Len>::new_unbound(idx)
816 }
817
818 #[inline]
819 unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
820 let ptr = this.rb().ptr_inbounds_at(i);
821 &*ptr
822 }
823
824 #[inline(always)]
825 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
826 let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
827 *slice = tail;
828 head
829 }
830
831 #[inline(always)]
832 fn is_contiguous(this: &Self) -> bool {
833 this.row_stride().element_stride() == 1
834 }
835
836 #[inline(always)]
837 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
838 let strd = this.row_stride().element_stride();
839 let len = this.nrows().unbound();
840
841 if len > 1 && strd == 1 {
842 VecLayoutTransform::None
843 } else if len > 1 && strd == -1 {
844 VecLayoutTransform::Reverse
845 } else {
846 VecLayoutTransform::None
847 }
848 }
849
850 #[inline(always)]
851 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
852 use VecLayoutTransform::*;
853 let this = this.as_dyn_rows().as_dyn_stride();
854 match layout {
855 None => this,
856 Reverse => this.reverse_rows(),
857 }
858 }
859}
860
861impl<'b, T, Len: Shape, Strd: Stride> MatIndex for RowRef<'b, T, Len, Strd> {
862 type Cols = Len;
863 type Dyn = RowRef<'b, T, usize, isize>;
864 type Index = Idx<Len>;
865 type Item = &'b T;
866 type LayoutTransform = VecLayoutTransform;
867 type Rows = ();
868 type Slice = SliceRef<'b, T>;
869
870 #[inline]
871 fn nrows(_: &Self) -> Self::Rows {
872 ()
873 }
874
875 #[inline]
876 fn ncols(this: &Self) -> Self::Cols {
877 this.ncols()
878 }
879
880 #[inline]
881 unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
882 let ptr = this.ptr_inbounds_at(idx);
883 core::slice::from_raw_parts(ptr, n_elems)
884 }
885
886 #[inline]
887 unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
888 Idx::<Len>::new_unbound(idx)
889 }
890
891 #[inline]
892 unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
893 let ptr = this.rb().ptr_inbounds_at(i);
894 &*ptr
895 }
896
897 #[inline(always)]
898 unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
899 let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
900 *slice = tail;
901 head
902 }
903
904 #[inline(always)]
905 fn is_contiguous(this: &Self) -> bool {
906 this.col_stride().element_stride() == 1
907 }
908
909 #[inline(always)]
910 fn preferred_layout(this: &Self) -> Self::LayoutTransform {
911 let strd = this.col_stride().element_stride();
912 let len = this.ncols().unbound();
913
914 if len > 1 && strd == 1 {
915 VecLayoutTransform::None
916 } else if len > 1 && strd == -1 {
917 VecLayoutTransform::Reverse
918 } else {
919 VecLayoutTransform::None
920 }
921 }
922
923 #[inline(always)]
924 fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
925 use VecLayoutTransform::*;
926 let this = this.as_dyn_cols().as_dyn_stride();
927 match layout {
928 None => this,
929 Reverse => this.reverse_cols(),
930 }
931 }
932}
933
934#[inline(always)]
935fn annotate_noalias_mat<Z: MatIndex>(
936 f: &mut impl FnMut(<Z as MatIndex>::Item),
937 mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
938 i_begin: usize,
939 i_end: usize,
940 _j: usize,
941) {
942 for _ in i_begin..i_end {
943 unsafe { f(Z::next_unchecked(&mut slice)) };
944 }
945}
946
947#[inline(always)]
948fn annotate_noalias_mat_with_index<Z: MatIndex<Index = (RowIdx, ColIdx)>, RowIdx, ColIdx>(
949 f: &mut impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
950 mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
951 i_begin: usize,
952 i_end: usize,
953 j: usize,
954 transpose: bool,
955 reverse_rows: bool,
956) where
957 Z::Dyn: MatIndex<Index = (usize, usize)>,
958{
959 if !transpose {
960 if !reverse_rows {
961 for i in i_begin..i_end {
962 unsafe {
963 let (ii, jj) = Z::from_dyn_idx((i, j));
964 f(ii, jj, Z::next_unchecked(&mut slice))
965 };
966 }
967 } else {
968 for i in i_begin..i_end {
969 unsafe {
970 let (ii, jj) = Z::from_dyn_idx((i_begin + (i_end - i - 1), j));
971 f(ii, jj, Z::next_unchecked(&mut slice))
972 };
973 }
974 }
975 } else {
976 if !reverse_rows {
977 for i in i_begin..i_end {
978 unsafe {
979 let (ii, jj) = Z::from_dyn_idx((j, i));
980 f(ii, jj, Z::next_unchecked(&mut slice))
981 };
982 }
983 } else {
984 for i in i_begin..i_end {
985 unsafe {
986 let (ii, jj) = Z::from_dyn_idx((j, i_begin + (i_end - i - 1)));
987 f(ii, jj, Z::next_unchecked(&mut slice))
988 };
989 }
990 }
991 }
992}
993
994#[inline(always)]
995fn annotate_noalias_col<Z: MatIndex>(
996 f: &mut impl FnMut(<Z as MatIndex>::Item),
997 mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
998 i_begin: usize,
999 i_end: usize,
1000) {
1001 for _ in i_begin..i_end {
1002 unsafe { f(Z::next_unchecked(&mut slice)) };
1003 }
1004}
1005
1006#[inline(always)]
1007fn annotate_noalias_col_with_index<Z: MatIndex<Index = Idx>, Idx>(
1008 f: &mut impl FnMut(Idx, <Z as MatIndex>::Item),
1009 mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
1010 i_begin: usize,
1011 i_end: usize,
1012 reverse: bool,
1013) where
1014 Z::Dyn: MatIndex<Item = Z::Item, Index = usize>,
1015{
1016 if !reverse {
1017 for i in i_begin..i_end {
1018 unsafe {
1019 let ii = Z::from_dyn_idx(i);
1020 f(ii, Z::next_unchecked(&mut slice))
1021 };
1022 }
1023 } else {
1024 for i in i_begin..i_end {
1025 unsafe {
1026 let ii = Z::from_dyn_idx(i_begin + (i_end - i - 1));
1027 f(ii, Z::next_unchecked(&mut slice))
1028 };
1029 }
1030 }
1031}
1032
1033#[inline(always)]
1034fn for_each_mat<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1035where
1036 Z::Dyn: MatIndex<Item = Z::Item, Slice = Z::Slice, Rows = usize, Cols = usize, Index = (usize, usize)>,
1037{
1038 let layout = Z::preferred_layout(&z);
1039 let mut z = Z::with_layout(z, layout);
1040
1041 let m = Z::Dyn::nrows(&z);
1042 let n = Z::Dyn::ncols(&z);
1043 if m == 0 || n == 0 {
1044 return;
1045 }
1046
1047 unsafe {
1048 if Z::Dyn::is_contiguous(&z) {
1049 for j in 0..n {
1050 annotate_noalias_mat::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j);
1051 }
1052 } else {
1053 for j in 0..n {
1054 for i in 0..m {
1055 f(Z::Dyn::get_unchecked(&mut z, (i, j)))
1056 }
1057 }
1058 }
1059 }
1060}
1061
1062#[inline(always)]
1066fn for_each_mat_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1067 z: Z,
1068 mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1069) where
1070 Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Slice = Z::Slice, Item = Z::Item>,
1071{
1072 let layout = Z::preferred_layout(&z);
1073 let mut z = Z::with_layout(z, layout);
1074
1075 let m = Z::Dyn::nrows(&z);
1076 let n = Z::Dyn::ncols(&z);
1077 if m == 0 || n == 0 {
1078 return;
1079 }
1080
1081 match layout {
1082 MatLayoutTransform::None => unsafe {
1083 if Z::Dyn::is_contiguous(&z) {
1084 for j in 0..n {
1085 annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, false, false);
1086 }
1087 } else {
1088 for j in 0..n {
1089 for i in 0..m {
1090 let (ii, jj) = Z::from_dyn_idx((i, j));
1091 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1092 }
1093 }
1094 }
1095 },
1096 MatLayoutTransform::ReverseRows => unsafe {
1097 if Z::Dyn::is_contiguous(&z) {
1098 for j in 0..n {
1099 annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, false, true);
1100 }
1101 } else {
1102 for j in 0..n {
1103 for i in 0..m {
1104 let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1105 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1106 }
1107 }
1108 }
1109 },
1110 MatLayoutTransform::Transpose => unsafe {
1111 if Z::Dyn::is_contiguous(&z) {
1112 for j in 0..n {
1113 annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, true, false);
1114 }
1115 } else {
1116 for j in 0..n {
1117 for i in 0..m {
1118 let (ii, jj) = Z::from_dyn_idx((j, i));
1119 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1120 }
1121 }
1122 }
1123 },
1124 MatLayoutTransform::TransposeReverseRows => unsafe {
1125 if Z::Dyn::is_contiguous(&z) {
1126 for j in 0..n {
1127 annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, true, true);
1128 }
1129 } else {
1130 for j in 0..n {
1131 for i in 0..m {
1132 let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1133 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1134 }
1135 }
1136 }
1137 },
1138 }
1139}
1140
1141#[inline(always)]
1142fn for_each_mat_triangular_lower_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1143 z: Z,
1144 diag: Diag,
1145 mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1146) where
1147 Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Item = Z::Item, Slice = Z::Slice>,
1148{
1149 let layout = Z::preferred_layout(&z);
1150 let mut z = Z::with_layout(z, layout);
1151
1152 let m = Z::Dyn::nrows(&z);
1153 let n = Z::Dyn::ncols(&z);
1154 let strict = match diag {
1155 Diag::Skip => true,
1156 Diag::Include => false,
1157 };
1158 let strict = strict as usize;
1159
1160 if m == 0 || n == 0 {
1161 return;
1162 }
1163
1164 match layout {
1165 MatLayoutTransform::None => unsafe {
1166 if Z::Dyn::is_contiguous(&z) {
1167 for j in 0..n {
1168 let start = j + strict;
1169 let end = m;
1170 if start == end {
1171 continue;
1172 }
1173 annotate_noalias_mat_with_index::<Z, _, _>(
1174 &mut f,
1175 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1176 start,
1177 end,
1178 j,
1179 false,
1180 false,
1181 );
1182 }
1183 } else {
1184 for j in 0..n {
1185 let start = j + strict;
1186 let end = m;
1187 if start == end {
1188 continue;
1189 }
1190 for i in start..end {
1191 let (ii, jj) = Z::from_dyn_idx((i, j));
1192 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1193 }
1194 }
1195 }
1196 },
1197 MatLayoutTransform::ReverseRows => unsafe {
1198 if Z::Dyn::is_contiguous(&z) {
1199 for j in 0..Ord::min(m, n) {
1200 let start = 0;
1201 let end = m - j - strict;
1202 if start == end {
1203 continue;
1204 }
1205 annotate_noalias_mat_with_index::<Z, _, _>(
1206 &mut f,
1207 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1208 j + strict + start,
1209 j + strict + end,
1210 j,
1211 false,
1212 true,
1213 );
1214 }
1215 } else {
1216 for j in 0..Ord::min(m, n) {
1217 let start = 0;
1218 let end = m - j - strict;
1219 if start == end {
1220 continue;
1221 }
1222 for i in start..end {
1223 let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1224 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1225 }
1226 }
1227 }
1228 },
1229 MatLayoutTransform::Transpose => unsafe {
1230 if Z::Dyn::is_contiguous(&z) {
1231 for j in 0..n {
1232 let start = 0;
1233 let end = Ord::min(m, j + (1 - strict));
1234 if start == end {
1235 continue;
1236 }
1237 annotate_noalias_mat_with_index::<Z, _, _>(
1238 &mut f,
1239 Z::Dyn::get_slice_unchecked(&mut z, (0, j), end - start),
1240 start,
1241 end,
1242 j,
1243 true,
1244 false,
1245 );
1246 }
1247 } else {
1248 for j in 0..n {
1249 let start = 0;
1250 let end = Ord::min(m, j + (1 - strict));
1251 if start == end {
1252 continue;
1253 }
1254 for i in start..end {
1255 let (ii, jj) = Z::from_dyn_idx((j, i));
1256 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1257 }
1258 }
1259 }
1260 },
1261 MatLayoutTransform::TransposeReverseRows => unsafe {
1262 if Z::Dyn::is_contiguous(&z) {
1263 for j in 0..n {
1264 let start = m - Ord::min(j + (1 - strict) as usize, m);
1265 let end = m;
1266 if start == end {
1267 continue;
1268 }
1269 annotate_noalias_mat_with_index::<Z, _, _>(
1270 &mut f,
1271 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1272 0,
1273 end - start,
1274 j,
1275 true,
1276 true,
1277 );
1278 }
1279 } else {
1280 for j in 0..n {
1281 let start = m - Ord::min(j + (1 - strict) as usize, m);
1282 let end = m;
1283 if start == end {
1284 continue;
1285 }
1286 for i in start..end {
1287 let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1288 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1289 }
1290 }
1291 }
1292 },
1293 }
1294}
1295
1296#[inline(always)]
1297fn for_each_mat_triangular_upper_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1298 z: Z,
1299 diag: Diag,
1300 mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1301) where
1302 Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Item = Z::Item, Slice = Z::Slice>,
1303{
1304 let layout = Z::preferred_layout(&z);
1305 let mut z = Z::with_layout(z, layout);
1306
1307 let m = Z::Dyn::nrows(&z);
1308 let n = Z::Dyn::ncols(&z);
1309 let strict = match diag {
1310 Diag::Skip => true,
1311 Diag::Include => false,
1312 };
1313 let strict = strict as usize;
1314
1315 if m == 0 || n == 0 {
1316 return;
1317 }
1318
1319 match layout {
1320 MatLayoutTransform::None => unsafe {
1321 if Z::Dyn::is_contiguous(&z) {
1322 for j in 0..n {
1323 let start = 0;
1324 let end = Ord::min(m, j + (1 - strict));
1325 if start == end {
1326 continue;
1327 }
1328
1329 annotate_noalias_mat_with_index::<Z, _, _>(
1330 &mut f,
1331 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1332 start,
1333 end,
1334 j,
1335 false,
1336 false,
1337 );
1338 }
1339 } else {
1340 for j in 0..n {
1341 let start = 0;
1342 let end = Ord::min(m, j + (1 - strict));
1343 if start == end {
1344 continue;
1345 }
1346 for i in start..end {
1347 let (ii, jj) = Z::from_dyn_idx((i, j));
1348 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1349 }
1350 }
1351 }
1352 },
1353 MatLayoutTransform::ReverseRows => unsafe {
1354 if Z::Dyn::is_contiguous(&z) {
1355 for j in 0..Ord::min(m, n) {
1356 let start = m - Ord::min(j + (1 - strict) as usize, m);
1357 let end = m;
1358 if start == end {
1359 continue;
1360 }
1361 annotate_noalias_mat_with_index::<Z, _, _>(
1362 &mut f,
1363 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1364 0,
1365 end - start,
1366 j,
1367 false,
1368 true,
1369 );
1370 }
1371 } else {
1372 for j in 0..Ord::min(m, n) {
1373 let start = m - Ord::min(j + (1 - strict) as usize, m);
1374 let end = m;
1375 if start == end {
1376 continue;
1377 }
1378 for i in start..end {
1379 let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1380 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1381 }
1382 }
1383 }
1384 },
1385 MatLayoutTransform::Transpose => unsafe {
1386 if Z::Dyn::is_contiguous(&z) {
1387 for j in 0..n {
1388 let start = j + strict;
1389 let end = m;
1390 if start == end {
1391 continue;
1392 }
1393 annotate_noalias_mat_with_index::<Z, _, _>(
1394 &mut f,
1395 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1396 start,
1397 end,
1398 j,
1399 true,
1400 false,
1401 );
1402 }
1403 } else {
1404 for j in 0..n {
1405 let start = j + strict;
1406 let end = m;
1407 if start == end {
1408 continue;
1409 }
1410 for i in start..end {
1411 let (ii, jj) = Z::from_dyn_idx((j, i));
1412 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1413 }
1414 }
1415 }
1416 },
1417 MatLayoutTransform::TransposeReverseRows => unsafe {
1418 if Z::Dyn::is_contiguous(&z) {
1419 for j in 0..n {
1420 let start = 0;
1421 let end = m - j - strict;
1422 if start == end {
1423 continue;
1424 }
1425 annotate_noalias_mat_with_index::<Z, _, _>(
1426 &mut f,
1427 Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1428 j + strict,
1429 j + strict + end - start,
1430 j,
1431 true,
1432 true,
1433 );
1434 }
1435 } else {
1436 for j in 0..n {
1437 let start = 0;
1438 let end = m - j - strict;
1439 if start == end {
1440 continue;
1441 }
1442 for i in start..end {
1443 let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1444 f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1445 }
1446 }
1447 }
1448 },
1449 }
1450}
1451
1452#[inline(always)]
1453fn for_each_mat_triangular_lower<Z: MatIndex<LayoutTransform = MatLayoutTransform>>(
1454 z: Z,
1455 diag: Diag,
1456 transpose: bool,
1457 mut f: impl FnMut(<Z as MatIndex>::Item),
1458) where
1459 Z::Dyn: MatIndex<
1460 LayoutTransform = MatLayoutTransform,
1461 Item = Z::Item,
1462 Slice = Z::Slice,
1463 Rows = usize,
1464 Cols = usize,
1465 Index = (usize, usize),
1466 Dyn = Z::Dyn,
1467 >,
1468{
1469 use MatLayoutTransform::*;
1470
1471 let z = if transpose {
1472 Z::with_layout(z, MatLayoutTransform::Transpose)
1473 } else {
1474 Z::with_layout(z, MatLayoutTransform::None)
1475 };
1476 let layout = Z::Dyn::preferred_layout(&z);
1477 let mut z = Z::Dyn::with_layout(z, layout);
1478
1479 let m = Z::Dyn::nrows(&z);
1480 let n = Z::Dyn::ncols(&z);
1481 let n = match layout {
1482 None | ReverseRows => Ord::min(m, n),
1483 Transpose | TransposeReverseRows => n,
1484 };
1485 if m == 0 || n == 0 {
1486 return;
1487 }
1488
1489 let strict = match diag {
1490 Diag::Skip => true,
1491 Diag::Include => false,
1492 };
1493
1494 unsafe {
1495 if Z::Dyn::is_contiguous(&z) {
1496 for j in 0..n {
1497 let (start, end) = match layout {
1498 None => (j + strict as usize, m),
1499 ReverseRows => (0, (m - (j + strict as usize))),
1500 Transpose => (0, (j + !strict as usize).min(m)),
1501 TransposeReverseRows => (m - ((j + !strict as usize).min(m)), m),
1502 };
1503
1504 let len = end - start;
1505 if start == end {
1506 continue;
1507 }
1508
1509 annotate_noalias_mat::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (start, j), len), start, end, j);
1510 }
1511 } else {
1512 for j in 0..n {
1513 let (start, end) = match layout {
1514 None => (j + strict as usize, m),
1515 ReverseRows => (0, (m - (j + strict as usize))),
1516 Transpose => (0, (j + !strict as usize).min(m)),
1517 TransposeReverseRows => (m - ((j + !strict as usize).min(m)), m),
1518 };
1519 if start == end {
1520 continue;
1521 }
1522
1523 for i in start..end {
1524 f(Z::Dyn::get_unchecked(&mut z, (i, j)))
1525 }
1526 }
1527 }
1528 }
1529}
1530
1531#[inline(always)]
1532fn for_each_col<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1533where
1534 Z::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize, Item = Z::Item, Slice = Z::Slice>,
1535{
1536 let layout = Z::preferred_layout(&z);
1537 let mut z = Z::with_layout(z, layout);
1538
1539 let m = Z::Dyn::nrows(&z);
1540 if m == 0 {
1541 return;
1542 }
1543
1544 unsafe {
1545 if Z::Dyn::is_contiguous(&z) {
1546 annotate_noalias_col::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m);
1547 } else {
1548 for i in 0..m {
1549 f(Z::Dyn::get_unchecked(&mut z, i))
1550 }
1551 }
1552 }
1553}
1554
1555#[inline(always)]
1556fn for_each_col_with_index<Idx, Z: MatIndex<LayoutTransform = VecLayoutTransform, Index = Idx>>(z: Z, mut f: impl FnMut(Idx, <Z as MatIndex>::Item))
1557where
1558 Z::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize, Item = Z::Item, Slice = Z::Slice>,
1559{
1560 let layout = Z::preferred_layout(&z);
1561 let mut z = Z::with_layout(z, layout);
1562
1563 let m = Z::Dyn::nrows(&z);
1564 if m == 0 {
1565 return;
1566 }
1567
1568 unsafe {
1569 match layout {
1570 VecLayoutTransform::None => {
1571 if Z::Dyn::is_contiguous(&z) {
1572 annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, false);
1573 } else {
1574 for i in 0..m {
1575 f(Z::from_dyn_idx(i), Z::Dyn::get_unchecked(&mut z, i))
1576 }
1577 }
1578 },
1579 VecLayoutTransform::Reverse => {
1580 if Z::Dyn::is_contiguous(&z) {
1581 annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, true);
1582 } else {
1583 for i in 0..m {
1584 f(Z::from_dyn_idx(m - i - 1), Z::Dyn::get_unchecked(&mut z, i))
1585 }
1586 }
1587 },
1588 }
1589 }
1590}
1591
1592#[inline(always)]
1593fn for_each_row_with_index<Idx, Z: MatIndex<LayoutTransform = VecLayoutTransform, Index = Idx>>(z: Z, mut f: impl FnMut(Idx, <Z as MatIndex>::Item))
1594where
1595 Z::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1596{
1597 let layout = Z::preferred_layout(&z);
1598 let mut z = Z::with_layout(z, layout);
1599
1600 let n = Z::Dyn::ncols(&z);
1601 if n == 0 {
1602 return;
1603 }
1604
1605 unsafe {
1606 match layout {
1607 VecLayoutTransform::None => {
1608 if Z::Dyn::is_contiguous(&z) {
1609 annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n, false);
1610 } else {
1611 for i in 0..n {
1612 f(Z::from_dyn_idx(i), Z::Dyn::get_unchecked(&mut z, i))
1613 }
1614 }
1615 },
1616 VecLayoutTransform::Reverse => {
1617 if Z::Dyn::is_contiguous(&z) {
1618 annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n, true);
1619 } else {
1620 for i in 0..n {
1621 f(Z::from_dyn_idx(n - i - 1), Z::Dyn::get_unchecked(&mut z, i))
1622 }
1623 }
1624 },
1625 }
1626 }
1627}
1628#[inline(always)]
1629fn for_each_row<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1630where
1631 Z::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1632{
1633 let layout = Z::preferred_layout(&z);
1634 let mut z = Z::with_layout(z, layout);
1635
1636 let n = Z::Dyn::ncols(&z);
1637 if n == 0 {
1638 return;
1639 }
1640
1641 unsafe {
1642 if Z::Dyn::is_contiguous(&z) {
1643 annotate_noalias_col::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n);
1644 } else {
1645 for j in 0..n {
1646 f(Z::Dyn::get_unchecked(&mut z, j))
1647 }
1648 }
1649 }
1650}
1651
1652impl<Rows: Shape, Cols: Shape, M: MatIndex<LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>>
1653 LastEq<Rows, Cols, M>
1654where
1655 M::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
1656{
1657 #[inline(always)]
1659 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1660 for_each_mat(self, f);
1661 }
1662
1663 #[inline(always)]
1666 pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1667 for_each_mat_with_index(self, f);
1668 }
1669
1670 #[inline(always)]
1675 pub fn for_each_triangular_lower_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1676 for_each_mat_triangular_lower_with_index(self, diag, f);
1677 }
1678
1679 #[inline(always)]
1684 pub fn for_each_triangular_upper_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1685 for_each_mat_triangular_upper_with_index(self, diag, f);
1686 }
1687
1688 #[inline(always)]
1692 pub fn for_each_triangular_lower(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1693 for_each_mat_triangular_lower(self, diag, false, f);
1694 }
1695
1696 #[inline(always)]
1700 pub fn for_each_triangular_upper(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1701 for_each_mat_triangular_lower(self, diag, true, f);
1702 }
1703
1704 #[inline(always)]
1706 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
1707 let (m, n) = (Self::nrows(&self), Self::ncols(&self));
1708 let mut f = f;
1709 let mut this = self;
1710 Mat::from_fn(
1711 m,
1712 n,
1713 #[inline(always)]
1714 |i, j| f(unsafe { Self::get_unchecked(&mut this, (i, j)) }),
1715 )
1716 }
1717
1718 #[inline(always)]
1720 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
1721 let (m, n) = (Self::nrows(&self), Self::ncols(&self));
1722 let mut f = f;
1723 let mut this = self;
1724
1725 Mat::from_fn(
1726 m,
1727 n,
1728 #[inline(always)]
1729 |i, j| f(i, j, unsafe { Self::get_unchecked(&mut this, (i, j)) }),
1730 )
1731 }
1732}
1733
1734impl<
1735 Rows: Shape,
1736 Cols: Shape,
1737 L: MatIndex<LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>,
1738 R: MatIndex<LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>,
1739> ZipEq<Rows, Cols, L, R>
1740where
1741 L::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
1742 R::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
1743{
1744 #[inline(always)]
1746 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1747 for_each_mat(self, f);
1748 }
1749
1750 #[inline(always)]
1753 pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1754 for_each_mat_with_index(self, f);
1755 }
1756
1757 #[inline(always)]
1762 pub fn for_each_triangular_lower_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1763 for_each_mat_triangular_lower_with_index(self, diag, f);
1764 }
1765
1766 #[inline(always)]
1771 pub fn for_each_triangular_upper_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1772 for_each_mat_triangular_upper_with_index(self, diag, f);
1773 }
1774
1775 #[inline(always)]
1779 pub fn for_each_triangular_lower(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1780 for_each_mat_triangular_lower(self, diag, false, f);
1781 }
1782
1783 #[inline(always)]
1787 pub fn for_each_triangular_upper(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1788 for_each_mat_triangular_lower(self, diag, true, f);
1789 }
1790
1791 #[inline(always)]
1793 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
1794 let (m, n) = (Self::nrows(&self), Self::ncols(&self));
1795 let mut f = f;
1796 let mut this = self;
1797 Mat::from_fn(
1798 m,
1799 n,
1800 #[inline(always)]
1801 |i, j| f(unsafe { Self::get_unchecked(&mut this, (i, j)) }),
1802 )
1803 }
1804
1805 #[inline(always)]
1807 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
1808 let (m, n) = (Self::nrows(&self), Self::ncols(&self));
1809 let mut f = f;
1810 let mut this = self;
1811
1812 Mat::from_fn(
1813 m,
1814 n,
1815 #[inline(always)]
1816 |i, j| f(i, j, unsafe { Self::get_unchecked(&mut this, (i, j)) }),
1817 )
1818 }
1819}
1820
1821impl<Rows: Shape, M: MatIndex<LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>> LastEq<Rows, (), M>
1822where
1823 M::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
1824{
1825 #[inline(always)]
1827 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1828 for_each_col(self, f);
1829 }
1830
1831 #[inline(always)]
1834 pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item)) {
1835 for_each_col_with_index(self, f);
1836 }
1837
1838 #[inline(always)]
1840 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
1841 let (m, _) = (Self::nrows(&self), Self::ncols(&self));
1842 let mut f = f;
1843 let mut this = self;
1844 Col::from_fn(
1845 m,
1846 #[inline(always)]
1847 |i| f(unsafe { Self::get_unchecked(&mut this, i) }),
1848 )
1849 }
1850
1851 #[inline(always)]
1853 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
1854 let (m, _) = (Self::nrows(&self), Self::ncols(&self));
1855 let mut f = f;
1856 let mut this = self;
1857
1858 Col::from_fn(
1859 m,
1860 #[inline(always)]
1861 |i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
1862 )
1863 }
1864}
1865
1866impl<
1867 Rows: Shape,
1868 L: MatIndex<LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>,
1869 R: MatIndex<LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>,
1870> ZipEq<Rows, (), L, R>
1871where
1872 L::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
1873 R::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
1874{
1875 #[inline(always)]
1877 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1878 for_each_col(self, f);
1879 }
1880
1881 #[inline(always)]
1884 pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item)) {
1885 for_each_col_with_index(self, f);
1886 }
1887
1888 #[inline(always)]
1890 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
1891 let (m, _) = (Self::nrows(&self), Self::ncols(&self));
1892 let mut f = f;
1893 let mut this = self;
1894 Col::from_fn(
1895 m,
1896 #[inline(always)]
1897 |i| f(unsafe { Self::get_unchecked(&mut this, i) }),
1898 )
1899 }
1900
1901 #[inline(always)]
1903 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
1904 let (m, _) = (Self::nrows(&self), Self::ncols(&self));
1905 let mut f = f;
1906 let mut this = self;
1907
1908 Col::from_fn(
1909 m,
1910 #[inline(always)]
1911 |i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
1912 )
1913 }
1914}
1915
1916impl<Cols: Shape, M: MatIndex<LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>> LastEq<(), Cols, M>
1917where
1918 M::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
1919{
1920 #[inline(always)]
1922 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1923 for_each_row(self, f);
1924 }
1925
1926 #[inline(always)]
1929 pub fn for_each_with_index(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item)) {
1930 for_each_row_with_index(self, f);
1931 }
1932
1933 #[inline(always)]
1935 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
1936 let (_, n) = (Self::nrows(&self), Self::ncols(&self));
1937 let mut f = f;
1938 let mut this = self;
1939 Row::from_fn(
1940 n,
1941 #[inline(always)]
1942 |i| f(unsafe { Self::get_unchecked(&mut this, i) }),
1943 )
1944 }
1945
1946 #[inline(always)]
1948 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
1949 let (_, n) = (Self::nrows(&self), Self::ncols(&self));
1950 let mut f = f;
1951 let mut this = self;
1952
1953 Row::from_fn(
1954 n,
1955 #[inline(always)]
1956 |i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
1957 )
1958 }
1959}
1960
1961impl<
1962 Cols: Shape,
1963 L: MatIndex<LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>,
1964 R: MatIndex<LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>,
1965> ZipEq<(), Cols, L, R>
1966where
1967 L::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
1968 R::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
1969{
1970 #[inline(always)]
1972 pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1973 for_each_row(self, f);
1974 }
1975
1976 #[inline(always)]
1979 pub fn for_each_with_index(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item)) {
1980 for_each_row_with_index(self, f);
1981 }
1982
1983 #[inline(always)]
1985 pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
1986 let (_, n) = (Self::nrows(&self), Self::ncols(&self));
1987 let mut f = f;
1988 let mut this = self;
1989 Row::from_fn(
1990 n,
1991 #[inline(always)]
1992 |i| f(unsafe { Self::get_unchecked(&mut this, i) }),
1993 )
1994 }
1995
1996 #[inline(always)]
1998 pub fn map_with_index<T>(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
1999 let (_, n) = (Self::nrows(&self), Self::ncols(&self));
2000 let mut f = f;
2001 let mut this = self;
2002
2003 Row::from_fn(
2004 n,
2005 #[inline(always)]
2006 |i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2007 )
2008 }
2009}