use faer::sparse::SymbolicSparseColMatRef;
use faer_traits::Index;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(crate) enum DiagError {
NonSquare { nrows: usize, ncols: usize },
MissingDiagonal { col: usize },
UnsortedRowIndices { col: usize },
}
pub(crate) fn validated_diag_pos<I: Index>(
pattern: SymbolicSparseColMatRef<'_, I>,
) -> Result<Vec<usize>, DiagError> {
let nrows = pattern.nrows();
let ncols = pattern.ncols();
if nrows != ncols {
return Err(DiagError::NonSquare { nrows, ncols });
}
let n = nrows;
let mut diag_pos = Vec::with_capacity(n);
for j in 0..n {
let row_idx = pattern.row_idx_of_col_raw(j);
let mut diag_idx: Option<usize> = None;
let mut prev: Option<usize> = None;
for (k, raw) in row_idx.iter().enumerate() {
let r = raw.zx();
if let Some(p) = prev
&& r <= p
{
return Err(DiagError::UnsortedRowIndices { col: j });
}
if r == j {
diag_idx = Some(k);
}
prev = Some(r);
}
diag_pos.push(diag_idx.ok_or(DiagError::MissingDiagonal { col: j })?);
}
Ok(diag_pos)
}