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, diag};
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, Len: Shape> IntoView for &'a mut diag::Diag<T, Len> {
70	type Target = diag::DiagMut<'a, T, Len, ContiguousFwd>;
71
72	#[inline]
73	fn into_view(self) -> Self::Target {
74		self.as_mut().column_vector_mut().try_as_col_major_mut().unwrap().as_diagonal_mut()
75	}
76}
77impl<'a, T, Len: Shape> IntoView for &'a diag::Diag<T, Len> {
78	type Target = diag::DiagRef<'a, T, Len, ContiguousFwd>;
79
80	#[inline]
81	fn into_view(self) -> Self::Target {
82		self.as_ref().column_vector().try_as_col_major().unwrap().as_diagonal()
83	}
84}
85
86impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for MatMut<'a, T, Rows, Cols, RStride, CStride> {
87	type Target = Self;
88
89	#[inline]
90	fn into_view(self) -> Self::Target {
91		self
92	}
93}
94impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for MatRef<'a, T, Rows, Cols, RStride, CStride> {
95	type Target = Self;
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 MatMut<'_, T, Rows, Cols, RStride, CStride> {
104	type Target = MatRef<'a, T, Rows, Cols, RStride, CStride>;
105
106	#[inline]
107	fn into_view(self) -> Self::Target {
108		self.rb()
109	}
110}
111impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a 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, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a mut MatMut<'_, T, Rows, Cols, RStride, CStride> {
121	type Target = MatMut<'a, T, Rows, Cols, RStride, CStride>;
122
123	#[inline]
124	fn into_view(self) -> Self::Target {
125		self.rb_mut()
126	}
127}
128impl<'a, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> IntoView for &'a mut MatRef<'_, T, Rows, Cols, RStride, CStride> {
129	type Target = MatRef<'a, T, Rows, Cols, RStride, CStride>;
130
131	#[inline]
132	fn into_view(self) -> Self::Target {
133		*self
134	}
135}
136
137impl<'a, T, Rows: Shape, RStride: Stride> IntoView for ColMut<'a, T, Rows, RStride> {
138	type Target = Self;
139
140	#[inline]
141	fn into_view(self) -> Self::Target {
142		self
143	}
144}
145impl<'a, T, Rows: Shape, RStride: Stride> IntoView for ColRef<'a, T, Rows, RStride> {
146	type Target = Self;
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 ColMut<'_, T, Rows, RStride> {
155	type Target = ColRef<'a, T, Rows, RStride>;
156
157	#[inline]
158	fn into_view(self) -> Self::Target {
159		self.rb()
160	}
161}
162impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a 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, Rows: Shape, RStride: Stride> IntoView for &'a mut ColMut<'_, T, Rows, RStride> {
172	type Target = ColMut<'a, T, Rows, RStride>;
173
174	#[inline]
175	fn into_view(self) -> Self::Target {
176		self.rb_mut()
177	}
178}
179impl<'a, T, Rows: Shape, RStride: Stride> IntoView for &'a mut ColRef<'_, T, Rows, RStride> {
180	type Target = ColRef<'a, T, Rows, RStride>;
181
182	#[inline]
183	fn into_view(self) -> Self::Target {
184		*self
185	}
186}
187
188impl<'a, T, Rows: Shape, DStride: Stride> IntoView for diag::DiagMut<'a, T, Rows, DStride> {
189	type Target = Self;
190
191	#[inline]
192	fn into_view(self) -> Self::Target {
193		self
194	}
195}
196impl<'a, T, Rows: Shape, DStride: Stride> IntoView for diag::DiagRef<'a, T, Rows, DStride> {
197	type Target = Self;
198
199	#[inline]
200	fn into_view(self) -> Self::Target {
201		self
202	}
203}
204
205impl<'a, T, Rows: Shape, DStride: Stride> IntoView for &'a diag::DiagMut<'_, T, Rows, DStride> {
206	type Target = diag::DiagRef<'a, T, Rows, DStride>;
207
208	#[inline]
209	fn into_view(self) -> Self::Target {
210		self.rb()
211	}
212}
213impl<'a, T, Rows: Shape, DStride: Stride> IntoView for &'a diag::DiagRef<'_, T, Rows, DStride> {
214	type Target = diag::DiagRef<'a, T, Rows, DStride>;
215
216	#[inline]
217	fn into_view(self) -> Self::Target {
218		*self
219	}
220}
221
222impl<'a, T, Rows: Shape, DStride: Stride> IntoView for &'a mut diag::DiagMut<'_, T, Rows, DStride> {
223	type Target = diag::DiagMut<'a, T, Rows, DStride>;
224
225	#[inline]
226	fn into_view(self) -> Self::Target {
227		self.rb_mut()
228	}
229}
230impl<'a, T, Rows: Shape, DStride: Stride> IntoView for &'a mut diag::DiagRef<'_, T, Rows, DStride> {
231	type Target = diag::DiagRef<'a, T, Rows, DStride>;
232
233	#[inline]
234	fn into_view(self) -> Self::Target {
235		*self
236	}
237}
238
239impl<'a, T, Cols: Shape, CStride: Stride> IntoView for RowMut<'a, T, Cols, CStride> {
240	type Target = Self;
241
242	#[inline]
243	fn into_view(self) -> Self::Target {
244		self
245	}
246}
247impl<'a, T, Cols: Shape, CStride: Stride> IntoView for RowRef<'a, T, Cols, CStride> {
248	type Target = Self;
249
250	#[inline]
251	fn into_view(self) -> Self::Target {
252		self
253	}
254}
255
256impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a RowMut<'_, T, Cols, CStride> {
257	type Target = RowRef<'a, T, Cols, CStride>;
258
259	#[inline]
260	fn into_view(self) -> Self::Target {
261		self.rb()
262	}
263}
264impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a RowRef<'_, T, Cols, CStride> {
265	type Target = RowRef<'a, T, Cols, CStride>;
266
267	#[inline]
268	fn into_view(self) -> Self::Target {
269		*self
270	}
271}
272
273impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a mut RowMut<'_, T, Cols, CStride> {
274	type Target = RowMut<'a, T, Cols, CStride>;
275
276	#[inline]
277	fn into_view(self) -> Self::Target {
278		self.rb_mut()
279	}
280}
281impl<'a, T, Cols: Shape, CStride: Stride> IntoView for &'a mut RowRef<'_, T, Cols, CStride> {
282	type Target = RowRef<'a, T, Cols, CStride>;
283
284	#[inline]
285	fn into_view(self) -> Self::Target {
286		*self
287	}
288}
289
290#[derive(Copy, Clone, Debug, PartialEq, Eq)]
291pub enum Diag {
292	Skip,
293	Include,
294}
295
296/// matrix layout transformation. used for zipping optimizations
297#[derive(Copy, Clone)]
298pub enum MatLayoutTransform {
299	/// matrix is used as-is
300	None,
301	/// matrix rows are reversed
302	ReverseRows,
303	/// matrix is transposed
304	Transpose,
305	/// matrix is transposed, then rows are reversed
306	TransposeReverseRows,
307}
308
309/// vector layout transformation. used for zipping optimizations
310#[derive(Copy, Clone)]
311pub enum VecLayoutTransform {
312	/// vector is used as-is
313	None,
314	/// vector is reversed
315	Reverse,
316}
317
318/// type with a given matrix shape
319pub trait MatIndex {
320	type Kind;
321
322	/// type of rows
323	type Rows: Copy + Eq + core::fmt::Debug;
324	/// type of columns
325	type Cols: Copy + Eq + core::fmt::Debug;
326	/// returns the number of rows
327	fn nrows(this: &Self) -> Self::Rows;
328	/// returns the number of columns
329	fn ncols(this: &Self) -> Self::Cols;
330
331	/// indexing type
332	type Index: Copy;
333	/// layout transformation type
334	type LayoutTransform: Copy;
335
336	/// item produced by the zip views
337	type Item;
338
339	/// matrix type with type erased dimensions
340	type Dyn: MatIndex<Kind = Self::Kind, Dyn = Self::Dyn, LayoutTransform = Self::LayoutTransform, Item = Self::Item, Slice = Self::Slice>;
341
342	type Slice: for<'a> SliceFamily<'a, Self::Item>;
343
344	/// returns slice at index of length `n_elems`
345	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice;
346
347	/// converts a type erased index back to its original representation
348	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index;
349
350	/// get the item at the given index, skipping bound checks
351	unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item;
352	/// get the item at the given slice position, skipping bound checks
353	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item;
354
355	/// checks if the zip matrices are contiguous
356	fn is_contiguous(this: &Self) -> bool;
357	/// computes the preferred iteration layout of the matrices
358	fn preferred_layout(this: &Self) -> Self::LayoutTransform;
359	/// applies the layout transformation to the matrices
360	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn;
361}
362
363pub trait SliceFamily<'a, T, Outlives = &'a Self> {
364	type Slice;
365}
366pub struct Slice<T>(pub T);
367pub struct SliceRef<'b, T>(pub &'b T);
368pub struct SliceMut<'b, T>(pub &'b mut T);
369
370impl<'a, T> SliceFamily<'a, T> for Slice<T> {
371	type Slice = &'a [T];
372}
373impl<'a, 'b, T> SliceFamily<'a, &'b T> for SliceRef<'b, T> {
374	type Slice = &'b [T];
375}
376impl<'a, 'b, T> SliceFamily<'a, &'b mut T> for SliceMut<'b, T> {
377	type Slice = &'b mut [T];
378}
379impl<'a, T, F: SliceFamily<'a, T>> SliceFamily<'a, Last<T>> for Last<F> {
380	type Slice = Last<F::Slice>;
381}
382impl<'a, T, U, F: SliceFamily<'a, T>, G: SliceFamily<'a, U>> SliceFamily<'a, Zip<T, U>> for Zip<F, G> {
383	type Slice = Zip<F::Slice, G::Slice>;
384}
385
386/// single matrix
387#[derive(Copy, Clone, Debug)]
388pub struct LastEq<Kind, Mat>(pub Mat, pub PhantomData<Kind>);
389
390/// single element
391#[derive(Copy, Clone, Debug)]
392pub struct Last<Mat>(pub Mat);
393
394/// zipped matrices
395#[derive(Copy, Clone, Debug)]
396pub struct ZipEq<Kind, Head, Tail>(pub Head, pub Tail, PhantomData<Kind>);
397
398/// zipped elements
399#[derive(Copy, Clone, Debug)]
400pub struct Zip<Head, Tail>(pub Head, pub Tail);
401
402/// single matrix view
403impl<
404	Kind,
405	Rows: Copy + Eq + core::fmt::Debug,
406	Cols: Copy + Eq + core::fmt::Debug,
407	Head: MatIndex<Kind = Kind, Rows = Rows, Cols = Cols>,
408	Tail: MatIndex<Kind = Kind, Rows = Rows, Cols = Cols>,
409> ZipEq<Kind, Head, Tail>
410{
411	/// creates a zip matrix, after asserting that the dimensions match
412	#[inline(always)]
413	#[track_caller]
414	pub fn new(head: Head, tail: Tail) -> Self {
415		assert!(all(Head::nrows(&head) == Tail::nrows(&tail), Head::ncols(&head) == Tail::ncols(&tail),));
416		Self(head, tail, PhantomData)
417	}
418
419	/// creates a zip matrix, assuming that the dimensions match
420	#[inline(always)]
421	#[track_caller]
422	pub fn new_unchecked(head: Head, tail: Tail) -> Self {
423		debug_assert!(all(Head::nrows(&head) == Tail::nrows(&tail), Head::ncols(&head) == Tail::ncols(&tail),));
424		Self(head, tail, PhantomData)
425	}
426}
427
428impl<Kind, Rows: Copy + Eq + core::fmt::Debug, Cols: Copy + Eq + core::fmt::Debug, Mat: MatIndex<Rows = Rows, Cols = Cols, Kind = Kind>> MatIndex
429	for LastEq<Kind, Mat>
430{
431	type Cols = Mat::Cols;
432	type Dyn = LastEq<<Mat::Dyn as MatIndex>::Kind, Mat::Dyn>;
433	type Index = Mat::Index;
434	type Item = Last<Mat::Item>;
435	type Kind = Mat::Kind;
436	type LayoutTransform = Mat::LayoutTransform;
437	type Rows = Mat::Rows;
438	type Slice = Last<Mat::Slice>;
439
440	#[inline(always)]
441	fn nrows(this: &Self) -> Self::Rows {
442		Mat::nrows(&this.0)
443	}
444
445	#[inline(always)]
446	fn ncols(this: &Self) -> Self::Cols {
447		Mat::ncols(&this.0)
448	}
449
450	#[inline]
451	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
452		Last(Mat::get_slice_unchecked(&mut this.0, idx, n_elems))
453	}
454
455	#[inline]
456	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
457		Mat::from_dyn_idx(idx)
458	}
459
460	#[inline]
461	unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item {
462		Last(Mat::get_unchecked(&mut this.0, index))
463	}
464
465	#[inline]
466	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
467		Last(Mat::next_unchecked(&mut slice.0))
468	}
469
470	#[inline]
471	fn is_contiguous(this: &Self) -> bool {
472		Mat::is_contiguous(&this.0)
473	}
474
475	#[inline]
476	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
477		Mat::preferred_layout(&this.0)
478	}
479
480	#[inline]
481	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
482		LastEq(Mat::with_layout(this.0, layout), PhantomData)
483	}
484}
485
486impl<
487	Kind,
488	Rows: Copy + Eq + core::fmt::Debug,
489	Cols: Copy + Eq + core::fmt::Debug,
490	L: MatIndex<Kind = Kind, Rows = Rows, Cols = Cols>,
491	R: MatIndex<Kind = Kind, Rows = Rows, Cols = Cols, Index = L::Index, LayoutTransform = L::LayoutTransform>,
492> MatIndex for ZipEq<Kind, L, R>
493where
494	R::Dyn: MatIndex<Rows = <L::Dyn as MatIndex>::Rows, Cols = <L::Dyn as MatIndex>::Cols, Index = <L::Dyn as MatIndex>::Index>,
495{
496	type Cols = L::Cols;
497	type Dyn = ZipEq<<L::Dyn as MatIndex>::Kind, L::Dyn, R::Dyn>;
498	type Index = L::Index;
499	type Item = Zip<L::Item, R::Item>;
500	type Kind = L::Kind;
501	type LayoutTransform = L::LayoutTransform;
502	type Rows = L::Rows;
503	type Slice = Zip<L::Slice, R::Slice>;
504
505	#[inline(always)]
506	fn nrows(this: &Self) -> Self::Rows {
507		L::nrows(&this.0)
508	}
509
510	#[inline(always)]
511	fn ncols(this: &Self) -> Self::Cols {
512		L::ncols(&this.0)
513	}
514
515	#[inline]
516	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
517		Zip(
518			L::get_slice_unchecked(&mut this.0, idx, n_elems),
519			R::get_slice_unchecked(&mut this.1, idx, n_elems),
520		)
521	}
522
523	#[inline]
524	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
525		L::from_dyn_idx(idx)
526	}
527
528	#[inline]
529	unsafe fn get_unchecked(this: &mut Self, index: Self::Index) -> Self::Item {
530		Zip(L::get_unchecked(&mut this.0, index), R::get_unchecked(&mut this.1, index))
531	}
532
533	#[inline]
534	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
535		Zip(L::next_unchecked(&mut slice.0), R::next_unchecked(&mut slice.1))
536	}
537
538	#[inline]
539	fn is_contiguous(this: &Self) -> bool {
540		L::is_contiguous(&this.0) && R::is_contiguous(&this.1)
541	}
542
543	#[inline]
544	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
545		L::preferred_layout(&this.0)
546	}
547
548	#[inline]
549	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
550		ZipEq(L::with_layout(this.0, layout), R::with_layout(this.1, layout), PhantomData)
551	}
552}
553
554impl<'b, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> MatIndex for MatMut<'b, T, Rows, Cols, RStride, CStride> {
555	type Cols = Cols;
556	type Dyn = MatMut<'b, T, usize, usize, isize, isize>;
557	type Index = (Idx<Rows>, Idx<Cols>);
558	type Item = &'b mut T;
559	type Kind = kind::Mat;
560	type LayoutTransform = MatLayoutTransform;
561	type Rows = Rows;
562	type Slice = SliceMut<'b, T>;
563
564	#[inline]
565	fn nrows(this: &Self) -> Self::Rows {
566		this.nrows()
567	}
568
569	#[inline]
570	fn ncols(this: &Self) -> Self::Cols {
571		this.ncols()
572	}
573
574	#[inline]
575	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
576		let ptr = this.ptr_inbounds_at_mut(idx.0, idx.1);
577		core::slice::from_raw_parts_mut(ptr, n_elems)
578	}
579
580	#[inline]
581	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
582		(Idx::<Rows>::new_unbound(idx.0), Idx::<Cols>::new_unbound(idx.1))
583	}
584
585	#[inline]
586	unsafe fn get_unchecked(this: &mut Self, (i, j): Self::Index) -> Self::Item {
587		let ptr = this.rb().ptr_inbounds_at_mut(i, j);
588		&mut *ptr
589	}
590
591	#[inline(always)]
592	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
593		let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
594		*slice = tail;
595		head
596	}
597
598	#[inline(always)]
599	fn is_contiguous(this: &Self) -> bool {
600		this.row_stride().element_stride() == 1
601	}
602
603	#[inline(always)]
604	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
605		let rs = this.row_stride().element_stride();
606		let cs = this.col_stride().element_stride();
607		let nrows = this.nrows().unbound();
608		let ncols = this.ncols().unbound();
609
610		if nrows > 1 && rs == 1 {
611			MatLayoutTransform::None
612		} else if nrows > 1 && rs == -1 {
613			MatLayoutTransform::ReverseRows
614		} else if ncols > 1 && cs == 1 {
615			MatLayoutTransform::Transpose
616		} else if ncols > 1 && cs == -1 {
617			MatLayoutTransform::TransposeReverseRows
618		} else {
619			MatLayoutTransform::None
620		}
621	}
622
623	#[inline(always)]
624	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
625		use MatLayoutTransform::*;
626		let this = this.as_dyn_mut().as_dyn_stride_mut();
627		match layout {
628			None => this,
629			ReverseRows => this.reverse_rows_mut(),
630			Transpose => this.transpose_mut(),
631			TransposeReverseRows => this.transpose_mut().reverse_rows_mut(),
632		}
633	}
634}
635
636impl<'b, T, Rows: Shape, Cols: Shape, RStride: Stride, CStride: Stride> MatIndex for MatRef<'b, T, Rows, Cols, RStride, CStride> {
637	type Cols = Cols;
638	type Dyn = MatRef<'b, T, usize, usize, isize, isize>;
639	type Index = (Idx<Rows>, Idx<Cols>);
640	type Item = &'b T;
641	type Kind = kind::Mat;
642	type LayoutTransform = MatLayoutTransform;
643	type Rows = Rows;
644	type Slice = SliceRef<'b, T>;
645
646	#[inline]
647	fn nrows(this: &Self) -> Self::Rows {
648		this.nrows()
649	}
650
651	#[inline]
652	fn ncols(this: &Self) -> Self::Cols {
653		this.ncols()
654	}
655
656	#[inline]
657	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
658		let ptr = this.ptr_inbounds_at(idx.0, idx.1);
659		core::slice::from_raw_parts(ptr, n_elems)
660	}
661
662	#[inline]
663	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
664		(Idx::<Rows>::new_unbound(idx.0), Idx::<Cols>::new_unbound(idx.1))
665	}
666
667	#[inline]
668	unsafe fn get_unchecked(this: &mut Self, (i, j): Self::Index) -> Self::Item {
669		let ptr = this.rb().ptr_inbounds_at(i, j);
670		&*ptr
671	}
672
673	#[inline(always)]
674	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
675		let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
676		*slice = tail;
677		head
678	}
679
680	#[inline(always)]
681	fn is_contiguous(this: &Self) -> bool {
682		this.row_stride().element_stride() == 1
683	}
684
685	#[inline(always)]
686	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
687		let rs = this.row_stride().element_stride();
688		let cs = this.col_stride().element_stride();
689		let nrows = this.nrows().unbound();
690		let ncols = this.ncols().unbound();
691
692		if nrows > 1 && rs == 1 {
693			MatLayoutTransform::None
694		} else if nrows > 1 && rs == -1 {
695			MatLayoutTransform::ReverseRows
696		} else if ncols > 1 && cs == 1 {
697			MatLayoutTransform::Transpose
698		} else if ncols > 1 && cs == -1 {
699			MatLayoutTransform::TransposeReverseRows
700		} else {
701			MatLayoutTransform::None
702		}
703	}
704
705	#[inline(always)]
706	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
707		use MatLayoutTransform::*;
708		let this = this.as_dyn().as_dyn_stride();
709		match layout {
710			None => this,
711			ReverseRows => this.reverse_rows(),
712			Transpose => this.transpose(),
713			TransposeReverseRows => this.transpose().reverse_rows(),
714		}
715	}
716}
717
718impl<'b, T, Len: Shape, Strd: Stride> MatIndex for ColMut<'b, T, Len, Strd> {
719	type Cols = ();
720	type Dyn = ColMut<'b, T, usize, isize>;
721	type Index = Idx<Len>;
722	type Item = &'b mut T;
723	type Kind = kind::Col;
724	type LayoutTransform = VecLayoutTransform;
725	type Rows = Len;
726	type Slice = SliceMut<'b, T>;
727
728	#[inline]
729	fn nrows(this: &Self) -> Self::Rows {
730		this.nrows()
731	}
732
733	#[inline]
734	fn ncols(_: &Self) -> Self::Cols {
735		()
736	}
737
738	#[inline]
739	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
740		let ptr = this.ptr_inbounds_at_mut(idx);
741		core::slice::from_raw_parts_mut(ptr, n_elems)
742	}
743
744	#[inline]
745	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
746		Idx::<Len>::new_unbound(idx)
747	}
748
749	#[inline]
750	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
751		let ptr = this.ptr_inbounds_at_mut(i);
752		&mut *ptr
753	}
754
755	#[inline(always)]
756	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
757		let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
758		*slice = tail;
759		head
760	}
761
762	#[inline(always)]
763	fn is_contiguous(this: &Self) -> bool {
764		this.row_stride().element_stride() == 1
765	}
766
767	#[inline(always)]
768	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
769		let strd = this.row_stride().element_stride();
770		let len = this.nrows().unbound();
771
772		if len > 1 && strd == 1 {
773			VecLayoutTransform::None
774		} else if len > 1 && strd == -1 {
775			VecLayoutTransform::Reverse
776		} else {
777			VecLayoutTransform::None
778		}
779	}
780
781	#[inline(always)]
782	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
783		use VecLayoutTransform::*;
784		let this = this.as_dyn_rows_mut().as_dyn_stride_mut();
785		match layout {
786			None => this,
787			Reverse => this.reverse_rows_mut(),
788		}
789	}
790}
791
792impl<'b, T, Len: Shape, Strd: Stride> MatIndex for diag::DiagMut<'b, T, Len, Strd> {
793	type Cols = Len;
794	type Dyn = diag::DiagMut<'b, T, usize, isize>;
795	type Index = Idx<Len>;
796	type Item = &'b mut T;
797	type Kind = kind::Diag;
798	type LayoutTransform = VecLayoutTransform;
799	type Rows = Len;
800	type Slice = SliceMut<'b, T>;
801
802	#[inline]
803	fn nrows(this: &Self) -> Self::Rows {
804		this.dim()
805	}
806
807	#[inline]
808	fn ncols(this: &Self) -> Self::Cols {
809		this.dim()
810	}
811
812	#[inline]
813	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
814		let ptr = this.rb_mut().column_vector_mut().ptr_inbounds_at_mut(idx);
815		core::slice::from_raw_parts_mut(ptr, n_elems)
816	}
817
818	#[inline]
819	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
820		Idx::<Len>::new_unbound(idx)
821	}
822
823	#[inline]
824	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
825		let ptr = this.rb_mut().column_vector_mut().ptr_inbounds_at_mut(i);
826		&mut *ptr
827	}
828
829	#[inline(always)]
830	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
831		let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
832		*slice = tail;
833		head
834	}
835
836	#[inline(always)]
837	fn is_contiguous(this: &Self) -> bool {
838		this.stride().element_stride() == 1
839	}
840
841	#[inline(always)]
842	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
843		let strd = this.stride().element_stride();
844		let len = this.dim().unbound();
845
846		if len > 1 && strd == 1 {
847			VecLayoutTransform::None
848		} else if len > 1 && strd == -1 {
849			VecLayoutTransform::Reverse
850		} else {
851			VecLayoutTransform::None
852		}
853	}
854
855	#[inline(always)]
856	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
857		use VecLayoutTransform::*;
858		let this = this.as_dyn_mut().as_dyn_stride_mut();
859		match layout {
860			None => this,
861			Reverse => this.column_vector_mut().reverse_rows_mut().as_diagonal_mut(),
862		}
863	}
864}
865
866impl<'b, T, Len: Shape, Strd: Stride> MatIndex for RowMut<'b, T, Len, Strd> {
867	type Cols = Len;
868	type Dyn = RowMut<'b, T, usize, isize>;
869	type Index = Idx<Len>;
870	type Item = &'b mut T;
871	type Kind = kind::Row;
872	type LayoutTransform = VecLayoutTransform;
873	type Rows = ();
874	type Slice = SliceMut<'b, T>;
875
876	#[inline]
877	fn nrows(_: &Self) -> Self::Rows {
878		()
879	}
880
881	#[inline]
882	fn ncols(this: &Self) -> Self::Cols {
883		this.ncols()
884	}
885
886	#[inline]
887	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
888		let ptr = this.ptr_inbounds_at_mut(idx);
889		core::slice::from_raw_parts_mut(ptr, n_elems)
890	}
891
892	#[inline]
893	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
894		Idx::<Len>::new_unbound(idx)
895	}
896
897	#[inline]
898	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
899		let ptr = this.rb().ptr_inbounds_at_mut(i);
900		&mut *ptr
901	}
902
903	#[inline(always)]
904	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
905		let (head, tail) = core::mem::take(slice).split_first_mut().unwrap_unchecked();
906		*slice = tail;
907		head
908	}
909
910	#[inline(always)]
911	fn is_contiguous(this: &Self) -> bool {
912		this.col_stride().element_stride() == 1
913	}
914
915	#[inline(always)]
916	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
917		let strd = this.col_stride().element_stride();
918		let len = this.ncols().unbound();
919
920		if len > 1 && strd == 1 {
921			VecLayoutTransform::None
922		} else if len > 1 && strd == -1 {
923			VecLayoutTransform::Reverse
924		} else {
925			VecLayoutTransform::None
926		}
927	}
928
929	#[inline(always)]
930	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
931		use VecLayoutTransform::*;
932		let this = this.as_dyn_cols_mut().as_dyn_stride_mut();
933		match layout {
934			None => this,
935			Reverse => this.reverse_cols_mut(),
936		}
937	}
938}
939
940impl<'b, T, Len: Shape, Strd: Stride> MatIndex for ColRef<'b, T, Len, Strd> {
941	type Cols = ();
942	type Dyn = ColRef<'b, T, usize, isize>;
943	type Index = Idx<Len>;
944	type Item = &'b T;
945	type Kind = kind::Col;
946	type LayoutTransform = VecLayoutTransform;
947	type Rows = Len;
948	type Slice = SliceRef<'b, T>;
949
950	#[inline]
951	fn nrows(this: &Self) -> Self::Rows {
952		this.nrows()
953	}
954
955	#[inline]
956	fn ncols(_: &Self) -> Self::Cols {
957		()
958	}
959
960	#[inline]
961	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
962		let ptr = this.ptr_inbounds_at(idx);
963		core::slice::from_raw_parts(ptr, n_elems)
964	}
965
966	#[inline]
967	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
968		Idx::<Len>::new_unbound(idx)
969	}
970
971	#[inline]
972	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
973		let ptr = this.rb().ptr_inbounds_at(i);
974		&*ptr
975	}
976
977	#[inline(always)]
978	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
979		let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
980		*slice = tail;
981		head
982	}
983
984	#[inline(always)]
985	fn is_contiguous(this: &Self) -> bool {
986		this.row_stride().element_stride() == 1
987	}
988
989	#[inline(always)]
990	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
991		let strd = this.row_stride().element_stride();
992		let len = this.nrows().unbound();
993
994		if len > 1 && strd == 1 {
995			VecLayoutTransform::None
996		} else if len > 1 && strd == -1 {
997			VecLayoutTransform::Reverse
998		} else {
999			VecLayoutTransform::None
1000		}
1001	}
1002
1003	#[inline(always)]
1004	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
1005		use VecLayoutTransform::*;
1006		let this = this.as_dyn_rows().as_dyn_stride();
1007		match layout {
1008			None => this,
1009			Reverse => this.reverse_rows(),
1010		}
1011	}
1012}
1013
1014impl<'b, T, Len: Shape, Strd: Stride> MatIndex for diag::DiagRef<'b, T, Len, Strd> {
1015	type Cols = Len;
1016	type Dyn = diag::DiagRef<'b, T, usize, isize>;
1017	type Index = Idx<Len>;
1018	type Item = &'b T;
1019	type Kind = kind::Diag;
1020	type LayoutTransform = VecLayoutTransform;
1021	type Rows = Len;
1022	type Slice = SliceRef<'b, T>;
1023
1024	#[inline]
1025	fn nrows(this: &Self) -> Self::Rows {
1026		this.dim()
1027	}
1028
1029	#[inline]
1030	fn ncols(this: &Self) -> Self::Cols {
1031		this.dim()
1032	}
1033
1034	#[inline]
1035	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
1036		let ptr = this.column_vector().ptr_inbounds_at(idx);
1037		core::slice::from_raw_parts(ptr, n_elems)
1038	}
1039
1040	#[inline]
1041	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
1042		Idx::<Len>::new_unbound(idx)
1043	}
1044
1045	#[inline]
1046	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
1047		let ptr = this.column_vector().ptr_inbounds_at(i);
1048		&*ptr
1049	}
1050
1051	#[inline(always)]
1052	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
1053		let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
1054		*slice = tail;
1055		head
1056	}
1057
1058	#[inline(always)]
1059	fn is_contiguous(this: &Self) -> bool {
1060		this.stride().element_stride() == 1
1061	}
1062
1063	#[inline(always)]
1064	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
1065		let strd = this.stride().element_stride();
1066		let len = this.dim().unbound();
1067
1068		if len > 1 && strd == 1 {
1069			VecLayoutTransform::None
1070		} else if len > 1 && strd == -1 {
1071			VecLayoutTransform::Reverse
1072		} else {
1073			VecLayoutTransform::None
1074		}
1075	}
1076
1077	#[inline(always)]
1078	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
1079		use VecLayoutTransform::*;
1080		let this = this.as_dyn().as_dyn_stride();
1081		match layout {
1082			None => this,
1083			Reverse => this.column_vector().reverse_rows().as_diagonal(),
1084		}
1085	}
1086}
1087
1088impl<'b, T, Len: Shape, Strd: Stride> MatIndex for RowRef<'b, T, Len, Strd> {
1089	type Cols = Len;
1090	type Dyn = RowRef<'b, T, usize, isize>;
1091	type Index = Idx<Len>;
1092	type Item = &'b T;
1093	type Kind = kind::Row;
1094	type LayoutTransform = VecLayoutTransform;
1095	type Rows = ();
1096	type Slice = SliceRef<'b, T>;
1097
1098	#[inline]
1099	fn nrows(_: &Self) -> Self::Rows {
1100		()
1101	}
1102
1103	#[inline]
1104	fn ncols(this: &Self) -> Self::Cols {
1105		this.ncols()
1106	}
1107
1108	#[inline]
1109	unsafe fn get_slice_unchecked<'a>(this: &'a mut Self, idx: Self::Index, n_elems: usize) -> <Self::Slice as SliceFamily<'a, Self::Item>>::Slice {
1110		let ptr = this.ptr_inbounds_at(idx);
1111		core::slice::from_raw_parts(ptr, n_elems)
1112	}
1113
1114	#[inline]
1115	unsafe fn from_dyn_idx(idx: <Self::Dyn as MatIndex>::Index) -> Self::Index {
1116		Idx::<Len>::new_unbound(idx)
1117	}
1118
1119	#[inline]
1120	unsafe fn get_unchecked(this: &mut Self, i: Self::Index) -> Self::Item {
1121		let ptr = this.rb().ptr_inbounds_at(i);
1122		&*ptr
1123	}
1124
1125	#[inline(always)]
1126	unsafe fn next_unchecked<'a>(slice: &mut <Self::Slice as SliceFamily<'a, Self::Item>>::Slice) -> Self::Item {
1127		let (head, tail) = core::mem::take(slice).split_first().unwrap_unchecked();
1128		*slice = tail;
1129		head
1130	}
1131
1132	#[inline(always)]
1133	fn is_contiguous(this: &Self) -> bool {
1134		this.col_stride().element_stride() == 1
1135	}
1136
1137	#[inline(always)]
1138	fn preferred_layout(this: &Self) -> Self::LayoutTransform {
1139		let strd = this.col_stride().element_stride();
1140		let len = this.ncols().unbound();
1141
1142		if len > 1 && strd == 1 {
1143			VecLayoutTransform::None
1144		} else if len > 1 && strd == -1 {
1145			VecLayoutTransform::Reverse
1146		} else {
1147			VecLayoutTransform::None
1148		}
1149	}
1150
1151	#[inline(always)]
1152	fn with_layout(this: Self, layout: Self::LayoutTransform) -> Self::Dyn {
1153		use VecLayoutTransform::*;
1154		let this = this.as_dyn_cols().as_dyn_stride();
1155		match layout {
1156			None => this,
1157			Reverse => this.reverse_cols(),
1158		}
1159	}
1160}
1161
1162#[inline(always)]
1163fn annotate_noalias_mat<Z: MatIndex>(
1164	f: &mut impl FnMut(<Z as MatIndex>::Item),
1165	mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
1166	i_begin: usize,
1167	i_end: usize,
1168	_j: usize,
1169) {
1170	for _ in i_begin..i_end {
1171		unsafe { f(Z::next_unchecked(&mut slice)) };
1172	}
1173}
1174
1175#[inline(always)]
1176fn annotate_noalias_mat_with_index<Z: MatIndex<Index = (RowIdx, ColIdx)>, RowIdx, ColIdx>(
1177	f: &mut impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1178	mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
1179	i_begin: usize,
1180	i_end: usize,
1181	j: usize,
1182	transpose: bool,
1183	reverse_rows: bool,
1184) where
1185	Z::Dyn: MatIndex<Index = (usize, usize)>,
1186{
1187	if !transpose {
1188		if !reverse_rows {
1189			for i in i_begin..i_end {
1190				unsafe {
1191					let (ii, jj) = Z::from_dyn_idx((i, j));
1192					f(ii, jj, Z::next_unchecked(&mut slice))
1193				};
1194			}
1195		} else {
1196			for i in i_begin..i_end {
1197				unsafe {
1198					let (ii, jj) = Z::from_dyn_idx((i_begin + (i_end - i - 1), j));
1199					f(ii, jj, Z::next_unchecked(&mut slice))
1200				};
1201			}
1202		}
1203	} else {
1204		if !reverse_rows {
1205			for i in i_begin..i_end {
1206				unsafe {
1207					let (ii, jj) = Z::from_dyn_idx((j, i));
1208					f(ii, jj, Z::next_unchecked(&mut slice))
1209				};
1210			}
1211		} else {
1212			for i in i_begin..i_end {
1213				unsafe {
1214					let (ii, jj) = Z::from_dyn_idx((j, i_begin + (i_end - i - 1)));
1215					f(ii, jj, Z::next_unchecked(&mut slice))
1216				};
1217			}
1218		}
1219	}
1220}
1221
1222#[inline(always)]
1223fn annotate_noalias_col<Z: MatIndex>(
1224	f: &mut impl FnMut(<Z as MatIndex>::Item),
1225	mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
1226	i_begin: usize,
1227	i_end: usize,
1228) {
1229	for _ in i_begin..i_end {
1230		unsafe { f(Z::next_unchecked(&mut slice)) };
1231	}
1232}
1233
1234#[inline(always)]
1235fn annotate_noalias_col_with_index<Z: MatIndex<Index = Idx>, Idx>(
1236	f: &mut impl FnMut(Idx, <Z as MatIndex>::Item),
1237	mut slice: <Z::Slice as SliceFamily<'_, Z::Item>>::Slice,
1238	i_begin: usize,
1239	i_end: usize,
1240	reverse: bool,
1241) where
1242	Z::Dyn: MatIndex<Item = Z::Item, Index = usize>,
1243{
1244	if !reverse {
1245		for i in i_begin..i_end {
1246			unsafe {
1247				let ii = Z::from_dyn_idx(i);
1248				f(ii, Z::next_unchecked(&mut slice))
1249			};
1250		}
1251	} else {
1252		for i in i_begin..i_end {
1253			unsafe {
1254				let ii = Z::from_dyn_idx(i_begin + (i_end - i - 1));
1255				f(ii, Z::next_unchecked(&mut slice))
1256			};
1257		}
1258	}
1259}
1260
1261#[inline(always)]
1262fn for_each_mat<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1263where
1264	Z::Dyn: MatIndex<Item = Z::Item, Slice = Z::Slice, Rows = usize, Cols = usize, Index = (usize, usize)>,
1265{
1266	let layout = Z::preferred_layout(&z);
1267	let mut z = Z::with_layout(z, layout);
1268
1269	let m = Z::Dyn::nrows(&z);
1270	let n = Z::Dyn::ncols(&z);
1271	if m == 0 || n == 0 {
1272		return;
1273	}
1274
1275	unsafe {
1276		if Z::Dyn::is_contiguous(&z) {
1277			for j in 0..n {
1278				annotate_noalias_mat::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j);
1279			}
1280		} else {
1281			for j in 0..n {
1282				for i in 0..m {
1283					f(Z::Dyn::get_unchecked(&mut z, (i, j)))
1284				}
1285			}
1286		}
1287	}
1288}
1289
1290// TODO:
1291// - for_each_vec_with_index
1292
1293#[inline(always)]
1294fn for_each_mat_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1295	z: Z,
1296	mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1297) where
1298	Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Slice = Z::Slice, Item = Z::Item>,
1299{
1300	let layout = Z::preferred_layout(&z);
1301	let mut z = Z::with_layout(z, layout);
1302
1303	let m = Z::Dyn::nrows(&z);
1304	let n = Z::Dyn::ncols(&z);
1305	if m == 0 || n == 0 {
1306		return;
1307	}
1308
1309	match layout {
1310		MatLayoutTransform::None => unsafe {
1311			if Z::Dyn::is_contiguous(&z) {
1312				for j in 0..n {
1313					annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, false, false);
1314				}
1315			} else {
1316				for j in 0..n {
1317					for i in 0..m {
1318						let (ii, jj) = Z::from_dyn_idx((i, j));
1319						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1320					}
1321				}
1322			}
1323		},
1324		MatLayoutTransform::ReverseRows => unsafe {
1325			if Z::Dyn::is_contiguous(&z) {
1326				for j in 0..n {
1327					annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, false, true);
1328				}
1329			} else {
1330				for j in 0..n {
1331					for i in 0..m {
1332						let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1333						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1334					}
1335				}
1336			}
1337		},
1338		MatLayoutTransform::Transpose => unsafe {
1339			if Z::Dyn::is_contiguous(&z) {
1340				for j in 0..n {
1341					annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, true, false);
1342				}
1343			} else {
1344				for j in 0..n {
1345					for i in 0..m {
1346						let (ii, jj) = Z::from_dyn_idx((j, i));
1347						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1348					}
1349				}
1350			}
1351		},
1352		MatLayoutTransform::TransposeReverseRows => unsafe {
1353			if Z::Dyn::is_contiguous(&z) {
1354				for j in 0..n {
1355					annotate_noalias_mat_with_index::<Z, _, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (0, j), m), 0, m, j, true, true);
1356				}
1357			} else {
1358				for j in 0..n {
1359					for i in 0..m {
1360						let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1361						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1362					}
1363				}
1364			}
1365		},
1366	}
1367}
1368
1369#[inline(always)]
1370fn for_each_mat_triangular_lower_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1371	z: Z,
1372	diag: Diag,
1373	mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1374) where
1375	Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Item = Z::Item, Slice = Z::Slice>,
1376{
1377	let layout = Z::preferred_layout(&z);
1378	let mut z = Z::with_layout(z, layout);
1379
1380	let m = Z::Dyn::nrows(&z);
1381	let n = Z::Dyn::ncols(&z);
1382	let strict = match diag {
1383		Diag::Skip => true,
1384		Diag::Include => false,
1385	};
1386	let strict = strict as usize;
1387
1388	if m == 0 || n == 0 {
1389		return;
1390	}
1391
1392	match layout {
1393		MatLayoutTransform::None => unsafe {
1394			if Z::Dyn::is_contiguous(&z) {
1395				for j in 0..n {
1396					let start = j + strict;
1397					let end = m;
1398					if start == end {
1399						continue;
1400					}
1401					annotate_noalias_mat_with_index::<Z, _, _>(
1402						&mut f,
1403						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1404						start,
1405						end,
1406						j,
1407						false,
1408						false,
1409					);
1410				}
1411			} else {
1412				for j in 0..n {
1413					let start = j + strict;
1414					let end = m;
1415					if start == end {
1416						continue;
1417					}
1418					for i in start..end {
1419						let (ii, jj) = Z::from_dyn_idx((i, j));
1420						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1421					}
1422				}
1423			}
1424		},
1425		MatLayoutTransform::ReverseRows => unsafe {
1426			if Z::Dyn::is_contiguous(&z) {
1427				for j in 0..Ord::min(m, n) {
1428					let start = 0;
1429					let end = m - j - strict;
1430					if start == end {
1431						continue;
1432					}
1433					annotate_noalias_mat_with_index::<Z, _, _>(
1434						&mut f,
1435						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1436						j + strict + start,
1437						j + strict + end,
1438						j,
1439						false,
1440						true,
1441					);
1442				}
1443			} else {
1444				for j in 0..Ord::min(m, n) {
1445					let start = 0;
1446					let end = m - j - strict;
1447					if start == end {
1448						continue;
1449					}
1450					for i in start..end {
1451						let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1452						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1453					}
1454				}
1455			}
1456		},
1457		MatLayoutTransform::Transpose => unsafe {
1458			if Z::Dyn::is_contiguous(&z) {
1459				for j in 0..n {
1460					let start = 0;
1461					let end = Ord::min(m, j + (1 - strict));
1462					if start == end {
1463						continue;
1464					}
1465					annotate_noalias_mat_with_index::<Z, _, _>(
1466						&mut f,
1467						Z::Dyn::get_slice_unchecked(&mut z, (0, j), end - start),
1468						start,
1469						end,
1470						j,
1471						true,
1472						false,
1473					);
1474				}
1475			} else {
1476				for j in 0..n {
1477					let start = 0;
1478					let end = Ord::min(m, j + (1 - strict));
1479					if start == end {
1480						continue;
1481					}
1482					for i in start..end {
1483						let (ii, jj) = Z::from_dyn_idx((j, i));
1484						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1485					}
1486				}
1487			}
1488		},
1489		MatLayoutTransform::TransposeReverseRows => unsafe {
1490			if Z::Dyn::is_contiguous(&z) {
1491				for j in 0..n {
1492					let start = m - Ord::min(j + (1 - strict) as usize, m);
1493					let end = m;
1494					if start == end {
1495						continue;
1496					}
1497					annotate_noalias_mat_with_index::<Z, _, _>(
1498						&mut f,
1499						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1500						0,
1501						end - start,
1502						j,
1503						true,
1504						true,
1505					);
1506				}
1507			} else {
1508				for j in 0..n {
1509					let start = m - Ord::min(j + (1 - strict) as usize, m);
1510					let end = m;
1511					if start == end {
1512						continue;
1513					}
1514					for i in start..end {
1515						let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1516						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1517					}
1518				}
1519			}
1520		},
1521	}
1522}
1523
1524#[inline(always)]
1525fn for_each_mat_triangular_upper_with_index<RowIdx, ColIdx, Z: MatIndex<Index = (RowIdx, ColIdx), LayoutTransform = MatLayoutTransform>>(
1526	z: Z,
1527	diag: Diag,
1528	mut f: impl FnMut(RowIdx, ColIdx, <Z as MatIndex>::Item),
1529) where
1530	Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize), Item = Z::Item, Slice = Z::Slice>,
1531{
1532	let layout = Z::preferred_layout(&z);
1533	let mut z = Z::with_layout(z, layout);
1534
1535	let m = Z::Dyn::nrows(&z);
1536	let n = Z::Dyn::ncols(&z);
1537	let strict = match diag {
1538		Diag::Skip => true,
1539		Diag::Include => false,
1540	};
1541	let strict = strict as usize;
1542
1543	if m == 0 || n == 0 {
1544		return;
1545	}
1546
1547	match layout {
1548		MatLayoutTransform::None => unsafe {
1549			if Z::Dyn::is_contiguous(&z) {
1550				for j in 0..n {
1551					let start = 0;
1552					let end = Ord::min(m, j + (1 - strict));
1553					if start == end {
1554						continue;
1555					}
1556
1557					annotate_noalias_mat_with_index::<Z, _, _>(
1558						&mut f,
1559						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1560						start,
1561						end,
1562						j,
1563						false,
1564						false,
1565					);
1566				}
1567			} else {
1568				for j in 0..n {
1569					let start = 0;
1570					let end = Ord::min(m, j + (1 - strict));
1571					if start == end {
1572						continue;
1573					}
1574					for i in start..end {
1575						let (ii, jj) = Z::from_dyn_idx((i, j));
1576						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1577					}
1578				}
1579			}
1580		},
1581		MatLayoutTransform::ReverseRows => unsafe {
1582			if Z::Dyn::is_contiguous(&z) {
1583				for j in 0..Ord::min(m, n) {
1584					let start = m - Ord::min(j + (1 - strict) as usize, m);
1585					let end = m;
1586					if start == end {
1587						continue;
1588					}
1589					annotate_noalias_mat_with_index::<Z, _, _>(
1590						&mut f,
1591						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1592						0,
1593						end - start,
1594						j,
1595						false,
1596						true,
1597					);
1598				}
1599			} else {
1600				for j in 0..Ord::min(m, n) {
1601					let start = m - Ord::min(j + (1 - strict) as usize, m);
1602					let end = m;
1603					if start == end {
1604						continue;
1605					}
1606					for i in start..end {
1607						let (ii, jj) = Z::from_dyn_idx((m - i - 1, j));
1608						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1609					}
1610				}
1611			}
1612		},
1613		MatLayoutTransform::Transpose => unsafe {
1614			if Z::Dyn::is_contiguous(&z) {
1615				for j in 0..n {
1616					let start = j + strict;
1617					let end = m;
1618					if start == end {
1619						continue;
1620					}
1621					annotate_noalias_mat_with_index::<Z, _, _>(
1622						&mut f,
1623						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1624						start,
1625						end,
1626						j,
1627						true,
1628						false,
1629					);
1630				}
1631			} else {
1632				for j in 0..n {
1633					let start = j + strict;
1634					let end = m;
1635					if start == end {
1636						continue;
1637					}
1638					for i in start..end {
1639						let (ii, jj) = Z::from_dyn_idx((j, i));
1640						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1641					}
1642				}
1643			}
1644		},
1645		MatLayoutTransform::TransposeReverseRows => unsafe {
1646			if Z::Dyn::is_contiguous(&z) {
1647				for j in 0..n {
1648					let start = 0;
1649					let end = m - j - strict;
1650					if start == end {
1651						continue;
1652					}
1653					annotate_noalias_mat_with_index::<Z, _, _>(
1654						&mut f,
1655						Z::Dyn::get_slice_unchecked(&mut z, (start, j), end - start),
1656						j + strict,
1657						j + strict + end - start,
1658						j,
1659						true,
1660						true,
1661					);
1662				}
1663			} else {
1664				for j in 0..n {
1665					let start = 0;
1666					let end = m - j - strict;
1667					if start == end {
1668						continue;
1669					}
1670					for i in start..end {
1671						let (ii, jj) = Z::from_dyn_idx((j, m - i - 1));
1672						f(ii, jj, Z::Dyn::get_unchecked(&mut z, (i, j)))
1673					}
1674				}
1675			}
1676		},
1677	}
1678}
1679
1680#[inline(always)]
1681fn for_each_mat_triangular_lower<Z: MatIndex<LayoutTransform = MatLayoutTransform>>(
1682	z: Z,
1683	diag: Diag,
1684	transpose: bool,
1685	mut f: impl FnMut(<Z as MatIndex>::Item),
1686) where
1687	Z::Dyn: MatIndex<
1688			LayoutTransform = MatLayoutTransform,
1689			Item = Z::Item,
1690			Slice = Z::Slice,
1691			Rows = usize,
1692			Cols = usize,
1693			Index = (usize, usize),
1694			Dyn = Z::Dyn,
1695		>,
1696{
1697	use MatLayoutTransform::*;
1698
1699	let z = if transpose {
1700		Z::with_layout(z, MatLayoutTransform::Transpose)
1701	} else {
1702		Z::with_layout(z, MatLayoutTransform::None)
1703	};
1704	let layout = Z::Dyn::preferred_layout(&z);
1705	let mut z = Z::Dyn::with_layout(z, layout);
1706
1707	let m = Z::Dyn::nrows(&z);
1708	let n = Z::Dyn::ncols(&z);
1709	let n = match layout {
1710		None | ReverseRows => Ord::min(m, n),
1711		Transpose | TransposeReverseRows => n,
1712	};
1713	if m == 0 || n == 0 {
1714		return;
1715	}
1716
1717	let strict = match diag {
1718		Diag::Skip => true,
1719		Diag::Include => false,
1720	};
1721
1722	unsafe {
1723		if Z::Dyn::is_contiguous(&z) {
1724			for j in 0..n {
1725				let (start, end) = match layout {
1726					None => (j + strict as usize, m),
1727					ReverseRows => (0, (m - (j + strict as usize))),
1728					Transpose => (0, (j + !strict as usize).min(m)),
1729					TransposeReverseRows => (m - ((j + !strict as usize).min(m)), m),
1730				};
1731
1732				let len = end - start;
1733				if start == end {
1734					continue;
1735				}
1736
1737				annotate_noalias_mat::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, (start, j), len), start, end, j);
1738			}
1739		} else {
1740			for j in 0..n {
1741				let (start, end) = match layout {
1742					None => (j + strict as usize, m),
1743					ReverseRows => (0, (m - (j + strict as usize))),
1744					Transpose => (0, (j + !strict as usize).min(m)),
1745					TransposeReverseRows => (m - ((j + !strict as usize).min(m)), m),
1746				};
1747				if start == end {
1748					continue;
1749				}
1750
1751				for i in start..end {
1752					f(Z::Dyn::get_unchecked(&mut z, (i, j)))
1753				}
1754			}
1755		}
1756	}
1757}
1758
1759#[inline(always)]
1760fn for_each_diag<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1761where
1762	Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1763{
1764	let layout = Z::preferred_layout(&z);
1765	let mut z = Z::with_layout(z, layout);
1766
1767	let m = Z::Dyn::nrows(&z);
1768	if m == 0 {
1769		return;
1770	}
1771
1772	unsafe {
1773		if Z::Dyn::is_contiguous(&z) {
1774			annotate_noalias_col::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m);
1775		} else {
1776			for i in 0..m {
1777				f(Z::Dyn::get_unchecked(&mut z, i))
1778			}
1779		}
1780	}
1781}
1782
1783#[inline(always)]
1784fn for_each_diag_with_index<Idx, Z: MatIndex<LayoutTransform = VecLayoutTransform, Index = Idx>>(z: Z, mut f: impl FnMut(Idx, <Z as MatIndex>::Item))
1785where
1786	Z::Dyn: MatIndex<Rows = usize, Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1787{
1788	let layout = Z::preferred_layout(&z);
1789	let mut z = Z::with_layout(z, layout);
1790
1791	let m = Z::Dyn::nrows(&z);
1792	if m == 0 {
1793		return;
1794	}
1795
1796	unsafe {
1797		match layout {
1798			VecLayoutTransform::None => {
1799				if Z::Dyn::is_contiguous(&z) {
1800					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, false);
1801				} else {
1802					for i in 0..m {
1803						f(Z::from_dyn_idx(i), Z::Dyn::get_unchecked(&mut z, i))
1804					}
1805				}
1806			},
1807			VecLayoutTransform::Reverse => {
1808				if Z::Dyn::is_contiguous(&z) {
1809					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, true);
1810				} else {
1811					for i in 0..m {
1812						f(Z::from_dyn_idx(m - i - 1), Z::Dyn::get_unchecked(&mut z, i))
1813					}
1814				}
1815			},
1816		}
1817	}
1818}
1819
1820#[inline(always)]
1821fn for_each_col<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1822where
1823	Z::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize, Item = Z::Item, Slice = Z::Slice>,
1824{
1825	let layout = Z::preferred_layout(&z);
1826	let mut z = Z::with_layout(z, layout);
1827
1828	let m = Z::Dyn::nrows(&z);
1829	if m == 0 {
1830		return;
1831	}
1832
1833	unsafe {
1834		if Z::Dyn::is_contiguous(&z) {
1835			annotate_noalias_col::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m);
1836		} else {
1837			for i in 0..m {
1838				f(Z::Dyn::get_unchecked(&mut z, i))
1839			}
1840		}
1841	}
1842}
1843
1844#[inline(always)]
1845fn for_each_col_with_index<Idx, Z: MatIndex<LayoutTransform = VecLayoutTransform, Index = Idx>>(z: Z, mut f: impl FnMut(Idx, <Z as MatIndex>::Item))
1846where
1847	Z::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize, Item = Z::Item, Slice = Z::Slice>,
1848{
1849	let layout = Z::preferred_layout(&z);
1850	let mut z = Z::with_layout(z, layout);
1851
1852	let m = Z::Dyn::nrows(&z);
1853	if m == 0 {
1854		return;
1855	}
1856
1857	unsafe {
1858		match layout {
1859			VecLayoutTransform::None => {
1860				if Z::Dyn::is_contiguous(&z) {
1861					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, false);
1862				} else {
1863					for i in 0..m {
1864						f(Z::from_dyn_idx(i), Z::Dyn::get_unchecked(&mut z, i))
1865					}
1866				}
1867			},
1868			VecLayoutTransform::Reverse => {
1869				if Z::Dyn::is_contiguous(&z) {
1870					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, m), 0, m, true);
1871				} else {
1872					for i in 0..m {
1873						f(Z::from_dyn_idx(m - i - 1), Z::Dyn::get_unchecked(&mut z, i))
1874					}
1875				}
1876			},
1877		}
1878	}
1879}
1880
1881#[inline(always)]
1882fn for_each_row_with_index<Idx, Z: MatIndex<LayoutTransform = VecLayoutTransform, Index = Idx>>(z: Z, mut f: impl FnMut(Idx, <Z as MatIndex>::Item))
1883where
1884	Z::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1885{
1886	let layout = Z::preferred_layout(&z);
1887	let mut z = Z::with_layout(z, layout);
1888
1889	let n = Z::Dyn::ncols(&z);
1890	if n == 0 {
1891		return;
1892	}
1893
1894	unsafe {
1895		match layout {
1896			VecLayoutTransform::None => {
1897				if Z::Dyn::is_contiguous(&z) {
1898					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n, false);
1899				} else {
1900					for i in 0..n {
1901						f(Z::from_dyn_idx(i), Z::Dyn::get_unchecked(&mut z, i))
1902					}
1903				}
1904			},
1905			VecLayoutTransform::Reverse => {
1906				if Z::Dyn::is_contiguous(&z) {
1907					annotate_noalias_col_with_index::<Z, _>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n, true);
1908				} else {
1909					for i in 0..n {
1910						f(Z::from_dyn_idx(n - i - 1), Z::Dyn::get_unchecked(&mut z, i))
1911					}
1912				}
1913			},
1914		}
1915	}
1916}
1917#[inline(always)]
1918fn for_each_row<Z: MatIndex>(z: Z, mut f: impl FnMut(<Z as MatIndex>::Item))
1919where
1920	Z::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize, Item = Z::Item, Slice = Z::Slice>,
1921{
1922	let layout = Z::preferred_layout(&z);
1923	let mut z = Z::with_layout(z, layout);
1924
1925	let n = Z::Dyn::ncols(&z);
1926	if n == 0 {
1927		return;
1928	}
1929
1930	unsafe {
1931		if Z::Dyn::is_contiguous(&z) {
1932			annotate_noalias_col::<Z::Dyn>(&mut f, Z::Dyn::get_slice_unchecked(&mut z, 0, n), 0, n);
1933		} else {
1934			for j in 0..n {
1935				f(Z::Dyn::get_unchecked(&mut z, j))
1936			}
1937		}
1938	}
1939}
1940
1941impl<
1942	Rows: Shape,
1943	Cols: Shape,
1944	M: MatIndex<Kind = kind::Mat, LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>,
1945> LastEq<kind::Mat, M>
1946where
1947	M::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
1948{
1949	/// applies `f` to each element of `self`
1950	#[inline(always)]
1951	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
1952		for_each_mat(self, f);
1953	}
1954
1955	/// applies `f` to each element of `self`, while passing the indices of the position of the
1956	/// current element
1957	#[inline(always)]
1958	pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1959		for_each_mat_with_index(self, f);
1960	}
1961
1962	/// applies `f` to each element of the lower triangular half of `self`, while passing the
1963	/// indices of the position of the current element
1964	///
1965	/// `diag` specifies whether the diagonal should be included or excluded
1966	#[inline(always)]
1967	pub fn for_each_triangular_lower_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1968		for_each_mat_triangular_lower_with_index(self, diag, f);
1969	}
1970
1971	/// applies `f` to each element of the upper triangular half of `self`, while passing the
1972	/// indices of the position of the current element
1973	///
1974	/// `diag` specifies whether the diagonal should be included or excluded
1975	#[inline(always)]
1976	pub fn for_each_triangular_upper_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
1977		for_each_mat_triangular_upper_with_index(self, diag, f);
1978	}
1979
1980	/// applies `f` to each element of the lower triangular half of `self`
1981	///
1982	/// `diag` specifies whether the diagonal should be included or excluded
1983	#[inline(always)]
1984	pub fn for_each_triangular_lower(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1985		for_each_mat_triangular_lower(self, diag, false, f);
1986	}
1987
1988	/// applies `f` to each element of the upper triangular half of `self`
1989	///
1990	/// `diag` specifies whether the diagonal should be included or excluded
1991	#[inline(always)]
1992	pub fn for_each_triangular_upper(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
1993		for_each_mat_triangular_lower(self, diag, true, f);
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<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
1999		let (m, n) = (Self::nrows(&self), Self::ncols(&self));
2000		let mut f = f;
2001		let mut this = self;
2002		Mat::from_fn(
2003			m,
2004			n,
2005			#[inline(always)]
2006			|i, j| f(unsafe { Self::get_unchecked(&mut this, (i, j)) }),
2007		)
2008	}
2009
2010	/// applies `f` to each element of `self` and collect its result into a new matrix
2011	#[inline(always)]
2012	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
2013		let (m, n) = (Self::nrows(&self), Self::ncols(&self));
2014		let mut f = f;
2015		let mut this = self;
2016
2017		Mat::from_fn(
2018			m,
2019			n,
2020			#[inline(always)]
2021			|i, j| f(i, j, unsafe { Self::get_unchecked(&mut this, (i, j)) }),
2022		)
2023	}
2024}
2025
2026impl<
2027	Rows: Shape,
2028	Cols: Shape,
2029	L: MatIndex<Kind = kind::Mat, LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>,
2030	R: MatIndex<Kind = kind::Mat, LayoutTransform = MatLayoutTransform, Rows = Rows, Cols = Cols, Index = (Idx<Rows>, Idx<Cols>)>,
2031> ZipEq<kind::Mat, L, R>
2032where
2033	L::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
2034	R::Dyn: MatIndex<Rows = usize, Cols = usize, Index = (usize, usize)>,
2035{
2036	/// applies `f` to each element of `self`
2037	#[inline(always)]
2038	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2039		for_each_mat(self, f);
2040	}
2041
2042	/// applies `f` to each element of `self`, while passing the indices of the position of the
2043	/// current element
2044	#[inline(always)]
2045	pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
2046		for_each_mat_with_index(self, f);
2047	}
2048
2049	/// applies `f` to each element of the lower triangular half of `self`, while passing the
2050	/// indices of the position of the current element
2051	///
2052	/// `diag` specifies whether the diagonal should be included or excluded
2053	#[inline(always)]
2054	pub fn for_each_triangular_lower_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
2055		for_each_mat_triangular_lower_with_index(self, diag, f);
2056	}
2057
2058	/// applies `f` to each element of the upper triangular half of `self`, while passing the
2059	/// indices of the position of the current element
2060	///
2061	/// `diag` specifies whether the diagonal should be included or excluded
2062	#[inline(always)]
2063	pub fn for_each_triangular_upper_with_index(self, diag: Diag, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item)) {
2064		for_each_mat_triangular_upper_with_index(self, diag, f);
2065	}
2066
2067	/// applies `f` to each element of the lower triangular half of `self`
2068	///
2069	/// `diag` specifies whether the diagonal should be included or excluded
2070	#[inline(always)]
2071	pub fn for_each_triangular_lower(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
2072		for_each_mat_triangular_lower(self, diag, false, f);
2073	}
2074
2075	/// applies `f` to each element of the upper triangular half of `self`
2076	///
2077	/// `diag` specifies whether the diagonal should be included or excluded
2078	#[inline(always)]
2079	pub fn for_each_triangular_upper(self, diag: Diag, f: impl FnMut(<Self as MatIndex>::Item)) {
2080		for_each_mat_triangular_lower(self, diag, true, f);
2081	}
2082
2083	/// applies `f` to each element of `self` and collect its result into a new matrix
2084	#[inline(always)]
2085	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
2086		let (m, n) = (Self::nrows(&self), Self::ncols(&self));
2087		let mut f = f;
2088		let mut this = self;
2089		Mat::from_fn(
2090			m,
2091			n,
2092			#[inline(always)]
2093			|i, j| f(unsafe { Self::get_unchecked(&mut this, (i, j)) }),
2094		)
2095	}
2096
2097	/// applies `f` to each element of `self` and collect its result into a new matrix
2098	#[inline(always)]
2099	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Mat<T, Rows, Cols> {
2100		let (m, n) = (Self::nrows(&self), Self::ncols(&self));
2101		let mut f = f;
2102		let mut this = self;
2103
2104		Mat::from_fn(
2105			m,
2106			n,
2107			#[inline(always)]
2108			|i, j| f(i, j, unsafe { Self::get_unchecked(&mut this, (i, j)) }),
2109		)
2110	}
2111}
2112
2113impl<Rows: Shape, M: MatIndex<Kind = kind::Col, LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>> LastEq<kind::Col, M>
2114where
2115	M::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
2116{
2117	/// applies `f` to each element of `self`
2118	#[inline(always)]
2119	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2120		for_each_col(self, f);
2121	}
2122
2123	/// applies `f` to each element of `self`, while passing the indices of the position of the
2124	/// current element
2125	#[inline(always)]
2126	pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item)) {
2127		for_each_col_with_index(self, f);
2128	}
2129
2130	/// applies `f` to each element of `self` and collect its result into a new matrix
2131	#[inline(always)]
2132	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
2133		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2134		let mut f = f;
2135		let mut this = self;
2136		Col::from_fn(
2137			m,
2138			#[inline(always)]
2139			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2140		)
2141	}
2142
2143	/// applies `f` to each element of `self` and collect its result into a new matrix
2144	#[inline(always)]
2145	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
2146		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2147		let mut f = f;
2148		let mut this = self;
2149
2150		Col::from_fn(
2151			m,
2152			#[inline(always)]
2153			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2154		)
2155	}
2156}
2157
2158impl<
2159	Rows: Shape,
2160	L: MatIndex<Kind = kind::Col, LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>,
2161	R: MatIndex<Kind = kind::Col, LayoutTransform = VecLayoutTransform, Rows = Rows, Cols = (), Index = Idx<Rows>>,
2162> ZipEq<kind::Col, L, R>
2163where
2164	L::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
2165	R::Dyn: MatIndex<Rows = usize, Cols = (), Index = usize>,
2166{
2167	/// applies `f` to each element of `self`
2168	#[inline(always)]
2169	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2170		for_each_col(self, f);
2171	}
2172
2173	/// applies `f` to each element of `self`, while passing the indices of the position of the
2174	/// current element
2175	#[inline(always)]
2176	pub fn for_each_with_index(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item)) {
2177		for_each_col_with_index(self, f);
2178	}
2179
2180	/// applies `f` to each element of `self` and collect its result into a new matrix
2181	#[inline(always)]
2182	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
2183		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2184		let mut f = f;
2185		let mut this = self;
2186		Col::from_fn(
2187			m,
2188			#[inline(always)]
2189			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2190		)
2191	}
2192
2193	/// applies `f` to each element of `self` and collect its result into a new matrix
2194	#[inline(always)]
2195	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Rows>, <Self as MatIndex>::Item) -> T) -> Col<T, Rows> {
2196		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2197		let mut f = f;
2198		let mut this = self;
2199
2200		Col::from_fn(
2201			m,
2202			#[inline(always)]
2203			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2204		)
2205	}
2206}
2207
2208impl<Dim: Shape, M: MatIndex<Kind = kind::Diag, LayoutTransform = VecLayoutTransform, Rows = Dim, Cols = Dim, Index = Idx<Dim>>> LastEq<kind::Diag, M>
2209where
2210	M::Dyn: MatIndex<Rows = usize, Cols = usize, Index = usize>,
2211{
2212	/// applies `f` to each element of `self`
2213	#[inline(always)]
2214	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2215		for_each_diag(self, f);
2216	}
2217
2218	/// applies `f` to each element of `self`, while passing the indices of the position of the
2219	/// current element
2220	#[inline(always)]
2221	pub fn for_each_with_index(self, f: impl FnMut(Idx<Dim>, <Self as MatIndex>::Item)) {
2222		for_each_diag_with_index(self, f);
2223	}
2224
2225	/// applies `f` to each element of `self` and collect its result into a new matrix
2226	#[inline(always)]
2227	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> diag::Diag<T, Dim> {
2228		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2229		let mut f = f;
2230		let mut this = self;
2231		Col::from_fn(
2232			m,
2233			#[inline(always)]
2234			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2235		)
2236		.into_diagonal()
2237	}
2238
2239	/// applies `f` to each element of `self` and collect its result into a new matrix
2240	#[inline(always)]
2241	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Dim>, <Self as MatIndex>::Item) -> T) -> diag::Diag<T, Dim> {
2242		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2243		let mut f = f;
2244		let mut this = self;
2245
2246		Col::from_fn(
2247			m,
2248			#[inline(always)]
2249			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2250		)
2251		.into_diagonal()
2252	}
2253}
2254
2255impl<
2256	Dim: Shape,
2257	L: MatIndex<Kind = kind::Diag, LayoutTransform = VecLayoutTransform, Rows = Dim, Cols = Dim, Index = Idx<Dim>>,
2258	R: MatIndex<Kind = kind::Diag, LayoutTransform = VecLayoutTransform, Rows = Dim, Cols = Dim, Index = Idx<Dim>>,
2259> ZipEq<kind::Diag, L, R>
2260where
2261	L::Dyn: MatIndex<Rows = usize, Cols = usize, Index = usize>,
2262	R::Dyn: MatIndex<Rows = usize, Cols = usize, Index = usize>,
2263{
2264	/// applies `f` to each element of `self`
2265	#[inline(always)]
2266	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2267		for_each_diag(self, f);
2268	}
2269
2270	/// applies `f` to each element of `self`, while passing the indices of the position of the
2271	/// current element
2272	#[inline(always)]
2273	pub fn for_each_with_index(self, f: impl FnMut(Idx<Dim>, <Self as MatIndex>::Item)) {
2274		for_each_diag_with_index(self, f);
2275	}
2276
2277	/// applies `f` to each element of `self` and collect its result into a new matrix
2278	#[inline(always)]
2279	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> diag::Diag<T, Dim> {
2280		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2281		let mut f = f;
2282		let mut this = self;
2283		Col::from_fn(
2284			m,
2285			#[inline(always)]
2286			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2287		)
2288		.into_diagonal()
2289	}
2290
2291	/// applies `f` to each element of `self` and collect its result into a new matrix
2292	#[inline(always)]
2293	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Dim>, <Self as MatIndex>::Item) -> T) -> diag::Diag<T, Dim> {
2294		let (m, _) = (Self::nrows(&self), Self::ncols(&self));
2295		let mut f = f;
2296		let mut this = self;
2297
2298		Col::from_fn(
2299			m,
2300			#[inline(always)]
2301			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2302		)
2303		.into_diagonal()
2304	}
2305}
2306
2307impl<Cols: Shape, M: MatIndex<Kind = kind::Row, LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>> LastEq<kind::Row, M>
2308where
2309	M::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
2310{
2311	/// applies `f` to each element of `self`
2312	#[inline(always)]
2313	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2314		for_each_row(self, f);
2315	}
2316
2317	/// applies `f` to each element of `self`, while passing the indices of the position of the
2318	/// current element
2319	#[inline(always)]
2320	pub fn for_each_with_index(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item)) {
2321		for_each_row_with_index(self, f);
2322	}
2323
2324	/// applies `f` to each element of `self` and collect its result into a new matrix
2325	#[inline(always)]
2326	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
2327		let (_, n) = (Self::nrows(&self), Self::ncols(&self));
2328		let mut f = f;
2329		let mut this = self;
2330		Row::from_fn(
2331			n,
2332			#[inline(always)]
2333			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2334		)
2335	}
2336
2337	/// applies `f` to each element of `self` and collect its result into a new matrix
2338	#[inline(always)]
2339	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
2340		let (_, n) = (Self::nrows(&self), Self::ncols(&self));
2341		let mut f = f;
2342		let mut this = self;
2343
2344		Row::from_fn(
2345			n,
2346			#[inline(always)]
2347			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2348		)
2349	}
2350}
2351
2352impl<
2353	Cols: Shape,
2354	L: MatIndex<Kind = kind::Row, LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>,
2355	R: MatIndex<Kind = kind::Row, LayoutTransform = VecLayoutTransform, Rows = (), Cols = Cols, Index = Idx<Cols>>,
2356> ZipEq<kind::Row, L, R>
2357where
2358	L::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
2359	R::Dyn: MatIndex<Rows = (), Cols = usize, Index = usize>,
2360{
2361	/// applies `f` to each element of `self`
2362	#[inline(always)]
2363	pub fn for_each(self, f: impl FnMut(<Self as MatIndex>::Item)) {
2364		for_each_row(self, f);
2365	}
2366
2367	/// applies `f` to each element of `self`, while passing the indices of the position of the
2368	/// current element
2369	#[inline(always)]
2370	pub fn for_each_with_index(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item)) {
2371		for_each_row_with_index(self, f);
2372	}
2373
2374	/// applies `f` to each element of `self` and collect its result into a new matrix
2375	#[inline(always)]
2376	pub fn map<T>(self, f: impl FnMut(<Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
2377		let (_, n) = (Self::nrows(&self), Self::ncols(&self));
2378		let mut f = f;
2379		let mut this = self;
2380		Row::from_fn(
2381			n,
2382			#[inline(always)]
2383			|i| f(unsafe { Self::get_unchecked(&mut this, i) }),
2384		)
2385	}
2386
2387	/// applies `f` to each element of `self` and collect its result into a new matrix
2388	#[inline(always)]
2389	pub fn map_with_index<T>(self, f: impl FnMut(Idx<Cols>, <Self as MatIndex>::Item) -> T) -> Row<T, Cols> {
2390		let (_, n) = (Self::nrows(&self), Self::ncols(&self));
2391		let mut f = f;
2392		let mut this = self;
2393
2394		Row::from_fn(
2395			n,
2396			#[inline(always)]
2397			|i| f(i, unsafe { Self::get_unchecked(&mut this, i) }),
2398		)
2399	}
2400}
2401
2402pub mod kind {
2403	pub struct Col;
2404	pub struct Row;
2405	pub struct Mat;
2406	pub struct Diag;
2407}