ruvector_solver/error.rs
1//! Error types for the solver crate.
2//!
3//! Provides structured error variants for convergence failures, numerical
4//! instabilities, budget overruns, and invalid inputs. All errors implement
5//! `std::error::Error` via `thiserror`.
6
7use std::time::Duration;
8
9use crate::types::Algorithm;
10
11/// Primary error type for solver operations.
12#[derive(Debug, thiserror::Error)]
13pub enum SolverError {
14 /// The iterative solver did not converge within the allowed iteration budget.
15 #[error(
16 "solver did not converge after {iterations} iterations (residual={residual:.2e}, tol={tolerance:.2e})"
17 )]
18 NonConvergence {
19 /// Number of iterations completed before the budget was exhausted.
20 iterations: usize,
21 /// Final residual norm at termination.
22 residual: f64,
23 /// Target tolerance that was not reached.
24 tolerance: f64,
25 },
26
27 /// A numerical instability was detected (NaN, Inf, or loss of precision).
28 #[error("numerical instability at iteration {iteration}: {detail}")]
29 NumericalInstability {
30 /// Iteration at which the instability was detected.
31 iteration: usize,
32 /// Human-readable explanation.
33 detail: String,
34 },
35
36 /// The compute budget (wall-time, iterations, or memory) was exhausted.
37 #[error("compute budget exhausted: {reason}")]
38 BudgetExhausted {
39 /// Which budget limit was hit.
40 reason: String,
41 /// Wall-clock time elapsed before the budget was hit.
42 elapsed: Duration,
43 },
44
45 /// The caller supplied invalid input (dimensions, parameters, etc.).
46 #[error("invalid input: {0}")]
47 InvalidInput(#[from] ValidationError),
48
49 /// The matrix spectral radius exceeds the threshold required by the algorithm.
50 #[error(
51 "spectral radius {spectral_radius:.4} exceeds limit {limit:.4} for algorithm {algorithm}"
52 )]
53 SpectralRadiusExceeded {
54 /// Estimated spectral radius of the iteration matrix.
55 spectral_radius: f64,
56 /// Maximum spectral radius the algorithm tolerates.
57 limit: f64,
58 /// Algorithm that detected the violation.
59 algorithm: Algorithm,
60 },
61
62 /// A backend-specific error (e.g. nalgebra or BLAS).
63 #[error("backend error: {0}")]
64 BackendError(String),
65}
66
67/// Validation errors for solver inputs.
68///
69/// These are raised eagerly before any computation begins so that callers get
70/// clear diagnostics rather than mysterious numerical failures.
71#[derive(Debug, thiserror::Error)]
72pub enum ValidationError {
73 /// Matrix dimensions are inconsistent (e.g. row_ptrs length vs rows).
74 #[error("dimension mismatch: {0}")]
75 DimensionMismatch(String),
76
77 /// A value is NaN or infinite where a finite number is required.
78 #[error("non-finite value detected: {0}")]
79 NonFiniteValue(String),
80
81 /// A column index is out of bounds for the declared number of columns.
82 #[error("column index {index} out of bounds for {cols} columns (row {row})")]
83 IndexOutOfBounds {
84 /// Offending column index.
85 index: u32,
86 /// Row containing the offending entry.
87 row: usize,
88 /// Declared column count.
89 cols: usize,
90 },
91
92 /// The `row_ptrs` array is not monotonically non-decreasing.
93 #[error("row_ptrs is not monotonically non-decreasing at position {position}")]
94 NonMonotonicRowPtrs {
95 /// Position in `row_ptrs` where the violation was detected.
96 position: usize,
97 },
98
99 /// A parameter is outside its valid range.
100 #[error("parameter out of range: {name} = {value} (expected {expected})")]
101 ParameterOutOfRange {
102 /// Name of the parameter.
103 name: String,
104 /// The invalid value (as a string for flexibility).
105 value: String,
106 /// Human-readable description of the valid range.
107 expected: String,
108 },
109
110 /// Matrix size exceeds the implementation limit.
111 #[error("matrix size {rows}x{cols} exceeds maximum supported {max_dim}x{max_dim}")]
112 MatrixTooLarge {
113 /// Number of rows.
114 rows: usize,
115 /// Number of columns.
116 cols: usize,
117 /// Maximum supported dimension.
118 max_dim: usize,
119 },
120}