Skip to main content

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