#![forbid(unsafe_code)]
#![deny(missing_docs)]
mod stats;
pub use feral_ordering_core::{CscPattern, OrderingError, OrderingStats, CONTRACT_VERSION};
pub use stats::AmfStats;
use feral_ordering_core::quotient_graph::{order, MinFill, WorkspaceOptions};
use std::time::Instant;
#[derive(Debug, Clone)]
pub struct AmfOptions {
pub dense_alpha: f64,
}
impl Default for AmfOptions {
fn default() -> Self {
Self { dense_alpha: 10.0 }
}
}
pub fn amf_order(pattern: &CscPattern<'_>) -> Result<Vec<i32>, OrderingError> {
amf_order_opts(pattern, &AmfOptions::default()).map(|(perm, _)| perm)
}
pub fn amf_order_with_stats(
pattern: &CscPattern<'_>,
) -> Result<(Vec<i32>, AmfStats), OrderingError> {
amf_order_opts(pattern, &AmfOptions::default())
}
pub fn amf_order_opts(
pattern: &CscPattern<'_>,
opts: &AmfOptions,
) -> Result<(Vec<i32>, AmfStats), OrderingError> {
amf_order_full(pattern, opts).map(|(perm, _, amf_stats)| (perm, amf_stats))
}
pub fn amf_order_full(
pattern: &CscPattern<'_>,
opts: &AmfOptions,
) -> Result<(Vec<i32>, OrderingStats, AmfStats), OrderingError> {
let t0 = Instant::now();
let ws_opts = WorkspaceOptions {
dense_alpha: opts.dense_alpha,
};
let (perm, diag) = order::<MinFill>(pattern, &ws_opts, true)?;
let amf_stats = AmfStats {
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, amf_stats))
}