use alloc::vec;
use alloc::vec::Vec;
use crate::scalar::Scalar;
use super::sorted_csr::SortedCsrMatrix;
use super::{CooMatrix, CscMatrix, CsrMatrix};
pub fn coo_to_csr<T: Scalar>(coo: CooMatrix<T>) -> SortedCsrMatrix<T> {
let (rows, cols, coo_row, coo_col, coo_val) = coo.into_raw_parts();
let nnz_in = coo_val.len();
let mut order: Vec<usize> = (0..nnz_in).collect();
order.sort_by_key(|&i| (coo_row[i], coo_col[i]));
let mut out_row: Vec<usize> = Vec::new();
let mut out_col: Vec<usize> = Vec::new();
let mut out_val: Vec<T> = Vec::new();
for &i in &order {
let r = coo_row[i];
let c = coo_col[i];
let v = coo_val[i];
let is_dup = out_row.last().copied() == Some(r) && out_col.last().copied() == Some(c);
if is_dup {
if let Some(last) = out_val.last_mut() {
*last = last.add(v);
}
} else {
out_row.push(r);
out_col.push(c);
out_val.push(v);
}
}
let mut row_ptr = vec![0usize; rows + 1];
for &r in &out_row {
row_ptr[r + 1] += 1;
}
for i in 1..=rows {
row_ptr[i] += row_ptr[i - 1];
}
SortedCsrMatrix::from_sorted_unchecked(CsrMatrix::new_raw(
rows, cols, row_ptr, out_col, out_val,
))
}
pub fn csr_to_coo<T>(csr: CsrMatrix<T>) -> CooMatrix<T> {
let (rows, cols, row_ptr, col_indices, values) = csr.into_raw_parts();
let nnz = values.len();
let mut row_indices = Vec::with_capacity(nnz);
for r in 0..rows {
let count = row_ptr[r + 1] - row_ptr[r];
for _ in 0..count {
row_indices.push(r);
}
}
CooMatrix::new_raw(rows, cols, row_indices, col_indices, values)
}
pub fn csr_to_csc<T: Scalar>(m: CsrMatrix<T>) -> CscMatrix<T> {
let (rows, cols, row_ptr, col_indices, values) = m.into_raw_parts();
let nnz = values.len();
let mut triples: Vec<(usize, usize, T)> = Vec::with_capacity(nnz);
for r in 0..rows {
for k in row_ptr[r]..row_ptr[r + 1] {
triples.push((col_indices[k], r, values[k]));
}
}
triples.sort_by_key(|&(c, r, _)| (c, r));
let mut col_ptr = vec![0usize; cols + 1];
for &(c, _, _) in &triples {
col_ptr[c + 1] += 1;
}
for i in 1..=cols {
col_ptr[i] += col_ptr[i - 1];
}
let mut out_row: Vec<usize> = Vec::with_capacity(nnz);
let mut out_val: Vec<T> = Vec::with_capacity(nnz);
for (_, r, v) in triples {
out_row.push(r);
out_val.push(v);
}
CscMatrix::new_raw(rows, cols, col_ptr, out_row, out_val)
}
pub fn csc_to_csr<T: Scalar>(m: CscMatrix<T>) -> CsrMatrix<T> {
let (rows, cols, col_ptr, row_indices, values) = m.into_raw_parts();
let nnz = values.len();
let mut triples: Vec<(usize, usize, T)> = Vec::with_capacity(nnz);
for c in 0..cols {
for k in col_ptr[c]..col_ptr[c + 1] {
triples.push((row_indices[k], c, values[k]));
}
}
triples.sort_by_key(|&(r, c, _)| (r, c));
let mut row_ptr = vec![0usize; rows + 1];
for &(r, _, _) in &triples {
row_ptr[r + 1] += 1;
}
for i in 1..=rows {
row_ptr[i] += row_ptr[i - 1];
}
let mut out_col: Vec<usize> = Vec::with_capacity(nnz);
let mut out_val: Vec<T> = Vec::with_capacity(nnz);
for (_, c, v) in triples {
out_col.push(c);
out_val.push(v);
}
CsrMatrix::new_raw(rows, cols, row_ptr, out_col, out_val)
}