1use super::*;
2use crate::internal_prelude::*;
3use crate::{Idx, MaybeIdx, assert, debug_assert};
4use core::ops::Range;
5use core::{fmt, iter};
6
7pub mod symbolic {
9 pub mod generic {
11 use core::fmt::Debug;
12 use reborrow::*;
13
14 #[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 #[inline(always)]
29 pub fn from_inner_ref(inner: &Inner) -> &Self {
30 unsafe { &*(inner as *const Inner as *const Self) }
31 }
32
33 #[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 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 #[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
104pub mod numeric {
106 pub mod generic {
108 use core::fmt::Debug;
109 use reborrow::*;
110
111 #[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 #[inline(always)]
126 pub fn from_inner_ref(inner: &Inner) -> &Self {
127 unsafe { &*(inner as *const Inner as *const Self) }
128 }
129
130 #[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 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 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 #[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
185pub type SymbolicSparseColMatRef<'a, I, Rows = usize, Cols = usize> = symbolic::generic::SymbolicSparseColMat<symbolic::Ref<'a, I, Rows, Cols>>;
210
211pub type SymbolicSparseColMat<I, Rows = usize, Cols = usize> = symbolic::generic::SymbolicSparseColMat<symbolic::Own<I, Rows, Cols>>;
216
217pub type SparseColMatRef<'a, I, T, Rows = usize, Cols = usize> = numeric::generic::SparseColMat<numeric::Ref<'a, I, T, Rows, Cols>>;
221
222pub type SparseColMatMut<'a, I, T, Rows = usize, Cols = usize> = numeric::generic::SparseColMat<numeric::Mut<'a, I, T, Rows, Cols>>;
226
227pub 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 #[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 #[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 #[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 #[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 #[inline]
546 pub fn nrows(&self) -> Rows {
547 self.nrows
548 }
549
550 #[inline]
552 pub fn ncols(&self) -> Cols {
553 self.ncols
554 }
555
556 #[inline]
558 pub fn shape(&self) -> (Rows, Cols) {
559 (self.nrows, self.ncols)
560 }
561
562 #[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 #[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 #[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 #[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 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 #[inline]
618 pub fn col_ptr(&self) -> &'a [I] {
619 self.col_ptr
620 }
621
622 #[inline]
624 pub fn col_nnz(&self) -> Option<&'a [I]> {
625 self.col_nnz
626 }
627
628 #[inline]
630 pub fn row_idx(&self) -> &'a [I] {
631 self.row_idx
632 }
633
634 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 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 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 pub fn nrows(&self) -> Rows {
825 self.nrows
826 }
827
828 #[inline]
829 pub fn ncols(&self) -> Cols {
831 self.ncols
832 }
833
834 #[inline]
835 pub fn shape(&self) -> (Rows, Cols) {
837 (self.nrows, self.ncols)
838 }
839
840 #[inline]
841 pub fn transpose(&self) -> SymbolicSparseRowMatRef<'_, I, Cols, Rows> {
843 self.rb().transpose()
844 }
845
846 #[inline]
847 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 pub fn to_owned(&self) -> Result<SymbolicSparseColMat<I, Rows, Cols>, FaerError> {
863 self.rb().to_owned()
864 }
865
866 #[inline]
867 pub fn to_row_major(&self) -> Result<SymbolicSparseRowMat<I, Rows, Cols>, FaerError> {
869 self.rb().to_row_major()
870 }
871
872 #[inline]
873 pub fn compute_nnz(&self) -> usize {
875 self.rb().compute_nnz()
876 }
877
878 #[inline]
879 pub fn col_ptr(&self) -> &'_ [I] {
881 &self.col_ptr
882 }
883
884 #[inline]
885 pub fn col_nnz(&self) -> Option<&'_ [I]> {
887 self.col_nnz.as_deref()
888 }
889
890 #[inline]
891 pub fn row_idx(&self) -> &'_ [I] {
893 &self.row_idx
894 }
895
896 #[inline]
897 #[track_caller]
898 pub fn col_range(&self, j: Idx<Cols>) -> Range<usize> {
900 self.rb().col_range(j)
901 }
902
903 #[inline]
904 #[track_caller]
905 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 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 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 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 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 pub fn as_dyn(&self) -> SymbolicSparseColMatRef<'_, I> {
950 self.rb().as_dyn()
951 }
952
953 #[inline]
954 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 #[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 #[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 #[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 #[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 #[inline]
1158 pub fn parts(self) -> (SymbolicSparseColMatRef<'a, I, Rows, Cols>, &'a [T]) {
1159 (self.0.symbolic, self.0.val)
1160 }
1161
1162 #[inline]
1164 pub fn symbolic(&self) -> SymbolicSparseColMatRef<'a, I, Rows, Cols> {
1165 self.0.symbolic
1166 }
1167
1168 #[inline]
1170 pub fn val(self) -> &'a [T] {
1171 self.0.val
1172 }
1173
1174 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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 #[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(); 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 #[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 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 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 pub fn parts(self) -> (SymbolicSparseColMatRef<'a, I, Rows, Cols>, &'a [T]) {
1393 (self.0.symbolic, self.0.val)
1394 }
1395
1396 #[inline]
1397 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 pub fn symbolic(&self) -> SymbolicSparseColMatRef<'a, I, Rows, Cols> {
1405 self.0.symbolic
1406 }
1407
1408 #[inline]
1409 pub fn val(self) -> &'a [T] {
1411 self.0.val
1412 }
1413
1414 #[inline]
1415 pub fn val_mut(self) -> &'a mut [T] {
1417 self.0.val
1418 }
1419
1420 #[inline]
1421 #[track_caller]
1422 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 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 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 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 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 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 #[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 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 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 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 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 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 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 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 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 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 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 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 pub fn to_dense(&self) -> Mat<T::Canonical, Rows, Cols>
1628 where
1629 T: Conjugate,
1630 {
1631 self.rb().to_dense()
1632 }
1633
1634 #[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 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 pub fn parts(&self) -> (SymbolicSparseColMatRef<'_, I, Rows, Cols>, &'_ [T]) {
1659 (self.0.symbolic.rb(), &self.0.val)
1660 }
1661
1662 #[inline]
1663 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 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 pub fn symbolic(&self) -> SymbolicSparseColMatRef<'_, I, Rows, Cols> {
1677 self.0.symbolic.rb()
1678 }
1679
1680 #[inline]
1681 pub fn val(&self) -> &'_ [T] {
1683 &self.0.val
1684 }
1685
1686 #[inline]
1687 pub fn val_mut(&mut self) -> &'_ mut [T] {
1689 &mut self.0.val
1690 }
1691
1692 #[inline]
1693 #[track_caller]
1694 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 #[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 #[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 #[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 #[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 #[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 #[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}