#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum LinalgError {
Singular,
NotPositiveDefinite,
Underdetermined,
NonFinite,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum DiffError {
OrderZero,
OrderUnsupported,
StepSizeZero,
IndexOutOfRange,
EmptyFunctionSet,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum IntegrateError {
IterationsZero,
LimitsIllDefined,
QuadratureOrderOutOfRange,
StepSizeTooSmall,
DidNotConverge {
steps: usize,
},
NonFinite,
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum SolveError {
DidNotConverge {
iters: usize,
residual: f64,
},
NonFinite,
InvalidBracket,
Linalg(LinalgError),
Diff(DiffError),
}
#[derive(Debug, Clone, Copy, PartialEq)]
#[non_exhaustive]
pub enum CalcError {
Linalg(LinalgError),
Solve(SolveError),
Integrate(IntegrateError),
Differentiate(DiffError),
}
impl From<LinalgError> for SolveError {
fn from(e: LinalgError) -> Self {
SolveError::Linalg(e)
}
}
impl From<DiffError> for SolveError {
fn from(e: DiffError) -> Self {
SolveError::Diff(e)
}
}
impl From<LinalgError> for CalcError {
fn from(e: LinalgError) -> Self {
CalcError::Linalg(e)
}
}
impl From<DiffError> for CalcError {
fn from(e: DiffError) -> Self {
CalcError::Differentiate(e)
}
}
impl From<IntegrateError> for CalcError {
fn from(e: IntegrateError) -> Self {
CalcError::Integrate(e)
}
}
impl From<SolveError> for CalcError {
fn from(e: SolveError) -> Self {
CalcError::Solve(e)
}
}
impl core::fmt::Display for LinalgError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
LinalgError::Singular => "matrix is singular or rank-deficient",
LinalgError::NotPositiveDefinite => "matrix is not positive definite",
LinalgError::Underdetermined => "system is underdetermined (M < N)",
LinalgError::NonFinite => "matrix contained a non-finite value",
})
}
}
impl core::fmt::Display for DiffError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str(match self {
DiffError::OrderZero => "derivative order cannot be zero",
DiffError::OrderUnsupported => "derivative order is not supported",
DiffError::StepSizeZero => "step size cannot be zero",
DiffError::IndexOutOfRange => "variable index out of range",
DiffError::EmptyFunctionSet => "function set cannot be empty",
})
}
}
impl core::fmt::Display for IntegrateError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
IntegrateError::IterationsZero => f.write_str("number of iterations cannot be zero"),
IntegrateError::LimitsIllDefined => {
f.write_str("lower limit must be strictly less than upper limit")
}
IntegrateError::QuadratureOrderOutOfRange => {
f.write_str("quadrature order is out of supported range")
}
IntegrateError::StepSizeTooSmall => {
f.write_str("adaptive step size fell below the minimum")
}
IntegrateError::DidNotConverge { steps } => {
write!(f, "integrator did not converge within {steps} steps")
}
IntegrateError::NonFinite => {
f.write_str("integrand or state contained a non-finite value")
}
}
}
}
impl core::fmt::Display for SolveError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
SolveError::DidNotConverge { iters, residual } => {
write!(
f,
"solver did not converge after {iters} iterations (residual {residual})"
)
}
SolveError::NonFinite => {
f.write_str("residual or Jacobian contained a non-finite value")
}
SolveError::InvalidBracket => {
f.write_str("bracket endpoints must enclose a sign change")
}
SolveError::Linalg(e) => write!(f, "{e}"),
SolveError::Diff(e) => write!(f, "{e}"),
}
}
}
impl core::fmt::Display for CalcError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
CalcError::Linalg(e) => write!(f, "{e}"),
CalcError::Solve(e) => write!(f, "{e}"),
CalcError::Integrate(e) => write!(f, "{e}"),
CalcError::Differentiate(e) => write!(f, "{e}"),
}
}
}
impl core::error::Error for LinalgError {}
impl core::error::Error for DiffError {}
impl core::error::Error for IntegrateError {}
impl core::error::Error for SolveError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
SolveError::Linalg(e) => Some(e),
SolveError::Diff(e) => Some(e),
_ => None,
}
}
}
impl core::error::Error for CalcError {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
CalcError::Linalg(e) => Some(e),
CalcError::Solve(e) => Some(e),
CalcError::Integrate(e) => Some(e),
CalcError::Differentiate(e) => Some(e),
}
}
}