faer/linalg/
zip.rs

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/// matrix layout transformation. used for zipping optimizations
229#[derive(Copy, Clone)]
230pub enum MatLayoutTransform {
231	/// matrix is used as-is
232	None,
233	/// matrix rows are reversed
234	ReverseRows,
235	/// matrix is transposed
236	Transpose,
237	/// matrix is transposed, then rows are reversed
238	TransposeReverseRows,
239}
240
241/// vector layout transformation. used for zipping optimizations
242#[derive(Copy, Clone)]
243pub enum VecLayoutTransform {
244	/// vector is used as-is
245	None,
246	/// vector is reversed
247	Reverse,
248}
249
250/// type with a given matrix shape
251pub trait MatIndex {
252	/// type of rows
253	type Rows: Copy + Eq + core::fmt::Debug;
254	/// type of columns
255	type Cols: Copy + Eq + core::fmt::Debug;
256	/// returns the number of rows
257	fn nrows(this: &Self) -> Self::Rows;
258	/// returns the number of columns
259	fn ncols(this: &Self) -> Self::Cols;
260
261	/// indexing type
262	type Index: Copy;
263	/// layout transformation type
264	type LayoutTransform: Copy;
265
266	/// item produced by the zip views
267	type Item;
268
269	/// matrix type with type erased dimensions
270	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	/// returns slice at index of length `n_elems`
275	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	/// converts a type erased index back to its original representation
278	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index;
279
280	/// get the item at the given index, skipping bound checks
281	unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item;
282	/// get the item at the given slice position, skipping bound checks
283	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item;
284
285	/// checks if the zip matrices are contiguous
286	fn is_contiguous(this: &Self) -> bool;
287	/// computes the preferred iteration layout of the matrices
288	fn preferred_layout(this: &Self) -> Self::LayoutTransform;
289	/// applies the layout transformation to the matrices
290	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/// single matrix
317#[derive(Copy, Clone, Debug)]
318pub struct LastEq<Rows, Cols, Mat>(pub Mat, pub PhantomData<(Rows, Cols)>);
319
320/// single element
321#[derive(Copy, Clone, Debug)]
322pub struct Last<Mat>(pub Mat);
323
324/// zipped matrices
325#[derive(Copy, Clone, Debug)]
326pub struct ZipEq<Rows, Cols, Head, Tail>(pub Head, pub Tail, PhantomData<(Rows, Cols)>);
327
328/// zipped elements
329#[derive(Copy, Clone, Debug)]
330pub struct Zip<Head, Tail>(pub Head, pub Tail);
331
332/// single matrix view
333impl<
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	/// creates a zip matrix, after asserting that the dimensions match
341	#[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	/// creates a zip matrix, assuming that the dimensions match
349	#[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// TODO:
1063// - for_each_vec_with_index
1064
1065#[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	/// applies `f` to each element of `self`
1658	#[inline(always)]
1659	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1660		for_each_mat(self, f);
1661	}
1662
1663	/// applies `f` to each element of `self`, while passing the indices of the position of the
1664	/// current element
1665	#[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	/// applies `f` to each element of the lower triangular half of `self`, while passing the
1671	/// indices of the position of the current element
1672	///
1673	/// `diag` specifies whether the diagonal should be included or excluded
1674	#[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	/// applies `f` to each element of the upper triangular half of `self`, while passing the
1680	/// indices of the position of the current element
1681	///
1682	/// `diag` specifies whether the diagonal should be included or excluded
1683	#[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	/// applies `f` to each element of the lower triangular half of `self`
1689	///
1690	/// `diag` specifies whether the diagonal should be included or excluded
1691	#[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	/// applies `f` to each element of the upper triangular half of `self`
1697	///
1698	/// `diag` specifies whether the diagonal should be included or excluded
1699	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1705	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1719	#[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	/// applies `f` to each element of `self`
1745	#[inline(always)]
1746	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1747		for_each_mat(self, f);
1748	}
1749
1750	/// applies `f` to each element of `self`, while passing the indices of the position of the
1751	/// current element
1752	#[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	/// applies `f` to each element of the lower triangular half of `self`, while passing the
1758	/// indices of the position of the current element
1759	///
1760	/// `diag` specifies whether the diagonal should be included or excluded
1761	#[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	/// applies `f` to each element of the upper triangular half of `self`, while passing the
1767	/// indices of the position of the current element
1768	///
1769	/// `diag` specifies whether the diagonal should be included or excluded
1770	#[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	/// applies `f` to each element of the lower triangular half of `self`
1776	///
1777	/// `diag` specifies whether the diagonal should be included or excluded
1778	#[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	/// applies `f` to each element of the upper triangular half of `self`
1784	///
1785	/// `diag` specifies whether the diagonal should be included or excluded
1786	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1792	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1806	#[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	/// applies `f` to each element of `self`
1826	#[inline(always)]
1827	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1828		for_each_col(self, f);
1829	}
1830
1831	/// applies `f` to each element of `self`, while passing the indices of the position of the
1832	/// current element
1833	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1839	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1852	#[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	/// applies `f` to each element of `self`
1876	#[inline(always)]
1877	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1878		for_each_col(self, f);
1879	}
1880
1881	/// applies `f` to each element of `self`, while passing the indices of the position of the
1882	/// current element
1883	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1889	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1902	#[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	/// applies `f` to each element of `self`
1921	#[inline(always)]
1922	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1923		for_each_row(self, f);
1924	}
1925
1926	/// applies `f` to each element of `self`, while passing the indices of the position of the
1927	/// current element
1928	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1934	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1947	#[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	/// applies `f` to each element of `self`
1971	#[inline(always)]
1972	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1973		for_each_row(self, f);
1974	}
1975
1976	/// applies `f` to each element of `self`, while passing the indices of the position of the
1977	/// current element
1978	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1984	#[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	/// applies `f` to each element of `self` and collect its result into a new matrix
1997	#[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}