#![forbid(unsafe_code)]
#![deny(missing_docs)]
mod stats;
pub use feral_ordering_core::{CscPattern, OrderingError, OrderingStats, CONTRACT_VERSION};
pub use stats::AmdStats;
use feral_ordering_core::quotient_graph::{
finalize_permutation, order, run_elimination, MinDegree, Workspace, WorkspaceOptions,
};
use std::time::Instant;
#[derive(Debug, Clone)]
pub struct AmdOptions {
pub aggressive: bool,
pub dense_alpha: f64,
}
impl Default for AmdOptions {
fn default() -> Self {
Self {
aggressive: true,
dense_alpha: 10.0,
}
}
}
pub fn amd_order(pattern: &CscPattern<'_>) -> Result<Vec<i32>, OrderingError> {
amd_order_opts(pattern, &AmdOptions::default()).map(|(perm, _)| perm)
}
pub fn amd_order_with_stats(
pattern: &CscPattern<'_>,
) -> Result<(Vec<i32>, AmdStats), OrderingError> {
amd_order_opts(pattern, &AmdOptions::default())
}
pub fn amd_order_opts(
pattern: &CscPattern<'_>,
opts: &AmdOptions,
) -> Result<(Vec<i32>, AmdStats), OrderingError> {
amd_order_full(pattern, opts).map(|(perm, _, amd_stats)| (perm, amd_stats))
}
pub fn amd_order_full(
pattern: &CscPattern<'_>,
opts: &AmdOptions,
) -> Result<(Vec<i32>, OrderingStats, AmdStats), OrderingError> {
let t0 = Instant::now();
let ws_opts = WorkspaceOptions {
dense_alpha: opts.dense_alpha,
};
let (perm, diag) = order::<MinDegree>(pattern, &ws_opts, opts.aggressive)?;
let amd_stats = AmdStats {
ncmpa: diag.ncmpa,
n_clear_flag: 0,
n_mass_elim: diag.n_mass_elim,
n_supervar_merge: diag.n_supervar_merge,
n_dense_deferred: diag.ndense.max(0) as u32,
ndiv: diag.flops.ndiv.max(0.0) as u64,
nms_lu: diag.flops.nms_lu.max(0.0) as u64,
nms_ldl: diag.flops.nms_ldl.max(0.0) as u64,
};
let ordering_stats = OrderingStats {
time_us: t0.elapsed().as_micros() as u64,
fill_estimate: None,
flop_estimate: None,
};
Ok((perm, ordering_stats, amd_stats))
}
#[derive(Debug, Clone, Copy, Default)]
pub struct AmdSubstages {
pub workspace_new_us: u64,
pub run_elimination_us: u64,
pub finalize_permutation_us: u64,
}
pub fn amd_order_substages(
pattern: &CscPattern<'_>,
opts: &AmdOptions,
) -> Result<(Vec<i32>, AmdSubstages), OrderingError> {
let t = Instant::now();
let ws_opts = WorkspaceOptions {
dense_alpha: opts.dense_alpha,
};
let mut ws = Workspace::new(pattern, &ws_opts)?;
let workspace_new_us = t.elapsed().as_micros() as u64;
let t = Instant::now();
let _flops = run_elimination(&mut ws, opts.aggressive)?;
let run_elimination_us = t.elapsed().as_micros() as u64;
let t = Instant::now();
let perm = finalize_permutation(&mut ws);
let finalize_permutation_us = t.elapsed().as_micros() as u64;
Ok((
perm,
AmdSubstages {
workspace_new_us,
run_elimination_us,
finalize_permutation_us,
},
))
}