scirs2_special/error.rs
1//! Error types for the SciRS2 special functions module
2//!
3//! This module provides comprehensive error handling for special function computations,
4//! with detailed error types that help users understand what went wrong and how to fix it.
5//!
6//! ## Error Categories
7//!
8//! The error types are organized into several categories:
9//!
10//! - **Mathematical Errors**: Domain errors, convergence failures, overflow
11//! - **Input Validation**: Value errors, parameter validation failures
12//! - **Implementation Status**: Not implemented functionality
13//! - **System Errors**: GPU unavailability, IO failures
14//! - **Core Integration**: Errors from scirs2-core dependencies
15//!
16//! ## Usage Examples
17//!
18//! ```rust,ignore
19//! use scirs2_special::{gamma, SpecialError, SpecialResult};
20//!
21//! // Function that can return different error types
22//! fn safe_gamma(x: f64) -> SpecialResult<f64> {
23//! if x <= 0.0 && x.fract() == 0.0 {
24//! return Err(SpecialError::DomainError(
25//! format!("Gamma function undefined for non-positive integer: {x}")
26//! ));
27//! }
28//!
29//! let result = gamma(x);
30//! if !result.is_finite() {
31//! return Err(SpecialError::OverflowError(
32//! format!("Gamma({x}) resulted in overflow")
33//! ));
34//! }
35//!
36//! Ok(result)
37//! }
38//! ```
39
40use scirs2_core::error::CoreError;
41use thiserror::Error;
42
43/// Error types for special function computations
44///
45/// This enum provides detailed error information for different failure modes
46/// that can occur during special function computations. Each variant includes
47/// contextual information to help users understand and resolve issues.
48#[derive(Error, Debug)]
49pub enum SpecialError {
50 /// Generic computation error for unexpected failures
51 ///
52 /// Used when a computation fails for reasons not covered by more specific error types.
53 /// Often indicates internal algorithmic issues or unexpected edge cases.
54 ///
55 /// # Examples
56 /// - Numerical integration failure
57 /// - Memory allocation failure during computation
58 /// - Internal algorithm assertion failure
59 #[error("Computation error: {0}")]
60 ComputationError(String),
61
62 /// Mathematical domain error - input outside the valid mathematical domain
63 ///
64 /// Thrown when function arguments are outside the mathematical domain where
65 /// the function is defined. This follows mathematical conventions strictly.
66 ///
67 /// # Examples
68 /// - `gamma(-1)` - gamma function undefined at negative integers
69 /// - `sqrt(-1)` for real-valued square root
70 /// - `log(0)` or `log(negative)` for real logarithm
71 /// - `asin(2)` - arcsine undefined outside [-1, 1]
72 #[error("Domain error: {0}")]
73 DomainError(String),
74
75 /// Input validation error for invalid parameter values
76 ///
77 /// Used for parameter validation failures where inputs don't meet function
78 /// requirements (but may be mathematically valid elsewhere).
79 ///
80 /// # Examples
81 /// - Negative array dimensions
82 /// - Invalid tolerance parameters (e.g., negative tolerance)
83 /// - Array shape mismatches
84 /// - Invalid enumeration values
85 #[error("Value error: {0}")]
86 ValueError(String),
87
88 /// Feature or function not yet implemented
89 ///
90 /// Indicates that a requested feature exists in the API but hasn't been
91 /// implemented yet. This is used during development phases.
92 ///
93 /// # Examples
94 /// - Complex number support for certain functions
95 /// - Specific algorithm variants
96 /// - Platform-specific optimizations
97 #[error("Not implemented: {0}")]
98 NotImplementedError(String),
99
100 /// Iterative algorithm convergence failure
101 ///
102 /// Thrown when iterative algorithms fail to converge within specified
103 /// tolerances or iteration limits. Often indicates numerical instability
104 /// or inappropriate algorithm parameters.
105 ///
106 /// # Examples
107 /// - Newton-Raphson method divergence
108 /// - Series expansion truncation errors
109 /// - Root-finding algorithm failure
110 /// - Integration quadrature non-convergence
111 #[error("Convergence error: {0}")]
112 ConvergenceError(String),
113
114 /// Numerical overflow - result too large to represent
115 ///
116 /// Occurs when mathematical operations produce results that exceed the
117 /// representable range of floating-point numbers (typically > 1.8e308 for f64).
118 ///
119 /// # Examples
120 /// - `gamma(1000)` - extremely large gamma function values
121 /// - `exp(1000)` - exponential overflow
122 /// - Factorial of large numbers
123 /// - Product operations with many large terms
124 #[error("Overflow error: {0}")]
125 OverflowError(String),
126
127 /// GPU acceleration unavailable, computation falls back to CPU
128 ///
129 /// Indicates that GPU computation was requested but is not available.
130 /// This is often a non-fatal error where computation continues on CPU,
131 /// but can be used to inform users about performance implications.
132 ///
133 /// # Examples
134 /// - No GPU hardware available
135 /// - GPU drivers not installed
136 /// - CUDA/OpenCL runtime unavailable
137 /// - GPU memory exhaustion
138 #[error("GPU not available: {0}")]
139 GpuNotAvailable(String),
140
141 /// Error propagated from scirs2-core dependency
142 ///
143 /// Wraps errors from the core SciRS2 infrastructure. These typically
144 /// relate to low-level operations like SIMD, parallel processing, or
145 /// hardware acceleration.
146 #[error("Core error: {0}")]
147 CoreError(#[from] CoreError),
148}
149
150/// Convenient Result type alias for special function operations
151///
152/// This type alias simplifies function signatures throughout the special functions module.
153/// All special function computations that can fail return this type, allowing for
154/// consistent error handling patterns.
155///
156/// # Usage Examples
157///
158/// ```rust,ignore
159/// use scirs2_special::{SpecialResult, SpecialError};
160///
161/// fn safe_computation(x: f64) -> SpecialResult<f64> {
162/// if x < 0.0 {
163/// Err(SpecialError::DomainError("x must be non-negative".to_string()))
164/// } else {
165/// Ok(x.sqrt())
166/// }
167/// }
168///
169/// // Pattern matching for error handling
170/// match safe_computation(-1.0) {
171/// Ok(result) => println!("Result: {}", result),
172/// Err(SpecialError::DomainError(msg)) => eprintln!("Domain error: {msg}"),
173/// Err(e) => eprintln!("Other error: {e}"),
174/// }
175/// ```
176pub type SpecialResult<T> = Result<T, SpecialError>;
177
178// Automatic error conversions for common error types
179
180/// Convert from standard library float parsing errors
181///
182/// Automatically converts `ParseFloatError` into `SpecialError::ValueError`
183/// for seamless error propagation when parsing numerical input.
184impl From<std::num::ParseFloatError> for SpecialError {
185 fn from(err: std::num::ParseFloatError) -> Self {
186 SpecialError::ValueError(format!("Failed to parse float: {err}"))
187 }
188}
189
190/// Convert from standard library IO errors
191///
192/// Automatically converts `std::io::Error` into `SpecialError::ComputationError`
193/// for handling file I/O failures during computation or data loading.
194impl From<std::io::Error> for SpecialError {
195 fn from(err: std::io::Error) -> Self {
196 SpecialError::ComputationError(format!("IO error: {err}"))
197 }
198}