faer/sparse/csr/
mod.rs

1use super::*;
2use crate::internal_prelude::*;
3use crate::{Idx, MaybeIdx, assert, debug_assert};
4use core::ops::Range;
5use core::{fmt, iter};
6
7/// implementation of symbolic representation
8pub mod symbolic {
9	/// generic `SymbolicSparseRowMat` wrapper
10	pub mod generic {
11		use core::fmt::Debug;
12		use reborrow::*;
13
14		/// generic `SymbolicSparseRowMat` wrapper
15		#[derive(Copy, Clone)]
16		#[repr(transparent)]
17		pub struct SymbolicSparseRowMat<Inner>(pub Inner);
18
19		impl<Inner: Debug> Debug for SymbolicSparseRowMat<Inner> {
20			#[inline(always)]
21			fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
22				self.0.fmt(f)
23			}
24		}
25
26		impl<Inner> SymbolicSparseRowMat<Inner> {
27			/// wrap by reference
28			#[inline(always)]
29			pub fn from_inner_ref(inner: &Inner) -> &Self {
30				unsafe { &*(inner as *const Inner as *const Self) }
31			}
32
33			/// wrap by mutable reference
34			#[inline(always)]
35			pub fn from_inner_mut(inner: &mut Inner) -> &mut Self {
36				unsafe { &mut *(inner as *mut Inner as *mut Self) }
37			}
38		}
39
40		impl<Inner> core::ops::Deref for SymbolicSparseRowMat<Inner> {
41			type Target = Inner;
42
43			#[inline(always)]
44			fn deref(&self) -> &Self::Target {
45				&self.0
46			}
47		}
48
49		impl<Inner> core::ops::DerefMut for SymbolicSparseRowMat<Inner> {
50			#[inline(always)]
51			fn deref_mut(&mut self) -> &mut Self::Target {
52				&mut self.0
53			}
54		}
55
56		impl<'short, Inner: Reborrow<'short>> Reborrow<'short> for SymbolicSparseRowMat<Inner> {
57			type Target = SymbolicSparseRowMat<Inner::Target>;
58
59			#[inline(always)]
60			fn rb(&'short self) -> Self::Target {
61				SymbolicSparseRowMat(self.0.rb())
62			}
63		}
64
65		impl<'short, Inner: ReborrowMut<'short>> ReborrowMut<'short> for SymbolicSparseRowMat<Inner> {
66			type Target = SymbolicSparseRowMat<Inner::Target>;
67
68			#[inline(always)]
69			fn rb_mut(&'short mut self) -> Self::Target {
70				SymbolicSparseRowMat(self.0.rb_mut())
71			}
72		}
73
74		impl<Inner: IntoConst> IntoConst for SymbolicSparseRowMat<Inner> {
75			type Target = SymbolicSparseRowMat<Inner::Target>;
76
77			#[inline(always)]
78			fn into_const(self) -> Self::Target {
79				SymbolicSparseRowMat(self.0.into_const())
80			}
81		}
82	}
83
84	/// see [`super::SymbolicSparseRowMatRef`]
85	pub struct Ref<'a, I, Rows = usize, Cols = usize> {
86		pub(crate) nrows: Rows,
87		pub(crate) ncols: Cols,
88		pub(crate) row_ptr: &'a [I],
89		pub(crate) row_nnz: Option<&'a [I]>,
90		pub(crate) col_idx: &'a [I],
91	}
92
93	/// see [`super::SymbolicSparseRowMat`]
94	#[derive(Clone)]
95	pub struct Own<I, Rows = usize, Cols = usize> {
96		pub(crate) nrows: Rows,
97		pub(crate) ncols: Cols,
98		pub(crate) row_ptr: alloc::vec::Vec<I>,
99		pub(crate) row_nnz: Option<alloc::vec::Vec<I>>,
100		pub(crate) col_idx: alloc::vec::Vec<I>,
101	}
102}
103
104/// implementation of numeric representation
105pub mod numeric {
106	/// generic `SparseRowMat` wrapper
107	pub mod generic {
108		use core::fmt::Debug;
109		use reborrow::*;
110
111		/// generic `SparseRowMat` wrapper
112		#[derive(Copy, Clone)]
113		#[repr(transparent)]
114		pub struct SparseRowMat<Inner>(pub Inner);
115
116		impl<Inner: Debug> Debug for SparseRowMat<Inner> {
117			#[inline(always)]
118			fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
119				self.0.fmt(f)
120			}
121		}
122
123		impl<Inner> SparseRowMat<Inner> {
124			/// wrap by reference
125			#[inline(always)]
126			pub fn from_inner_ref(inner: &Inner) -> &Self {
127				unsafe { &*(inner as *const Inner as *const Self) }
128			}
129
130			/// wrap by mutable reference
131			#[inline(always)]
132			pub fn from_inner_mut(inner: &mut Inner) -> &mut Self {
133				unsafe { &mut *(inner as *mut Inner as *mut Self) }
134			}
135		}
136
137		impl<'short, Inner: Reborrow<'short>> Reborrow<'short> for SparseRowMat<Inner> {
138			type Target = SparseRowMat<Inner::Target>;
139
140			#[inline(always)]
141			fn rb(&'short self) -> Self::Target {
142				SparseRowMat(self.0.rb())
143			}
144		}
145
146		impl<'short, Inner: ReborrowMut<'short>> ReborrowMut<'short> for SparseRowMat<Inner> {
147			type Target = SparseRowMat<Inner::Target>;
148
149			#[inline(always)]
150			fn rb_mut(&'short mut self) -> Self::Target {
151				SparseRowMat(self.0.rb_mut())
152			}
153		}
154
155		impl<Inner: IntoConst> IntoConst for SparseRowMat<Inner> {
156			type Target = SparseRowMat<Inner::Target>;
157
158			#[inline(always)]
159			fn into_const(self) -> Self::Target {
160				SparseRowMat(self.0.into_const())
161			}
162		}
163	}
164
165	/// see [`super::SparseRowMatRef`]
166	pub struct Ref<'a, I, T, Rows = usize, Cols = usize> {
167		pub(crate) symbolic: super::SymbolicSparseRowMatRef<'a, I, Rows, Cols>,
168		pub(crate) val: &'a [T],
169	}
170
171	/// see [`super::SparseRowMatMut`]
172	pub struct Mut<'a, I, T, Rows = usize, Cols = usize> {
173		pub(crate) symbolic: super::SymbolicSparseRowMatRef<'a, I, Rows, Cols>,
174		pub(crate) val: &'a mut [T],
175	}
176
177	/// see [`super::SparseRowMat`]
178	#[derive(Clone)]
179	pub struct Own<I, T, Rows = usize, Cols = usize> {
180		pub(crate) symbolic: super::SymbolicSparseRowMat<I, Rows, Cols>,
181		pub(crate) val: alloc::vec::Vec<T>,
182	}
183}
184
185/// symbolic view structure of sparse matrix in row format, either compressed or uncompressed
186///
187/// # invariants
188/// - `nrows <= I::Signed::MAX` (always checked)
189/// - `ncols <= I::Signed::MAX` (always checked)
190/// - `row_ptrs` has length `nrows + 1` (always checked)
191/// - `row_ptrs` is increasing
192/// - `row_ptrs[0]..row_ptrs[nrows]` is a valid range in row_indices (always checked, assuming
193///   increasing)
194/// - if `nnz_per_row` is `none`, elements of `col_indices[row_ptrs[i]..row_ptrs[i + 1]]` are less
195///   than `ncols`
196///
197/// - `nnz_per_row[i] <= row_ptrs[i+1] - row_ptrs[i]`
198/// - if `nnz_per_row` is `some(_)`, elements of `col_indices[row_ptrs[i]..][..nnz_per_row[i]]` are
199///   less than `ncols`
200///
201/// # soft invariants
202/// - within each row, column indices are sorted in increasing order
203///
204/// # note
205/// some algorithms allow working with matrices containing unsorted row indices per column
206///
207/// passing such a matrix to an algorithm that does not explicitly permit this is unspecified
208/// (though not undefined) behavior
209pub type SymbolicSparseRowMatRef<'a, I, Rows = usize, Cols = usize> = symbolic::generic::SymbolicSparseRowMat<symbolic::Ref<'a, I, Rows, Cols>>;
210
211/// owning symbolic structure of sparse matrix in row format, either compressed or
212/// uncompressed
213///
214/// see [`SymbolicSparseRowMatRef`]
215pub type SymbolicSparseRowMat<I, Rows = usize, Cols = usize> = symbolic::generic::SymbolicSparseRowMat<symbolic::Own<I, Rows, Cols>>;
216
217/// view over sparse row major matrix
218///
219/// see [`SymbolicSparseRowMatRef`]
220pub type SparseRowMatRef<'a, I, T, Rows = usize, Cols = usize> = numeric::generic::SparseRowMat<numeric::Ref<'a, I, T, Rows, Cols>>;
221
222/// view over sparse row major matrix
223///
224/// see [`SymbolicSparseRowMatRef`]
225pub type SparseRowMatMut<'a, I, T, Rows = usize, Cols = usize> = numeric::generic::SparseRowMat<numeric::Mut<'a, I, T, Rows, Cols>>;
226
227/// owning sparse row major matrix
228///
229/// see [`SymbolicSparseRowMatRef`]
230pub type SparseRowMat<I, T, Rows = usize, Cols = usize> = numeric::generic::SparseRowMat<numeric::Own<I, T, Rows, Cols>>;
231
232impl<'a, I, Rows: Copy, Cols: Copy> Copy for symbolic::Ref<'a, I, Rows, Cols> {}
233impl<'a, I, T, Rows: Copy, Cols: Copy> Copy for numeric::Ref<'a, I, T, Rows, Cols> {}
234
235impl<'a, I, Rows: Copy, Cols: Copy> Clone for symbolic::Ref<'a, I, Rows, Cols> {
236	#[inline]
237	fn clone(&self) -> Self {
238		*self
239	}
240}
241impl<'a, I, T, Rows: Copy, Cols: Copy> Clone for numeric::Ref<'a, I, T, Rows, Cols> {
242	#[inline]
243	fn clone(&self) -> Self {
244		*self
245	}
246}
247
248impl<'a, I, Rows: Copy, Cols: Copy> IntoConst for symbolic::Ref<'a, I, Rows, Cols> {
249	type Target = symbolic::Ref<'a, I, Rows, Cols>;
250
251	#[inline]
252	fn into_const(self) -> Self::Target {
253		self
254	}
255}
256
257impl<'short, 'a, I, Rows: Copy, Cols: Copy> ReborrowMut<'short> for symbolic::Ref<'a, I, Rows, Cols> {
258	type Target = symbolic::Ref<'short, I, Rows, Cols>;
259
260	#[inline]
261	fn rb_mut(&'short mut self) -> Self::Target {
262		*self
263	}
264}
265
266impl<'short, 'a, I, Rows: Copy, Cols: Copy> Reborrow<'short> for symbolic::Ref<'a, I, Rows, Cols> {
267	type Target = symbolic::Ref<'short, I, Rows, Cols>;
268
269	#[inline]
270	fn rb(&'short self) -> Self::Target {
271		*self
272	}
273}
274
275impl<'a, I, T, Rows: Copy, Cols: Copy> IntoConst for numeric::Ref<'a, I, T, Rows, Cols> {
276	type Target = numeric::Ref<'a, I, T, Rows, Cols>;
277
278	#[inline]
279	fn into_const(self) -> Self::Target {
280		self
281	}
282}
283
284impl<'short, 'a, I, T, Rows: Copy, Cols: Copy> ReborrowMut<'short> for numeric::Ref<'a, I, T, Rows, Cols> {
285	type Target = numeric::Ref<'short, I, T, Rows, Cols>;
286
287	#[inline]
288	fn rb_mut(&'short mut self) -> Self::Target {
289		*self
290	}
291}
292
293impl<'short, 'a, I, T, Rows: Copy, Cols: Copy> Reborrow<'short> for numeric::Ref<'a, I, T, Rows, Cols> {
294	type Target = numeric::Ref<'short, I, T, Rows, Cols>;
295
296	#[inline]
297	fn rb(&'short self) -> Self::Target {
298		*self
299	}
300}
301
302impl<'a, I, T, Rows: Copy, Cols: Copy> IntoConst for numeric::Mut<'a, I, T, Rows, Cols> {
303	type Target = numeric::Ref<'a, I, T, Rows, Cols>;
304
305	#[inline]
306	fn into_const(self) -> Self::Target {
307		numeric::Ref {
308			symbolic: self.symbolic,
309			val: self.val,
310		}
311	}
312}
313
314impl<'short, 'a, I, T, Rows: Copy, Cols: Copy> ReborrowMut<'short> for numeric::Mut<'a, I, T, Rows, Cols> {
315	type Target = numeric::Mut<'short, I, T, Rows, Cols>;
316
317	#[inline]
318	fn rb_mut(&'short mut self) -> Self::Target {
319		numeric::Mut {
320			symbolic: self.symbolic,
321			val: self.val,
322		}
323	}
324}
325
326impl<'short, 'a, I, T, Rows: Copy, Cols: Copy> Reborrow<'short> for numeric::Mut<'a, I, T, Rows, Cols> {
327	type Target = numeric::Ref<'short, I, T, Rows, Cols>;
328
329	#[inline]
330	fn rb(&'short self) -> Self::Target {
331		numeric::Ref {
332			symbolic: self.symbolic,
333			val: self.val,
334		}
335	}
336}
337
338impl<'short, I, T, Rows: Copy, Cols: Copy> ReborrowMut<'short> for numeric::Own<I, T, Rows, Cols> {
339	type Target = numeric::Mut<'short, I, T, Rows, Cols>;
340
341	#[inline]
342	fn rb_mut(&'short mut self) -> Self::Target {
343		numeric::Mut {
344			symbolic: self.symbolic.rb(),
345			val: &mut self.val,
346		}
347	}
348}
349
350impl<'short, I, T, Rows: Copy, Cols: Copy> Reborrow<'short> for numeric::Own<I, T, Rows, Cols> {
351	type Target = numeric::Ref<'short, I, T, Rows, Cols>;
352
353	#[inline]
354	fn rb(&'short self) -> Self::Target {
355		numeric::Ref {
356			symbolic: self.symbolic.rb(),
357			val: &self.val,
358		}
359	}
360}
361
362impl<'short, I, Rows: Copy, Cols: Copy> Reborrow<'short> for symbolic::Own<I, Rows, Cols> {
363	type Target = symbolic::Ref<'short, I, Rows, Cols>;
364
365	#[inline]
366	fn rb(&'short self) -> Self::Target {
367		symbolic::Ref {
368			nrows: self.nrows,
369			ncols: self.ncols,
370			row_ptr: &self.row_ptr,
371			row_nnz: self.row_nnz.as_deref(),
372			col_idx: &self.col_idx,
373		}
374	}
375}
376
377#[inline(always)]
378#[track_caller]
379fn assume_row_ptr<I: Index>(nrows: usize, ncols: usize, row_ptr: &[I], row_nnz: Option<&[I]>, col_idx: &[I]) {
380	assert!(all(ncols <= I::Signed::MAX.zx(), nrows <= I::Signed::MAX.zx(),));
381	assert!(row_ptr.len() == nrows + 1);
382	assert!(row_ptr[nrows].zx() <= col_idx.len());
383	if let Some(row_nnz) = row_nnz {
384		assert!(row_nnz.len() == nrows);
385	}
386}
387
388#[track_caller]
389fn check_row_ptr<I: Index>(nrows: usize, ncols: usize, row_ptr: &[I], row_nnz: Option<&[I]>, col_idx: &[I]) {
390	assert!(all(ncols <= I::Signed::MAX.zx(), nrows <= I::Signed::MAX.zx(),));
391	assert!(row_ptr.len() == nrows + 1);
392	if let Some(row_nnz) = row_nnz {
393		assert!(row_nnz.len() == nrows);
394		for (&nnz_i, &[row, row_next]) in iter::zip(row_nnz, windows2(row_ptr)) {
395			assert!(row <= row_next);
396			assert!(nnz_i <= row_next - row);
397		}
398	} else {
399		for &[row, row_next] in windows2(row_ptr) {
400			assert!(row <= row_next);
401		}
402	}
403	assert!(row_ptr[nrows].zx() <= col_idx.len());
404}
405
406#[track_caller]
407fn check_col_idx<I: Index>(nrows: usize, ncols: usize, row_ptr: &[I], row_nnz: Option<&[I]>, col_idx: &[I]) {
408	_ = nrows;
409	if let Some(row_nnz) = row_nnz {
410		for (nnz, &r) in iter::zip(row_nnz, row_ptr) {
411			let r = r.zx();
412			let nnz = nnz.zx();
413			let col_idx = &col_idx[r..r + nnz];
414			if !col_idx.is_empty() {
415				let mut j = col_idx[0].zx();
416				for &j_next in &col_idx[1..] {
417					let j_next = j_next.zx();
418					assert!(j < j_next);
419					j = j_next;
420				}
421				assert!(j < ncols);
422			}
423		}
424	} else {
425		for &[r, r_next] in windows2(row_ptr) {
426			let col_idx = &col_idx[r.zx()..r_next.zx()];
427			if !col_idx.is_empty() {
428				let mut j = col_idx[0].zx();
429				for &j_next in &col_idx[1..] {
430					let j_next = j_next.zx();
431					assert!(j < j_next);
432					j = j_next;
433				}
434				assert!(j < ncols);
435			}
436		}
437	}
438}
439
440#[track_caller]
441fn check_col_idx_unsorted<I: Index>(nrows: usize, ncols: usize, row_ptr: &[I], row_nnz: Option<&[I]>, col_idx: &[I]) {
442	_ = nrows;
443
444	if let Some(row_nnz) = row_nnz {
445		for (&nnz, &r) in iter::zip(row_nnz, row_ptr) {
446			let r = r.zx();
447			let nnz = nnz.zx();
448			for &j in &col_idx[r..r + nnz] {
449				let j = j.zx();
450				assert!(j < ncols);
451			}
452		}
453	} else {
454		for &[r, r_next] in windows2(row_ptr) {
455			for &j in &col_idx[r.zx()..r_next.zx()] {
456				let j = j.zx();
457				assert!(j < ncols);
458			}
459		}
460	}
461}
462
463impl<'a, Rows: Shape, Cols: Shape, I: Index> SymbolicSparseRowMatRef<'a, I, Rows, Cols> {
464	/// creates a new symbolic matrix view without checking its invariants
465	///
466	/// # safety
467	/// see type level documentation.
468	#[inline]
469	#[track_caller]
470	pub unsafe fn new_unchecked(nrows: Rows, ncols: Cols, row_ptr: &'a [I], row_nnz: Option<&'a [I]>, col_idx: &'a [I]) -> Self {
471		assume_row_ptr(nrows.unbound(), ncols.unbound(), row_ptr, row_nnz, col_idx);
472
473		Self {
474			0: symbolic::Ref {
475				nrows,
476				ncols,
477				row_ptr,
478				row_nnz,
479				col_idx,
480			},
481		}
482	}
483
484	/// creates a new symbolic matrix view after checking its invariants
485	///
486	/// # safety
487	/// see type level documentation.
488	#[inline]
489	#[track_caller]
490	pub fn new_checked(nrows: Rows, ncols: Cols, row_ptr: &'a [I], row_nnz: Option<&'a [I]>, col_idx: &'a [I]) -> Self {
491		check_row_ptr(nrows.unbound(), ncols.unbound(), row_ptr, row_nnz, col_idx);
492		check_col_idx(nrows.unbound(), ncols.unbound(), row_ptr, row_nnz, col_idx);
493
494		Self {
495			0: symbolic::Ref {
496				nrows,
497				ncols,
498				row_ptr,
499				row_nnz,
500				col_idx,
501			},
502		}
503	}
504
505	/// creates a new symbolic matrix view after checking its invariants (excluding soft invariants)
506	///
507	/// # safety
508	/// see type level documentation.
509	#[inline]
510	#[track_caller]
511	pub fn new_unsorted_checked(nrows: Rows, ncols: Cols, row_ptr: &'a [I], row_nnz: Option<&'a [I]>, col_idx: &'a [I]) -> Self {
512		check_row_ptr(nrows.unbound(), ncols.unbound(), row_ptr, row_nnz, col_idx);
513		check_col_idx_unsorted(nrows.unbound(), ncols.unbound(), row_ptr, row_nnz, col_idx);
514
515		Self {
516			0: symbolic::Ref {
517				nrows,
518				ncols,
519				row_ptr,
520				row_nnz,
521				col_idx,
522			},
523		}
524	}
525
526	/// returns the components of the sparse matrix
527	/// - number of rows
528	/// - number of columns
529	/// - row pointers
530	/// - row non-zero counts
531	/// - column indices
532	#[inline]
533	pub fn parts(self) -> (Rows, Cols, &'a [I], Option<&'a [I]>, &'a [I]) {
534		(self.nrows, self.ncols, self.0.row_ptr, self.0.row_nnz, self.0.col_idx)
535	}
536
537	/// returns the number of rows of the matrix
538	#[inline]
539	pub fn nrows(&self) -> Rows {
540		self.nrows
541	}
542
543	/// returns the number of columns of the matrix
544	#[inline]
545	pub fn ncols(&self) -> Cols {
546		self.ncols
547	}
548
549	/// returns the number of rows and columns of the matrix
550	#[inline]
551	pub fn shape(&self) -> (Rows, Cols) {
552		(self.nrows, self.ncols)
553	}
554
555	/// returns a view over the transpose of `self`
556	#[inline]
557	pub fn transpose(self) -> SymbolicSparseColMatRef<'a, I, Cols, Rows> {
558		SymbolicSparseColMatRef {
559			0: super::csc::symbolic::Ref {
560				nrows: self.ncols,
561				ncols: self.nrows,
562				col_ptr: self.0.row_ptr,
563				col_nnz: self.0.row_nnz,
564				row_idx: self.0.col_idx,
565			},
566		}
567	}
568
569	/// returns a newly allocated matrix holding the values of `self`
570	#[inline]
571	pub fn to_owned(&self) -> Result<SymbolicSparseRowMat<I, Rows, Cols>, FaerError> {
572		Ok(self.transpose().to_owned()?.into_transpose())
573	}
574
575	/// returns a newly allocated matrix holding the values of `self` in column major format
576	#[inline]
577	pub fn to_col_major(&self) -> Result<SymbolicSparseColMat<I, Rows, Cols>, FaerError> {
578		Ok(self.transpose().to_row_major()?.into_transpose())
579	}
580
581	/// returns the number of non-zero elements in the matrix
582	#[inline]
583	pub fn compute_nnz(&self) -> usize {
584		self.transpose().compute_nnz()
585	}
586
587	/// returns the row pointers
588	#[inline]
589	pub fn row_ptr(&self) -> &'a [I] {
590		self.0.row_ptr
591	}
592
593	/// returns the row non-zero counts
594	#[inline]
595	pub fn row_nnz(&self) -> Option<&'a [I]> {
596		self.0.row_nnz
597	}
598
599	/// returns the column indices
600	#[inline]
601	pub fn col_idx(&self) -> &'a [I] {
602		self.0.col_idx
603	}
604
605	/// returns the range specifying the indices of row `i`
606	#[inline]
607	#[track_caller]
608	pub fn row_range(&self, i: Idx<Rows>) -> Range<usize> {
609		assert!(i < self.nrows());
610		unsafe { self.row_range_unchecked(i) }
611	}
612
613	/// returns the range specifying the indices of row `i`, without bound checks
614	#[inline]
615	#[track_caller]
616	pub unsafe fn row_range_unchecked(&self, i: Idx<Rows>) -> Range<usize> {
617		debug_assert!(i < self.nrows());
618
619		self.transpose().col_range_unchecked(i)
620	}
621
622	/// returns the column indices of row `i`
623	#[inline]
624	#[track_caller]
625	pub fn col_idx_of_row_raw(&self, i: Idx<Rows>) -> &'a [Idx<Cols, I>] {
626		unsafe {
627			let slice = self.0.col_idx.get_unchecked(self.row_range(i));
628			let len = slice.len();
629			core::slice::from_raw_parts(slice.as_ptr() as *const Idx<Cols, I>, len)
630		}
631	}
632
633	/// returns the column indices of row `i`
634	#[inline]
635	#[track_caller]
636	pub fn col_idx_of_row(&self, i: Idx<Rows>) -> impl 'a + Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<Cols>>
637	where
638		Rows: 'a,
639		Cols: 'a,
640	{
641		self.col_idx_of_row_raw(i)
642			.iter()
643			.map(|&j| unsafe { Idx::<Cols>::new_unbound(j.unbound().zx()) })
644	}
645
646	/// returns the input matrix with the given shape after checking that it matches the
647	/// current shape
648	#[inline]
649	#[track_caller]
650	pub fn as_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SymbolicSparseRowMatRef<'a, I, V, H> {
651		assert!(all(self.nrows.unbound() == nrows.unbound(), self.ncols.unbound() == ncols.unbound()));
652
653		SymbolicSparseRowMatRef {
654			0: symbolic::Ref {
655				nrows,
656				ncols,
657				row_ptr: self.0.row_ptr,
658				row_nnz: self.0.row_nnz,
659				col_idx: self.0.col_idx,
660			},
661		}
662	}
663
664	/// returns the input matrix with dynamic shape
665	#[inline]
666	pub fn as_dyn(self) -> SymbolicSparseRowMatRef<'a, I> {
667		SymbolicSparseRowMatRef {
668			0: symbolic::Ref {
669				nrows: self.nrows.unbound(),
670				ncols: self.ncols.unbound(),
671				row_ptr: self.0.row_ptr,
672				row_nnz: self.0.row_nnz,
673				col_idx: self.0.col_idx,
674			},
675		}
676	}
677
678	/// Returns a view over the symbolic structure of `self`.
679	#[inline]
680	pub fn as_ref(self) -> SymbolicSparseRowMatRef<'a, I, Rows, Cols> {
681		SymbolicSparseRowMatRef {
682			0: symbolic::Ref {
683				nrows: self.nrows,
684				ncols: self.ncols,
685				row_ptr: self.0.row_ptr,
686				row_nnz: self.0.row_nnz,
687				col_idx: self.0.col_idx,
688			},
689		}
690	}
691}
692
693impl<Rows: Shape, Cols: Shape, I: Index> SymbolicSparseRowMat<I, Rows, Cols> {
694	#[inline]
695	#[track_caller]
696	/// see [`SymbolicSparseRowMatRef::new_unchecked`]
697	pub unsafe fn new_unchecked(
698		nrows: Rows,
699		ncols: Cols,
700		row_ptr: alloc::vec::Vec<I>,
701		row_nnz: Option<alloc::vec::Vec<I>>,
702		col_idx: alloc::vec::Vec<I>,
703	) -> Self {
704		assume_row_ptr(nrows.unbound(), ncols.unbound(), &row_ptr, row_nnz.as_deref(), &col_idx);
705
706		Self {
707			0: symbolic::Own {
708				nrows,
709				ncols,
710				row_ptr,
711				row_nnz,
712				col_idx,
713			},
714		}
715	}
716
717	#[inline]
718	#[track_caller]
719	/// see [`SymbolicSparseRowMatRef::new_checked`]
720	pub fn new_checked(
721		nrows: Rows,
722		ncols: Cols,
723		row_ptr: alloc::vec::Vec<I>,
724		row_nnz: Option<alloc::vec::Vec<I>>,
725		col_idx: alloc::vec::Vec<I>,
726	) -> Self {
727		check_row_ptr(nrows.unbound(), ncols.unbound(), &row_ptr, row_nnz.as_deref(), &col_idx);
728		check_col_idx(nrows.unbound(), ncols.unbound(), &row_ptr, row_nnz.as_deref(), &col_idx);
729
730		Self {
731			0: symbolic::Own {
732				nrows,
733				ncols,
734				row_ptr,
735				row_nnz,
736				col_idx,
737			},
738		}
739	}
740
741	#[inline]
742	#[track_caller]
743	/// see [`SymbolicSparseRowMatRef::new_unsorted_checked`]
744	pub fn new_unsorted_checked(
745		nrows: Rows,
746		ncols: Cols,
747		row_ptr: alloc::vec::Vec<I>,
748		row_nnz: Option<alloc::vec::Vec<I>>,
749		col_idx: alloc::vec::Vec<I>,
750	) -> Self {
751		check_row_ptr(nrows.unbound(), ncols.unbound(), &row_ptr, row_nnz.as_deref(), &col_idx);
752		check_col_idx_unsorted(nrows.unbound(), ncols.unbound(), &row_ptr, row_nnz.as_deref(), &col_idx);
753
754		Self {
755			0: symbolic::Own {
756				nrows,
757				ncols,
758				row_ptr,
759				row_nnz,
760				col_idx,
761			},
762		}
763	}
764
765	#[inline]
766	/// see [`SymbolicSparseRowMatRef::parts`]
767	pub fn parts(&self) -> (Rows, Cols, &'_ [I], Option<&'_ [I]>, &'_ [I]) {
768		(self.nrows, self.ncols, &self.0.row_ptr, self.0.row_nnz.as_deref(), &self.0.col_idx)
769	}
770
771	#[inline]
772	/// see [`SymbolicSparseRowMatRef::parts`]
773	pub fn into_parts(self) -> (Rows, Cols, alloc::vec::Vec<I>, Option<alloc::vec::Vec<I>>, alloc::vec::Vec<I>) {
774		(self.nrows, self.ncols, self.0.row_ptr, self.0.row_nnz, self.0.col_idx)
775	}
776
777	#[inline]
778	/// see [`SymbolicSparseRowMatRef::nrows`]
779	pub fn nrows(&self) -> Rows {
780		self.nrows
781	}
782
783	#[inline]
784	/// see [`SymbolicSparseRowMatRef::ncols`]
785	pub fn ncols(&self) -> Cols {
786		self.ncols
787	}
788
789	#[inline]
790	/// see [`SymbolicSparseRowMatRef::as_shape`]
791	pub fn shape(&self) -> (Rows, Cols) {
792		(self.nrows, self.ncols)
793	}
794
795	#[inline]
796	/// see [`SymbolicSparseRowMatRef::transpose`]
797	pub fn transpose(&self) -> SymbolicSparseColMatRef<'_, I, Cols, Rows> {
798		self.rb().transpose()
799	}
800
801	#[inline]
802	/// see [`SymbolicSparseRowMatRef::transpose`]
803	pub fn into_transpose(self) -> SymbolicSparseColMat<I, Cols, Rows> {
804		SymbolicSparseColMat {
805			0: super::csc::symbolic::Own {
806				nrows: self.ncols,
807				ncols: self.nrows,
808				col_ptr: self.0.row_ptr,
809				col_nnz: self.0.row_nnz,
810				row_idx: self.0.col_idx,
811			},
812		}
813	}
814
815	#[inline]
816	/// see [`SymbolicSparseRowMatRef::to_owned`]
817	pub fn to_owned(&self) -> Result<SymbolicSparseRowMat<I, Rows, Cols>, FaerError> {
818		self.rb().to_owned()
819	}
820
821	#[inline]
822	/// see [`SymbolicSparseRowMatRef::to_col_major`]
823	pub fn to_col_major(&self) -> Result<SymbolicSparseColMat<I, Rows, Cols>, FaerError> {
824		self.rb().to_col_major()
825	}
826
827	#[inline]
828	/// see [`SymbolicSparseRowMatRef::compute_nnz`]
829	pub fn compute_nnz(&self) -> usize {
830		self.rb().compute_nnz()
831	}
832
833	#[inline]
834	/// see [`SymbolicSparseRowMatRef::row_ptr`]
835	pub fn row_ptr(&self) -> &'_ [I] {
836		&self.0.row_ptr
837	}
838
839	#[inline]
840	/// see [`SymbolicSparseRowMatRef::row_nnz`]
841	pub fn row_nnz(&self) -> Option<&'_ [I]> {
842		self.0.row_nnz.as_deref()
843	}
844
845	#[inline]
846	/// see [`SymbolicSparseRowMatRef::col_idx`]
847	pub fn col_idx(&self) -> &'_ [I] {
848		&self.0.col_idx
849	}
850
851	#[inline]
852	#[track_caller]
853	/// see [`SymbolicSparseRowMatRef::row_range`]
854	pub fn row_range(&self, i: Idx<Rows>) -> Range<usize> {
855		self.rb().row_range(i)
856	}
857
858	#[inline]
859	#[track_caller]
860	/// see [`SymbolicSparseRowMatRef::row_range_unchecked`]
861	pub unsafe fn row_range_unchecked(&self, i: Idx<Rows>) -> Range<usize> {
862		self.rb().row_range_unchecked(i)
863	}
864
865	#[inline]
866	#[track_caller]
867	/// see [`SymbolicSparseRowMatRef::col_idx_of_row_raw`]
868	pub fn col_idx_of_row_raw(&self, i: Idx<Rows>) -> &'_ [Idx<Cols, I>] {
869		self.rb().col_idx_of_row_raw(i)
870	}
871
872	#[inline]
873	#[track_caller]
874	/// see [`SymbolicSparseRowMatRef::col_idx_of_row`]
875	pub fn col_idx_of_row(&self, i: Idx<Rows>) -> impl '_ + Clone + ExactSizeIterator + DoubleEndedIterator<Item = Idx<Cols>> {
876		self.rb().col_idx_of_row(i)
877	}
878
879	#[inline]
880	#[track_caller]
881	/// see [`SymbolicSparseRowMatRef::as_shape`]
882	pub fn as_shape<V: Shape, H: Shape>(&self, nrows: V, ncols: H) -> SymbolicSparseRowMatRef<'_, I, V, H> {
883		self.rb().as_shape(nrows, ncols)
884	}
885
886	#[inline]
887	#[track_caller]
888	/// see [`SymbolicSparseRowMatRef::as_shape`]
889	pub fn into_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SymbolicSparseRowMat<I, V, H> {
890		assert!(all(self.nrows().unbound() == nrows.unbound(), self.ncols().unbound() == ncols.unbound()));
891		SymbolicSparseRowMat {
892			0: symbolic::Own {
893				nrows,
894				ncols,
895				row_ptr: self.0.row_ptr,
896				row_nnz: self.0.row_nnz,
897				col_idx: self.0.col_idx,
898			},
899		}
900	}
901
902	#[inline]
903	/// see [`SymbolicSparseRowMatRef::as_dyn`]
904	pub fn as_dyn(&self) -> SymbolicSparseRowMatRef<'_, I> {
905		self.rb().as_dyn()
906	}
907
908	#[inline]
909	/// see [`SymbolicSparseRowMatRef::as_dyn`]
910	pub fn into_dyn(self) -> SymbolicSparseRowMat<I> {
911		SymbolicSparseRowMat {
912			0: symbolic::Own {
913				nrows: self.nrows.unbound(),
914				ncols: self.ncols.unbound(),
915				row_ptr: self.0.row_ptr,
916				row_nnz: self.0.row_nnz,
917				col_idx: self.0.col_idx,
918			},
919		}
920	}
921
922	#[inline]
923	/// Returns a view over the symbolic structure of `self`.
924	pub fn as_ref(&self) -> SymbolicSparseRowMatRef<'_, I, Rows, Cols> {
925		SymbolicSparseRowMatRef {
926			0: symbolic::Ref {
927				nrows: self.nrows,
928				ncols: self.ncols,
929				row_ptr: &self.0.row_ptr,
930				row_nnz: self.0.row_nnz.as_deref(),
931				col_idx: &self.0.col_idx,
932			},
933		}
934	}
935
936	#[inline]
937	/// create a new symbolic structure, and the corresponding order for the numerical values
938	/// from pairs of indices
939	pub fn try_new_from_indices(nrows: Rows, ncols: Cols, idx: &[Pair<Idx<Rows, I>, Idx<Cols, I>>]) -> Result<(Self, Argsort<I>), CreationError> {
940		let (symbolic, argsort) = SymbolicSparseColMat::try_new_from_indices_impl(
941			ncols,
942			nrows,
943			|i| Pair {
944				row: idx[i].col,
945				col: idx[i].row,
946			},
947			|_, _| false,
948			idx.len(),
949		)?;
950
951		Ok((symbolic.into_transpose(), argsort))
952	}
953
954	#[inline]
955	/// create a new symbolic structure, and the corresponding order for the numerical values
956	/// from pairs of indices
957	///
958	/// negative indices are ignored
959	pub fn try_new_from_nonnegative_indices(
960		nrows: Rows,
961		ncols: Cols,
962		idx: &[Pair<MaybeIdx<Rows, I>, MaybeIdx<Cols, I>>],
963	) -> Result<(Self, Argsort<I>), CreationError> {
964		let (symbolic, argsort) = SymbolicSparseColMat::try_new_from_indices_impl(
965			ncols,
966			nrows,
967			|i| Pair {
968				row: unsafe { Idx::<Cols, I>::new_unbound(I::from_signed(idx[i].col.unbound())) },
969				col: unsafe { Idx::<Rows, I>::new_unbound(I::from_signed(idx[i].row.unbound())) },
970			},
971			|row, col| {
972				let row = row.unbound().to_signed();
973				let col = col.unbound().to_signed();
974				let zero = I::Signed::truncate(0);
975
976				row < zero || col < zero
977			},
978			idx.len(),
979		)?;
980		Ok((symbolic.into_transpose(), argsort))
981	}
982}
983
984impl<'a, Rows: Shape, Cols: Shape, I: Index, T> SparseRowMatRef<'a, I, T, Rows, Cols> {
985	/// creates a new sparse matrix view.
986	///
987	/// # panics
988	/// panics if the length of `values` is not equal to the length of
989	/// `symbolic.col_idx()`
990	#[inline]
991	#[track_caller]
992	pub fn new(symbolic: SymbolicSparseRowMatRef<'a, I, Rows, Cols>, val: &'a [T]) -> Self {
993		assert!(symbolic.col_idx().len() == val.len());
994		Self {
995			0: numeric::Ref { symbolic, val },
996		}
997	}
998
999	/// returns the symbolic and numeric components of the sparse matrix
1000	#[inline]
1001	pub fn parts(self) -> (SymbolicSparseRowMatRef<'a, I, Rows, Cols>, &'a [T]) {
1002		(self.0.symbolic, self.0.val)
1003	}
1004
1005	/// returns the symbolic component of the sparse matrix
1006	#[inline]
1007	pub fn symbolic(&self) -> SymbolicSparseRowMatRef<'a, I, Rows, Cols> {
1008		self.0.symbolic
1009	}
1010
1011	/// returns the numeric component of the sparse matrix
1012	#[inline]
1013	pub fn val(self) -> &'a [T] {
1014		self.0.val
1015	}
1016
1017	/// returns a view over the values of row `i`
1018	#[inline]
1019	#[track_caller]
1020	pub fn val_of_row(self, i: Idx<Rows>) -> &'a [T] {
1021		unsafe { self.0.val.get_unchecked(self.row_range(i)) }
1022	}
1023
1024	/// returns the input matrix with the given shape after checking that it matches the
1025	/// current shape
1026	#[inline]
1027	#[track_caller]
1028	pub fn as_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SparseRowMatRef<'a, I, T, V, H> {
1029		SparseRowMatRef {
1030			0: numeric::Ref {
1031				symbolic: self.0.symbolic.as_shape(nrows, ncols),
1032				val: self.0.val,
1033			},
1034		}
1035	}
1036
1037	/// returns a reference to the value at the given index, or `None` if the symbolic structure
1038	/// doesn't contain it, or contains multiple indices with the given index
1039	///
1040	/// # panics
1041	/// - panics if `row >= self.nrows()`
1042	/// - panics if `col >= self.ncols()`
1043	#[track_caller]
1044	pub fn get(self, row: Idx<Rows>, col: Idx<Cols>) -> Option<&'a T> {
1045		assert!(row < self.nrows());
1046		assert!(col < self.ncols());
1047		let col = I::truncate(col.unbound());
1048		let rowl = row.unbound();
1049		let start = self
1050			.symbolic()
1051			.as_dyn()
1052			.col_idx_of_row_raw(rowl)
1053			.partition_point(super::csc::partition_by_lt(col));
1054		let end = start + self.symbolic().as_dyn().col_idx_of_row_raw(rowl)[start..].partition_point(super::csc::partition_by_le(col));
1055
1056		if end == start + 1 { Some(&self.val_of_row(row)[start]) } else { None }
1057	}
1058
1059	/// returns the input matrix with dynamic shape
1060	#[inline]
1061	pub fn as_dyn(self) -> SparseRowMatRef<'a, I, T> {
1062		SparseRowMatRef {
1063			0: numeric::Ref {
1064				symbolic: self.0.symbolic.as_dyn(),
1065				val: self.0.val,
1066			},
1067		}
1068	}
1069
1070	/// returns a view over `self`
1071	#[inline]
1072	pub fn as_ref(self) -> SparseRowMatRef<'a, I, T, Rows, Cols> {
1073		SparseRowMatRef {
1074			0: numeric::Ref {
1075				symbolic: self.0.symbolic,
1076				val: self.0.val,
1077			},
1078		}
1079	}
1080
1081	/// returns a view over the transpose of `self`
1082	#[inline]
1083	pub fn transpose(self) -> SparseColMatRef<'a, I, T, Cols, Rows> {
1084		SparseColMatRef {
1085			0: super::csc::numeric::Ref {
1086				symbolic: self.0.symbolic.transpose(),
1087				val: self.0.val,
1088			},
1089		}
1090	}
1091
1092	/// returns a view over the conjugate of `self`
1093	#[inline]
1094	pub fn conjugate(self) -> SparseRowMatRef<'a, I, T::Conj, Rows, Cols>
1095	where
1096		T: Conjugate,
1097	{
1098		self.transpose().conjugate().transpose()
1099	}
1100
1101	/// returns a view over the adjoint of `self`
1102	#[inline]
1103	pub fn adjoint(self) -> SparseColMatRef<'a, I, T::Conj, Cols, Rows>
1104	where
1105		T: Conjugate,
1106	{
1107		self.transpose().conjugate()
1108	}
1109
1110	/// returns an unconjugated view over `self`
1111	#[inline]
1112	pub fn canonical(self) -> SparseRowMatRef<'a, I, T::Canonical, Rows, Cols>
1113	where
1114		T: Conjugate,
1115	{
1116		self.transpose().canonical().transpose()
1117	}
1118
1119	/// returns a newly allocated matrix holding the (possibly conjugated) values of `self` in
1120	/// column major format
1121	#[inline]
1122	pub fn to_col_major(&self) -> Result<SparseColMat<I, T::Canonical, Rows, Cols>, FaerError>
1123	where
1124		T: Conjugate,
1125	{
1126		Ok(self.transpose().to_row_major()?.into_transpose())
1127	}
1128
1129	/// returns a newly allocated dense matrix holding the (possibly conjugated) values of `self`
1130	#[inline]
1131	pub fn to_dense(&self) -> Mat<T::Canonical, Rows, Cols>
1132	where
1133		T: Conjugate,
1134	{
1135		fn imp<'ROWS, 'COLS, I: Index, T: Conjugate>(
1136			src: SparseRowMatRef<'_, I, T, Dim<'ROWS>, Dim<'COLS>>,
1137		) -> Mat<T::Canonical, Dim<'ROWS>, Dim<'COLS>> {
1138			let src = src.canonical();
1139
1140			let mut out = Mat::zeros(src.nrows(), src.ncols());
1141			let M = src.nrows();
1142
1143			for i in M.indices() {
1144				for (j, val) in iter::zip(src.col_idx_of_row(i), src.val_of_row(i)) {
1145					if try_const! { Conj::get::<T>().is_conj() } {
1146						out[(i, j)] = add(&out[(i, j)], &conj(val));
1147					} else {
1148						out[(i, j)] = add(&out[(i, j)], val);
1149					}
1150				}
1151			}
1152
1153			out
1154		}
1155		with_dim!(ROWS, self.nrows().unbound());
1156		with_dim!(COLS, self.ncols().unbound());
1157		let this = self.as_shape(ROWS, COLS);
1158
1159		imp(this).into_shape(self.nrows(), self.ncols())
1160	}
1161
1162	/// returns an iterator over the entries of the matrix.
1163	pub fn triplet_iter(self) -> impl 'a + Iterator<Item = Triplet<Idx<Rows>, Idx<Cols>, &'a T>>
1164	where
1165		Rows: 'a,
1166		Cols: 'a,
1167	{
1168		self.transpose().triplet_iter().map(
1169			#[inline(always)]
1170			|Triplet { row, col, val }| Triplet { row: col, col: row, val },
1171		)
1172	}
1173}
1174
1175impl<'a, Rows: Shape, Cols: Shape, I: Index, T> SparseRowMatMut<'a, I, T, Rows, Cols> {
1176	#[inline]
1177	#[track_caller]
1178	/// see [`SparseRowMatRef::new`]
1179	pub fn new(symbolic: SymbolicSparseRowMatRef<'a, I, Rows, Cols>, val: &'a mut [T]) -> Self {
1180		assert!(symbolic.col_idx().len() == val.len());
1181		Self {
1182			0: numeric::Mut { symbolic, val },
1183		}
1184	}
1185
1186	#[inline]
1187	/// see [`SparseRowMatRef::parts`]
1188	pub fn parts(self) -> (SymbolicSparseRowMatRef<'a, I, Rows, Cols>, &'a [T]) {
1189		(self.0.symbolic, self.0.val)
1190	}
1191
1192	#[inline]
1193	/// see [`SparseRowMatRef::parts`]
1194	pub fn parts_mut(self) -> (SymbolicSparseRowMatRef<'a, I, Rows, Cols>, &'a mut [T]) {
1195		(self.0.symbolic, self.0.val)
1196	}
1197
1198	#[inline]
1199	/// see [`SparseRowMatRef::symbolic`]
1200	pub fn symbolic(&self) -> SymbolicSparseRowMatRef<'a, I, Rows, Cols> {
1201		self.0.symbolic
1202	}
1203
1204	#[inline]
1205	/// see [`SparseRowMatRef::val`]
1206	pub fn val(self) -> &'a [T] {
1207		self.0.val
1208	}
1209
1210	#[inline]
1211	/// see [`SparseRowMatRef::val`]
1212	pub fn val_mut(self) -> &'a mut [T] {
1213		self.0.val
1214	}
1215
1216	#[inline]
1217	#[track_caller]
1218	/// see [`SparseRowMatRef::val_of_row`]
1219	pub fn val_of_row(self, i: Idx<Rows>) -> &'a [T] {
1220		unsafe { self.0.val.get_unchecked(self.row_range(i)) }
1221	}
1222
1223	#[inline]
1224	#[track_caller]
1225	/// see [`SparseRowMatRef::val_of_row`]
1226	pub fn val_of_row_mut(self, j: Idx<Rows>) -> &'a mut [T] {
1227		unsafe { self.0.val.get_unchecked_mut(self.row_range(j)) }
1228	}
1229
1230	#[inline]
1231	#[track_caller]
1232	/// see [`SparseRowMatRef::as_shape`]
1233	pub fn as_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SparseRowMatRef<'a, I, T, V, H> {
1234		SparseRowMatRef {
1235			0: numeric::Ref {
1236				symbolic: self.0.symbolic.as_shape(nrows, ncols),
1237				val: self.0.val,
1238			},
1239		}
1240	}
1241
1242	#[inline]
1243	#[track_caller]
1244	/// see [`SparseRowMatRef::as_shape`]
1245	pub fn as_shape_mut<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SparseRowMatMut<'a, I, T, V, H> {
1246		SparseRowMatMut {
1247			0: numeric::Mut {
1248				symbolic: self.0.symbolic.as_shape(nrows, ncols),
1249				val: self.0.val,
1250			},
1251		}
1252	}
1253
1254	/// see [`SparseRowMatRef::get`]
1255	#[track_caller]
1256	#[inline]
1257	pub fn get(self, row: Idx<Rows>, col: Idx<Cols>) -> Option<&'a T> {
1258		self.into_const().get(row, col)
1259	}
1260
1261	/// returns a reference to the value at the given index, or `None` if the symbolic structure
1262	/// doesn't contain it, or contains multiple indices with the given index
1263	///
1264	/// # panics
1265	/// - panics if `row >= self.nrows()`
1266	/// - panics if `col >= self.ncols()`
1267	#[track_caller]
1268	/// see [`SparseRowMatRef::get`]
1269	pub fn get_mut(self, row: Idx<Rows>, col: Idx<Cols>) -> Option<&'a mut T> {
1270		assert!(row < self.nrows());
1271		assert!(col < self.ncols());
1272		let col = I::truncate(col.unbound());
1273		let rowl = row.unbound();
1274		let start = self
1275			.symbolic()
1276			.as_dyn()
1277			.col_idx_of_row_raw(rowl)
1278			.partition_point(super::csc::partition_by_lt(col));
1279		let end = start + self.symbolic().as_dyn().col_idx_of_row_raw(rowl)[start..].partition_point(super::csc::partition_by_le(col));
1280
1281		if end == start + 1 {
1282			Some(&mut self.val_of_row_mut(row)[start])
1283		} else {
1284			None
1285		}
1286	}
1287
1288	#[inline]
1289	/// see [`SparseRowMatRef::as_dyn`]
1290	pub fn as_dyn(self) -> SparseRowMatRef<'a, I, T> {
1291		SparseRowMatRef {
1292			0: numeric::Ref {
1293				symbolic: self.0.symbolic.as_dyn(),
1294				val: self.0.val,
1295			},
1296		}
1297	}
1298
1299	#[inline]
1300	/// see [`SparseRowMatRef::as_dyn`]
1301	pub fn as_dyn_mut(self) -> SparseRowMatMut<'a, I, T> {
1302		SparseRowMatMut {
1303			0: numeric::Mut {
1304				symbolic: self.0.symbolic.as_dyn(),
1305				val: self.0.val,
1306			},
1307		}
1308	}
1309
1310	#[inline]
1311	/// see [`SparseRowMatRef::transpose`]
1312	pub fn transpose(self) -> SparseColMatRef<'a, I, T, Cols, Rows> {
1313		SparseColMatRef {
1314			0: super::csc::numeric::Ref {
1315				symbolic: self.0.symbolic.transpose(),
1316				val: self.0.val,
1317			},
1318		}
1319	}
1320
1321	#[inline]
1322	/// see [`SparseRowMatRef::transpose`]
1323	pub fn transpose_mut(self) -> SparseColMatMut<'a, I, T, Cols, Rows> {
1324		SparseColMatMut {
1325			0: super::csc::numeric::Mut {
1326				symbolic: self.0.symbolic.transpose(),
1327				val: self.0.val,
1328			},
1329		}
1330	}
1331
1332	#[inline]
1333	/// see [`SparseRowMatRef::conjugate`]
1334	pub fn conjugate(self) -> SparseRowMatRef<'a, I, T::Conj, Rows, Cols>
1335	where
1336		T: Conjugate,
1337	{
1338		let len = self.0.val.len();
1339		SparseRowMatRef {
1340			0: numeric::Ref {
1341				symbolic: self.0.symbolic,
1342				val: unsafe { core::slice::from_raw_parts(self.0.val.as_ptr() as *const T::Conj, len) },
1343			},
1344		}
1345	}
1346
1347	#[inline]
1348	/// see [`SparseRowMatRef::conjugate`]
1349	pub fn conjugate_mut(self) -> SparseRowMatMut<'a, I, T::Conj, Rows, Cols>
1350	where
1351		T: Conjugate,
1352	{
1353		let len = self.0.val.len();
1354		SparseRowMatMut {
1355			0: numeric::Mut {
1356				symbolic: self.0.symbolic,
1357				val: unsafe { core::slice::from_raw_parts_mut(self.0.val.as_mut_ptr() as *mut T::Conj, len) },
1358			},
1359		}
1360	}
1361
1362	#[inline]
1363	/// see [`SparseRowMatRef::adjoint`]
1364	pub fn adjoint(self) -> SparseColMatRef<'a, I, T::Conj, Cols, Rows>
1365	where
1366		T: Conjugate,
1367	{
1368		self.conjugate().transpose()
1369	}
1370
1371	#[inline]
1372	/// see [`SparseRowMatRef::adjoint`]
1373	pub fn adjoint_mut(self) -> SparseColMatMut<'a, I, T::Conj, Cols, Rows>
1374	where
1375		T: Conjugate,
1376	{
1377		self.conjugate_mut().transpose_mut()
1378	}
1379
1380	#[inline]
1381	/// see [`SparseRowMatRef::canonical`]
1382	pub fn canonical(self) -> SparseRowMatRef<'a, I, T::Canonical, Rows, Cols>
1383	where
1384		T: Conjugate,
1385	{
1386		let len = self.0.val.len();
1387		SparseRowMatRef {
1388			0: numeric::Ref {
1389				symbolic: self.0.symbolic,
1390				val: unsafe { core::slice::from_raw_parts(self.0.val.as_ptr() as *const T::Canonical, len) },
1391			},
1392		}
1393	}
1394
1395	#[inline]
1396	/// see [`SparseRowMatRef::canonical`]
1397	pub fn canonical_mut(self) -> SparseRowMatMut<'a, I, T::Canonical, Rows, Cols>
1398	where
1399		T: Conjugate,
1400	{
1401		let len = self.0.val.len();
1402		SparseRowMatMut {
1403			0: numeric::Mut {
1404				symbolic: self.0.symbolic,
1405				val: unsafe { core::slice::from_raw_parts_mut(self.0.val.as_mut_ptr() as *mut T::Canonical, len) },
1406			},
1407		}
1408	}
1409
1410	#[inline]
1411	/// see [`SparseRowMatRef::to_col_major`]
1412	pub fn to_col_major(&self) -> Result<SparseColMat<I, T::Canonical, Rows, Cols>, FaerError>
1413	where
1414		T: Conjugate,
1415	{
1416		self.rb().to_col_major()
1417	}
1418
1419	#[inline]
1420	/// see [`SparseRowMatRef::to_dense`]
1421	pub fn to_dense(&self) -> Mat<T::Canonical, Rows, Cols>
1422	where
1423		T: Conjugate,
1424	{
1425		self.rb().to_dense()
1426	}
1427
1428	/// see [`SparseRowMatRef::triplet_iter`]
1429	#[inline]
1430	pub fn triplet_iter(self) -> impl 'a + Iterator<Item = Triplet<Idx<Rows>, Idx<Cols>, &'a T>>
1431	where
1432		Rows: 'a,
1433		Cols: 'a,
1434	{
1435		self.into_const().triplet_iter()
1436	}
1437}
1438
1439impl<Rows: Shape, Cols: Shape, I: Index, T> SparseRowMat<I, T, Rows, Cols> {
1440	#[inline]
1441	#[track_caller]
1442	/// see [`SparseRowMatRef::new`]
1443	pub fn new(symbolic: SymbolicSparseRowMat<I, Rows, Cols>, val: alloc::vec::Vec<T>) -> Self {
1444		assert!(symbolic.col_idx().len() == val.len());
1445		Self {
1446			0: numeric::Own { symbolic, val },
1447		}
1448	}
1449
1450	#[inline]
1451	/// see [`SparseRowMatRef::parts`]
1452	pub fn parts(&self) -> (SymbolicSparseRowMatRef<'_, I, Rows, Cols>, &'_ [T]) {
1453		(self.0.symbolic.rb(), &self.0.val)
1454	}
1455
1456	#[inline]
1457	/// see [`SparseRowMatRef::parts`]
1458	pub fn parts_mut(&mut self) -> (SymbolicSparseRowMatRef<'_, I, Rows, Cols>, &'_ mut [T]) {
1459		(self.0.symbolic.rb(), &mut self.0.val)
1460	}
1461
1462	#[inline]
1463	/// see [`SparseRowMatRef::parts`]
1464	pub fn into_parts(self) -> (SymbolicSparseRowMat<I, Rows, Cols>, alloc::vec::Vec<T>) {
1465		(self.0.symbolic, self.0.val)
1466	}
1467
1468	#[inline]
1469	/// see [`SparseRowMatRef::symbolic`]
1470	pub fn symbolic(&self) -> SymbolicSparseRowMatRef<'_, I, Rows, Cols> {
1471		self.0.symbolic.rb()
1472	}
1473
1474	#[inline]
1475	/// see [`SparseRowMatRef::val`]
1476	pub fn val(&self) -> &'_ [T] {
1477		&self.0.val
1478	}
1479
1480	#[inline]
1481	/// see [`SparseRowMatRef::val`]
1482	pub fn val_mut(&mut self) -> &'_ mut [T] {
1483		&mut self.0.val
1484	}
1485
1486	#[inline]
1487	#[track_caller]
1488	/// see [`SparseRowMatRef::val_of_row`]
1489	pub fn val_of_row(&self, j: Idx<Rows>) -> &'_ [T] {
1490		unsafe { self.0.val.get_unchecked(self.row_range(j)) }
1491	}
1492
1493	#[inline]
1494	#[track_caller]
1495	/// see [`SparseRowMatRef::val_of_row`]
1496	pub fn val_of_row_mut(&mut self, j: Idx<Rows>) -> &'_ mut [T] {
1497		unsafe { self.0.val.get_unchecked_mut(self.0.symbolic.row_range(j)) }
1498	}
1499
1500	#[inline]
1501	#[track_caller]
1502	/// see [`SparseRowMatRef::as_shape`]
1503	pub fn as_shape<V: Shape, H: Shape>(&self, nrows: V, ncols: H) -> SparseRowMatRef<'_, I, T, V, H> {
1504		SparseRowMatRef {
1505			0: numeric::Ref {
1506				symbolic: self.0.symbolic.as_shape(nrows, ncols),
1507				val: &self.0.val,
1508			},
1509		}
1510	}
1511
1512	#[inline]
1513	#[track_caller]
1514	/// see [`SparseRowMatRef::as_shape`]
1515	pub fn as_shape_mut<V: Shape, H: Shape>(&mut self, nrows: V, ncols: H) -> SparseRowMatMut<'_, I, T, V, H> {
1516		SparseRowMatMut {
1517			0: numeric::Mut {
1518				symbolic: self.0.symbolic.as_shape(nrows, ncols),
1519				val: &mut self.0.val,
1520			},
1521		}
1522	}
1523
1524	#[inline]
1525	#[track_caller]
1526	/// see [`SparseRowMatRef::as_shape`]
1527	pub fn into_shape<V: Shape, H: Shape>(self, nrows: V, ncols: H) -> SparseRowMat<I, T, V, H> {
1528		SparseRowMat {
1529			0: numeric::Own {
1530				symbolic: self.0.symbolic.into_shape(nrows, ncols),
1531				val: self.0.val,
1532			},
1533		}
1534	}
1535
1536	#[inline]
1537	/// see [`SparseRowMatRef::as_dyn`]
1538	pub fn as_dyn(&self) -> SparseRowMatRef<'_, I, T> {
1539		SparseRowMatRef {
1540			0: numeric::Ref {
1541				symbolic: self.0.symbolic.as_dyn(),
1542				val: &self.0.val,
1543			},
1544		}
1545	}
1546
1547	#[inline]
1548	/// see [`SparseRowMatRef::as_dyn`]
1549	pub fn as_dyn_mut(&mut self) -> SparseRowMatMut<'_, I, T> {
1550		SparseRowMatMut {
1551			0: numeric::Mut {
1552				symbolic: self.0.symbolic.as_dyn(),
1553				val: &mut self.0.val,
1554			},
1555		}
1556	}
1557
1558	#[inline]
1559	/// see [`SparseRowMatRef::as_dyn`]
1560	pub fn into_dyn(self) -> SparseRowMat<I, T> {
1561		SparseRowMat {
1562			0: numeric::Own {
1563				symbolic: self.0.symbolic.into_dyn(),
1564				val: self.0.val,
1565			},
1566		}
1567	}
1568
1569	#[inline]
1570	/// see [`SparseRowMatRef::as_ref`]
1571	pub fn as_ref(&self) -> SparseRowMatRef<'_, I, T, Rows, Cols> {
1572		SparseRowMatRef {
1573			0: numeric::Ref {
1574				symbolic: self.0.symbolic.as_ref(),
1575				val: &self.0.val,
1576			},
1577		}
1578	}
1579
1580	#[inline]
1581	/// see [`SparseRowMatRef::transpose`]
1582	pub fn transpose(&self) -> SparseColMatRef<'_, I, T, Cols, Rows> {
1583		SparseColMatRef {
1584			0: super::csc::numeric::Ref {
1585				symbolic: self.0.symbolic.transpose(),
1586				val: &self.0.val,
1587			},
1588		}
1589	}
1590
1591	#[inline]
1592	/// see [`SparseRowMatRef::transpose`]
1593	pub fn transpose_mut(&mut self) -> SparseColMatMut<'_, I, T, Cols, Rows> {
1594		SparseColMatMut {
1595			0: super::csc::numeric::Mut {
1596				symbolic: self.0.symbolic.transpose(),
1597				val: &mut self.0.val,
1598			},
1599		}
1600	}
1601
1602	#[inline]
1603	/// see [`SparseRowMatRef::transpose`]
1604	pub fn into_transpose(self) -> SparseColMat<I, T, Cols, Rows> {
1605		SparseColMat {
1606			0: super::csc::numeric::Own {
1607				symbolic: self.0.symbolic.into_transpose(),
1608				val: self.0.val,
1609			},
1610		}
1611	}
1612
1613	#[inline]
1614	/// see [`SparseRowMatRef::conjugate`]
1615	pub fn conjugate(&self) -> SparseRowMatRef<'_, I, T::Conj, Rows, Cols>
1616	where
1617		T: Conjugate,
1618	{
1619		self.rb().conjugate()
1620	}
1621
1622	#[inline]
1623	/// see [`SparseRowMatRef::conjugate`]
1624	pub fn conjugate_mut(&mut self) -> SparseRowMatMut<'_, I, T::Conj, Rows, Cols>
1625	where
1626		T: Conjugate,
1627	{
1628		self.rb_mut().conjugate_mut()
1629	}
1630
1631	#[inline]
1632	/// see [`SparseRowMatRef::conjugate`]
1633	pub fn into_conjugate(self) -> SparseRowMat<I, T::Conj, Rows, Cols>
1634	where
1635		T: Conjugate,
1636	{
1637		let mut vec = core::mem::ManuallyDrop::new(self.0.val);
1638		let len = vec.len();
1639		let cap = vec.capacity();
1640		let ptr = vec.as_mut_ptr();
1641
1642		SparseRowMat {
1643			0: numeric::Own {
1644				symbolic: self.0.symbolic,
1645				val: unsafe { alloc::vec::Vec::from_raw_parts(ptr as *mut T::Conj, len, cap) },
1646			},
1647		}
1648	}
1649
1650	#[inline]
1651	/// see [`SparseRowMatRef::adjoint`]
1652	pub fn adjoint(&self) -> SparseColMatRef<'_, I, T::Conj, Cols, Rows>
1653	where
1654		T: Conjugate,
1655	{
1656		self.conjugate().transpose()
1657	}
1658
1659	#[inline]
1660	/// see [`SparseRowMatRef::adjoint`]
1661	pub fn adjoint_mut(&mut self) -> SparseColMatMut<'_, I, T::Conj, Cols, Rows>
1662	where
1663		T: Conjugate,
1664	{
1665		self.conjugate_mut().transpose_mut()
1666	}
1667
1668	#[inline]
1669	/// see [`SparseRowMatRef::adjoint`]
1670	pub fn into_adjoint(self) -> SparseColMat<I, T::Conj, Cols, Rows>
1671	where
1672		T: Conjugate,
1673	{
1674		self.into_conjugate().into_transpose()
1675	}
1676
1677	#[inline]
1678	/// see [`SparseRowMatRef::canonical`]
1679	pub fn canonical(&self) -> SparseRowMatRef<'_, I, T::Canonical, Rows, Cols>
1680	where
1681		T: Conjugate,
1682	{
1683		let len = self.0.val.len();
1684		SparseRowMatRef {
1685			0: numeric::Ref {
1686				symbolic: self.0.symbolic.rb(),
1687				val: unsafe { core::slice::from_raw_parts(self.0.val.as_ptr() as *const T::Canonical, len) },
1688			},
1689		}
1690	}
1691
1692	#[inline]
1693	/// see [`SparseRowMatRef::canonical`]
1694	pub fn canonical_mut(&mut self) -> SparseRowMatMut<'_, I, T::Canonical, Rows, Cols>
1695	where
1696		T: Conjugate,
1697	{
1698		let len = self.0.val.len();
1699		SparseRowMatMut {
1700			0: numeric::Mut {
1701				symbolic: self.0.symbolic.rb(),
1702				val: unsafe { core::slice::from_raw_parts_mut(self.0.val.as_mut_ptr() as *mut T::Canonical, len) },
1703			},
1704		}
1705	}
1706
1707	#[inline]
1708	/// see [`SparseRowMatRef::canonical`]
1709	pub fn into_canonical(self) -> SparseRowMat<I, T::Canonical, Rows, Cols>
1710	where
1711		T: Conjugate,
1712	{
1713		let mut vec = core::mem::ManuallyDrop::new(self.0.val);
1714		let len = vec.len();
1715		let cap = vec.capacity();
1716		let ptr = vec.as_mut_ptr();
1717
1718		SparseRowMat {
1719			0: numeric::Own {
1720				symbolic: self.0.symbolic,
1721				val: unsafe { alloc::vec::Vec::from_raw_parts(ptr as *mut T::Canonical, len, cap) },
1722			},
1723		}
1724	}
1725
1726	#[inline]
1727	/// see [`SparseRowMatRef::to_col_major`]
1728	pub fn to_col_major(&self) -> Result<SparseColMat<I, T::Canonical, Rows, Cols>, FaerError>
1729	where
1730		T: Conjugate,
1731	{
1732		self.rb().to_col_major()
1733	}
1734
1735	#[inline]
1736	/// see [`SparseRowMatRef::to_dense`]
1737	pub fn to_dense(&self) -> Mat<T::Canonical, Rows, Cols>
1738	where
1739		T: Conjugate,
1740	{
1741		self.rb().to_dense()
1742	}
1743
1744	#[track_caller]
1745	/// create a new matrix from a previously created symbolic structure and value order
1746	///
1747	/// the provided values must correspond to the same indices that were provided in the
1748	/// function call from which the order was created
1749	pub fn new_from_argsort(symbolic: SymbolicSparseRowMat<I, Rows, Cols>, argsort: &Argsort<I>, val: &[T]) -> Result<Self, FaerError>
1750	where
1751		T: ComplexField,
1752	{
1753		Ok(SparseColMat::new_from_argsort(symbolic.into_transpose(), argsort, val)?.into_transpose())
1754	}
1755
1756	#[track_caller]
1757	/// create a new matrix from triplets
1758	pub fn try_new_from_triplets(nrows: Rows, ncols: Cols, entries: &[Triplet<Idx<Rows, I>, Idx<Cols, I>, T>]) -> Result<Self, CreationError>
1759	where
1760		T: ComplexField,
1761	{
1762		let (symbolic, argsort) = SymbolicSparseColMat::try_new_from_indices_impl(
1763			ncols,
1764			nrows,
1765			|i| Pair {
1766				row: entries[i].col,
1767				col: entries[i].row,
1768			},
1769			|_, _| false,
1770			entries.len(),
1771		)?;
1772
1773		Ok(SparseColMat::new_from_argsort_impl(symbolic, &argsort, |i| entries[i].val.clone(), entries.len())?.into_transpose())
1774	}
1775
1776	#[track_caller]
1777	/// create a new matrix from triplets
1778	///
1779	/// negative indices are ignored
1780	pub fn try_new_from_nonnegative_triplets(
1781		nrows: Rows,
1782		ncols: Cols,
1783		entries: &[Triplet<MaybeIdx<Rows, I>, MaybeIdx<Cols, I>, T>],
1784	) -> Result<Self, CreationError>
1785	where
1786		T: ComplexField,
1787	{
1788		let (symbolic, argsort) = SymbolicSparseColMat::try_new_from_indices_impl(
1789			ncols,
1790			nrows,
1791			|i| Pair {
1792				row: unsafe { Idx::<Cols, I>::new_unbound(I::from_signed(entries[i].col.unbound())) },
1793				col: unsafe { Idx::<Rows, I>::new_unbound(I::from_signed(entries[i].row.unbound())) },
1794			},
1795			|row, col| {
1796				let row = row.unbound().to_signed();
1797				let col = col.unbound().to_signed();
1798				let zero = I::Signed::truncate(0);
1799				row < zero || col < zero
1800			},
1801			entries.len(),
1802		)?;
1803
1804		Ok(SparseColMat::new_from_argsort_impl(symbolic, &argsort, |i| entries[i].val.clone(), entries.len())?.into_transpose())
1805	}
1806
1807	/// see [`SparseRowMatRef::get`]
1808	#[track_caller]
1809	#[inline]
1810	pub fn get(&self, row: Idx<Rows>, col: Idx<Cols>) -> Option<&T> {
1811		self.rb().get(row, col)
1812	}
1813
1814	/// see [`SparseRowMatRef::get`]
1815	#[track_caller]
1816	#[inline]
1817	pub fn get_mut(&mut self, row: Idx<Rows>, col: Idx<Cols>) -> Option<&mut T> {
1818		self.rb_mut().get_mut(row, col)
1819	}
1820
1821	/// see [`SparseRowMatRef::triplet_iter`]
1822	#[inline]
1823	pub fn triplet_iter(&self) -> impl '_ + Iterator<Item = Triplet<Idx<Rows>, Idx<Cols>, &'_ T>> {
1824		self.rb().triplet_iter()
1825	}
1826}
1827
1828impl<'a, Rows: Shape, Cols: Shape, I: Index, T> core::ops::Deref for SparseRowMatRef<'a, I, T, Rows, Cols> {
1829	type Target = SymbolicSparseRowMatRef<'a, I, Rows, Cols>;
1830
1831	#[inline]
1832	fn deref(&self) -> &Self::Target {
1833		&self.0.symbolic
1834	}
1835}
1836
1837impl<'a, Rows: Shape, Cols: Shape, I: Index, T> core::ops::Deref for SparseRowMatMut<'a, I, T, Rows, Cols> {
1838	type Target = SymbolicSparseRowMatRef<'a, I, Rows, Cols>;
1839
1840	#[inline]
1841	fn deref(&self) -> &Self::Target {
1842		&self.0.symbolic
1843	}
1844}
1845
1846impl<Rows: Shape, Cols: Shape, I: Index, T> core::ops::Deref for SparseRowMat<I, T, Rows, Cols> {
1847	type Target = SymbolicSparseRowMat<I, Rows, Cols>;
1848
1849	#[inline]
1850	fn deref(&self) -> &Self::Target {
1851		&self.0.symbolic
1852	}
1853}
1854
1855impl<Rows: Shape, Cols: Shape, I: Index> fmt::Debug for symbolic::Ref<'_, I, Rows, Cols> {
1856	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1857		fn imp<'ROWS, 'COLS, I: Index>(mat: SymbolicSparseRowMatRef<'_, I, Dim<'ROWS>, Dim<'COLS>>, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1858			struct Entries<'a, 'ROWS, 'COLS, I>(SymbolicSparseRowMatRef<'a, I, Dim<'ROWS>, Dim<'COLS>>);
1859
1860			impl<'ROWS, 'COLS, I: Index> fmt::Debug for Entries<'_, 'ROWS, 'COLS, I> {
1861				fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1862					let mat = self.0;
1863
1864					f.debug_list()
1865						.entries(
1866							mat.nrows()
1867								.indices()
1868								.flat_map(|row| mat.col_idx_of_row(row).map(move |col| Pair { row, col })),
1869						)
1870						.finish()
1871				}
1872			}
1873
1874			f.debug_struct("SymbolicSparseRowMat")
1875				.field("nrows", &mat.nrows)
1876				.field("ncols", &mat.ncols)
1877				.field("entries", &Entries(mat))
1878				.finish()
1879		}
1880		let this = symbolic::generic::SymbolicSparseRowMat::from_inner_ref(self);
1881		with_dim!(ROWS, this.nrows().unbound());
1882		with_dim!(COLS, this.ncols().unbound());
1883
1884		imp(this.as_shape(ROWS, COLS), f)
1885	}
1886}
1887
1888impl<Rows: Shape, Cols: Shape, I: Index> fmt::Debug for symbolic::Own<I, Rows, Cols> {
1889	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1890		self.rb().fmt(f)
1891	}
1892}
1893
1894impl<Rows: Shape, Cols: Shape, I: Index, T: fmt::Debug> fmt::Debug for SparseRowMatRef<'_, I, T, Rows, Cols> {
1895	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1896		fn imp<'ROWS, 'COLS, I: Index, T: fmt::Debug>(
1897			mat: SparseRowMatRef<'_, I, T, Dim<'ROWS>, Dim<'COLS>>,
1898			f: &mut fmt::Formatter<'_>,
1899		) -> fmt::Result {
1900			struct Entries<'a, 'ROWS, 'COLS, I, T>(SparseRowMatRef<'a, I, T, Dim<'ROWS>, Dim<'COLS>>);
1901
1902			impl<'ROWS, 'COLS, I: Index, T: fmt::Debug> fmt::Debug for Entries<'_, 'ROWS, 'COLS, I, T> {
1903				fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1904					let mat = self.0;
1905
1906					f.debug_list()
1907						.entries(mat.nrows().indices().flat_map(|row| {
1908							let col_idx = mat.col_idx_of_row(row);
1909							let val = mat.val_of_row(row);
1910
1911							iter::zip(col_idx, val).map(move |(col, val)| Triplet {
1912								row,
1913								col,
1914								val: crate::hacks::hijack_debug(val),
1915							})
1916						}))
1917						.finish()
1918				}
1919			}
1920
1921			f.debug_struct("SparseRowMat")
1922				.field("nrows", &mat.nrows)
1923				.field("ncols", &mat.ncols)
1924				.field("entries", &Entries(mat))
1925				.finish()
1926		}
1927
1928		with_dim!(ROWS, self.nrows().unbound());
1929		with_dim!(COLS, self.ncols().unbound());
1930
1931		imp(self.as_shape(ROWS, COLS), f)
1932	}
1933}
1934
1935impl<Rows: Shape, Cols: Shape, I: Index, T: fmt::Debug> fmt::Debug for SparseRowMatMut<'_, I, T, Rows, Cols> {
1936	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1937		self.rb().fmt(f)
1938	}
1939}
1940
1941impl<Rows: Shape, Cols: Shape, I: Index, T: fmt::Debug> fmt::Debug for SparseRowMat<I, T, Rows, Cols> {
1942	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1943		self.rb().fmt(f)
1944	}
1945}