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