pub fn build_symmetric_lists(n: usize, col_ptr: &[i64], row_idx: &[i64]) -> Vec<Vec<i64>> {
let mut lists: Vec<Vec<i64>> = vec![Vec::new(); n];
let mut tp: Vec<i64> = col_ptr[..n].to_vec();
for k in 0..n {
let p2 = col_ptr[k + 1];
let mut p = col_ptr[k];
loop {
if p >= p2 {
break;
}
let j = row_idx[p as usize];
if j < k as i64 {
lists[j as usize].push(k as i64);
lists[k].push(j);
p += 1;
} else if j == k as i64 {
p += 1;
break; } else {
break; }
let pj2 = col_ptr[j as usize + 1];
let mut pj = tp[j as usize];
loop {
if pj >= pj2 {
break;
}
let i = row_idx[pj as usize];
if i < k as i64 {
lists[i as usize].push(j);
lists[j as usize].push(i);
pj += 1;
} else if i == k as i64 {
pj += 1;
break; } else {
break; }
}
tp[j as usize] = pj;
}
tp[k] = p;
}
for j in 0..n {
let pj2 = col_ptr[j + 1];
let mut pj = tp[j];
while pj < pj2 {
let i = row_idx[pj as usize];
lists[i as usize].push(j as i64);
lists[j].push(i);
pj += 1;
}
}
lists
}
pub fn validate(n_row: usize, n_col: usize, col_ptr: &[i64], row_idx: &[i64]) -> bool {
if col_ptr.is_empty() || col_ptr[0] != 0 {
return false;
}
let nz = col_ptr[n_col];
if nz < 0 {
return false;
}
for j in 0..n_col {
let (p1, p2) = (col_ptr[j], col_ptr[j + 1]);
if p1 > p2 {
return false;
}
let mut ilast: i64 = -1;
for &i in &row_idx[p1 as usize..p2 as usize] {
if i < 0 || i as usize >= n_row {
return false;
}
if i <= ilast {
return false; }
ilast = i;
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn validate_accepts_sorted_no_dup() {
let col_ptr = [0, 1, 2, 3];
let row_idx = [0, 1, 2];
assert!(validate(3, 3, &col_ptr, &row_idx));
}
#[test]
fn validate_rejects_unsorted() {
let col_ptr = [0, 2];
let row_idx = [1, 0]; assert!(!validate(2, 1, &col_ptr, &row_idx));
}
#[test]
fn validate_rejects_duplicate() {
let col_ptr = [0, 2];
let row_idx = [0, 0]; assert!(!validate(2, 1, &col_ptr, &row_idx));
}
#[test]
fn build_symmetric_lists_diagonal_matrix_is_empty() {
let col_ptr = [0, 1, 2, 3];
let row_idx = [0, 1, 2];
let lists = build_symmetric_lists(3, &col_ptr, &row_idx);
assert!(lists.iter().all(|l| l.is_empty()), "diagonal-only matrix has no off-diagonal A+A' entries");
}
#[test]
fn build_symmetric_lists_is_symmetric() {
let col_ptr = [0, 1, 1];
let row_idx = [1];
let lists = build_symmetric_lists(2, &col_ptr, &row_idx);
assert_eq!(lists[0], vec![1]);
assert_eq!(lists[1], vec![0]);
}
}