Skip to main content

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}