Skip to main content

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