use std::fmt;
use crate::Row;
#[derive(Clone, Debug, PartialEq)]
pub enum SparseError {
Dimension {
what: &'static str,
expected: usize,
found: usize,
},
IndexOutOfRange {
what: &'static str,
index: usize,
bound: usize,
},
InvalidValue {
what: &'static str,
index: usize,
value: f64,
},
TooLarge {
what: &'static str,
value: usize,
},
Malformed(String),
}
impl fmt::Display for SparseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::IndexOutOfRange { what, index, bound } => {
write!(f, "{what} {index} out of bounds (must be < {bound})")
}
Self::Dimension {
what,
expected,
found,
} => {
write!(f, "{what} has length {found}, expected {expected}")
}
Self::InvalidValue { what, index, value } => {
write!(f, "invalid {what} at position {index}: {value}")
}
Self::TooLarge { what, value } => {
write!(f, "{what} = {value} exceeds the u32 index space")
}
Self::Malformed(msg) => write!(f, "invariant violated: {msg}"),
}
}
}
impl std::error::Error for SparseError {}
#[derive(Clone, Debug, PartialEq)]
pub enum LuError {
Singular {
rank_deficiency: usize,
cols: Vec<usize>,
rows: Vec<Row>,
},
Structure(SparseError),
NoSpike,
NotFactorized,
}
impl fmt::Display for LuError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Singular {
rank_deficiency,
cols,
..
} => write!(
f,
"singular basis: rank deficiency {rank_deficiency} (positions {cols:?})"
),
Self::Structure(e) => write!(f, "invalid basis: {e}"),
Self::NoSpike => write!(f, "update called without a spike from ftran_for_update"),
Self::NotFactorized => write!(f, "the factor holds no valid factorization"),
}
}
}
impl std::error::Error for LuError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Structure(e) => Some(e),
_ => None,
}
}
}
impl From<SparseError> for LuError {
fn from(e: SparseError) -> Self {
Self::Structure(e)
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum KktError {
NotSymmetric,
ZeroPivot {
position: usize,
},
NotFinite {
position: usize,
},
WrongInertia {
found: crate::Inertia,
expected: crate::Inertia,
},
Structure(SparseError),
Backend(&'static str),
}
impl fmt::Display for KktError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotSymmetric => write!(f, "the KKT pattern is not square and symmetric"),
Self::ZeroPivot { position } => write!(f, "zero pivot at row {position}"),
Self::NotFinite { position } => {
write!(f, "non-finite factor (overflow) at row {position}")
}
Self::WrongInertia { found, expected } => write!(
f,
"wrong inertia: found ({}, {}, {}), expected ({}, {}, {})",
found.positive,
found.negative,
found.zero,
expected.positive,
expected.negative,
expected.zero
),
Self::Structure(e) => write!(f, "invalid KKT matrix: {e}"),
Self::Backend(what) => write!(f, "KKT backend failure: {what}"),
}
}
}
impl std::error::Error for KktError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Structure(e) => Some(e),
_ => None,
}
}
}
impl From<SparseError> for KktError {
fn from(e: SparseError) -> Self {
Self::Structure(e)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum DenseError {
NotPositiveDefinite {
position: usize,
},
Dimension,
}
impl fmt::Display for DenseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NotPositiveDefinite { position } => {
write!(f, "block not positive definite at column {position}")
}
Self::Dimension => write!(f, "block dimensions do not agree"),
}
}
}
impl std::error::Error for DenseError {}