num_valid/core/errors.rs
1#![deny(rustdoc::broken_intra_doc_links)]
2
3//! Error types for validation and conversion failures.
4//!
5//! This module provides the error types used throughout the library for reporting
6//! validation failures, conversion errors, and function domain violations.
7
8use crate::kernels::RawRealTrait;
9use num::Integer;
10use std::{backtrace::Backtrace, fmt::Display};
11use thiserror::Error;
12
13//--------------------------------------------
14// Errors for raw real number validation
15//--------------------------------------------
16/// Errors that can occur during the validation of a raw real number.
17///
18/// This enum is generic over `RawReal`, which is typically `f64` or [`rug::Float`](https://docs.rs/rug/latest/rug/struct.Float.html).
19/// It covers common validation failures like non-finite values, subnormality, infinity, and precision mismatch.
20#[derive(Debug, Error)]
21pub enum ErrorsValidationRawReal<RawReal: std::fmt::Debug + Display + Clone> {
22 /// The value is subnormal.
23 #[error("Value is subnormal: {value}")]
24 IsSubnormal {
25 /// The subnormal value that failed validation.
26 value: RawReal,
27
28 /// A captured backtrace for debugging purposes.
29 backtrace: Backtrace,
30 },
31
32 /// The value is NaN (Not a Number).
33 #[error("Value is NaN: {value}")]
34 IsNaN {
35 /// The NaN value that failed validation.
36 value: RawReal,
37
38 /// A captured backtrace for debugging purposes.
39 backtrace: Backtrace,
40 },
41
42 /// The value is positive infinity.
43 #[error("Value is positive infinity")]
44 IsPosInfinity {
45 /// The positive infinity value that failed validation.
46 backtrace: Backtrace,
47 },
48
49 /// The value is negative infinity.
50 #[error("Value is negative infinity")]
51 IsNegInfinity {
52 /// The negative infinity value that failed validation.
53 backtrace: Backtrace,
54 },
55
56 /// The precision of the input does not match the requested precision.
57 #[error(
58 "precision mismatch: input real has precision {actual_precision}, \
59 but the requested precision is {requested_precision}"
60 )]
61 PrecisionMismatch {
62 /// The input value.
63 input_value: RawReal,
64
65 /// The precision of the input value.
66 actual_precision: u32,
67
68 /// The requested precision.
69 requested_precision: u32,
70
71 /// A captured backtrace for debugging purposes.
72 backtrace: Backtrace,
73 },
74}
75
76//--------------------------------------------
77// Errors for complex number validation
78//--------------------------------------------
79/// Errors that can occur during the validation of a complex number.
80///
81/// This enum is generic over `ErrorValidationReal`, which is the error type returned
82/// by validating the real and imaginary parts of the complex number (e.g.,
83/// [`ErrorsValidationRawReal<f64>`](ErrorsValidationRawReal)).
84///
85/// It indicates whether the real part, the imaginary part, or both parts failed validation.
86#[derive(Debug, Error)]
87pub enum ErrorsValidationRawComplex<ErrorValidationReal: std::error::Error> {
88 /// The real part of the complex number failed validation.
89 #[error("Real part validation error: {source}")]
90 InvalidRealPart {
91 /// The underlying validation error for the real part.
92 #[source]
93 #[backtrace]
94 source: Box<ErrorValidationReal>,
95 },
96
97 /// The imaginary part of the complex number failed validation.
98 #[error("Imaginary part validation error: {source}")]
99 InvalidImaginaryPart {
100 /// The underlying validation error for the imaginary part.
101 #[source]
102 #[backtrace]
103 source: Box<ErrorValidationReal>,
104 },
105
106 /// Both the real and imaginary parts of the complex number failed validation.
107 #[error("Both real and imaginary parts are invalid: real={real_error}, imag={imag_error}")]
108 InvalidBothParts {
109 /// The validation error for the real part.
110 real_error: Box<ErrorValidationReal>,
111
112 /// The validation error for the imaginary part.
113 imag_error: Box<ErrorValidationReal>,
114 },
115}
116
117//-------------------------------------------------------------
118#[derive(Debug, Error)]
119pub enum RawRealConversionError<RawRealIn: RawRealTrait, RawRealOut: RawRealTrait> {
120 #[error(
121 "the input value ({value_in:?}) cannot be exactly represented with the requested precision (precision_out: {precision_out:?}, value_out: {value_out:?}). "
122 )]
123 NonRepresentableExactly {
124 /// The `RawRealIn` value that could not be exactly represented.
125 value_in: RawRealIn,
126
127 /// The input `value_in` after the conversion to the type `RawRealOut` with the requested `precision`.
128 value_out: RawRealOut,
129
130 /// The precision of `value_out`.
131 precision_out: u32,
132
133 /// A captured backtrace for debugging purposes.
134 backtrace: Backtrace,
135 },
136
137 /// The input value failed validation.
138 #[error("the input value is invalid!")]
139 InputValidation {
140 /// The underlying validation error for the `input` value.
141 #[source]
142 source: ErrorsValidationRawReal<RawRealIn>,
143 },
144
145 /// The output value failed validation.
146 #[error("the output value is invalid!")]
147 OutputValidation {
148 /// The underlying validation error for the `output` value.
149 #[source]
150 source: ErrorsValidationRawReal<RawRealOut>,
151 },
152
153 #[error(
154 "the output value has a precision ({precision_out:?}) that is not valid for the target type. The valid precision is {valid_precision_out:?}."
155 )]
156 InvalidOutputPrecision {
157 /// The `RawRealIn` value.
158 value_in: RawRealIn,
159
160 valid_precision_out: u32,
161
162 /// The precision of `value_out`.
163 precision_out: u32,
164
165 /// A captured backtrace for debugging purposes.
166 backtrace: Backtrace,
167 },
168}
169//-------------------------------------------------------------
170
171//-------------------------------------------------------------
172/// Errors that can occur when converting a raw real number to an integer type.
173///
174/// This enum represents the possible failures when attempting to convert a
175/// floating-point number to an integer, including non-finite values, non-integer
176/// values (with fractional parts), and values outside the representable range
177/// of the target integer type.
178///
179/// # Type Parameters
180///
181/// - `RawReal`: The source floating-point type implementing [`RawRealTrait`].
182/// - `IntType`: The target integer type implementing [`Integer`].
183#[derive(Debug, Error)]
184pub enum ErrorsRawRealToInteger<RawReal: RawRealTrait, IntType: Integer> {
185 /// The `RawReal` value is not finite (i.e., it is NaN or Infinity).
186 #[error("Value is not finite: {value}")]
187 NotFinite {
188 /// The non-finite `RawReal` value that caused the error.
189 value: RawReal,
190
191 /// A captured backtrace for debugging purposes.
192 backtrace: Backtrace,
193 },
194
195 /// The `RawReal` value is not an integer (i.e., it has a fractional part).
196 #[error("Value is not an integer: {value}")]
197 NotAnInteger {
198 /// The `RawReal` value that is not an integer.
199 value: RawReal,
200
201 /// A captured backtrace for debugging purposes.
202 backtrace: Backtrace,
203 },
204
205 /// The `RawReal` value is outside the range representable by the target integer type `IntType`.
206 #[error("Value {value} is out of range [{min}, {max}] for target integer type")]
207 OutOfRange {
208 /// The `RawReal` value that is out of range.
209 value: RawReal,
210
211 /// The minimum representable value of the target integer type `IntType`.
212 min: IntType,
213
214 /// The maximum representable value of the target integer type `IntType`.
215 max: IntType,
216
217 /// A captured backtrace for debugging purposes.
218 backtrace: Backtrace,
219 },
220}
221//-------------------------------------------------------------
222
223//--------------------------------------------------------------------------------------------------
224// Conditional Backtrace Support
225//--------------------------------------------------------------------------------------------------
226
227/// Captures a backtrace if the `backtrace` feature is enabled.
228///
229/// When the `backtrace` feature is enabled, this function captures a full backtrace
230/// using [`capture_backtrace()`]. When disabled (default), it returns a
231/// disabled backtrace with zero overhead.
232///
233/// # Performance
234///
235/// Backtrace capture is expensive (~1-10μs per capture). For performance-critical
236/// code, leave the `backtrace` feature disabled. Enable it during development or
237/// debugging to get detailed error traces.
238///
239/// # Example
240///
241/// ```toml
242/// # In Cargo.toml, enable backtraces for debugging:
243/// [dependencies]
244/// num-valid = { version = "0.2", features = ["backtrace"] }
245/// ```
246#[inline(always)]
247pub fn capture_backtrace() -> Backtrace {
248 #[cfg(feature = "backtrace")]
249 {
250 Backtrace::force_capture()
251 }
252 #[cfg(not(feature = "backtrace"))]
253 {
254 Backtrace::disabled()
255 }
256}
257
258/// Returns `true` if the `backtrace` feature is enabled.
259///
260/// This can be used to conditionally check whether backtraces are being captured.
261///
262/// # Example
263///
264/// ```rust
265/// use num_valid::core::errors::is_backtrace_enabled;
266///
267/// if is_backtrace_enabled() {
268/// println!("Backtraces are enabled - errors will include stack traces");
269/// } else {
270/// println!("Backtraces are disabled for performance");
271/// }
272/// ```
273#[inline(always)]
274pub const fn is_backtrace_enabled() -> bool {
275 #[cfg(feature = "backtrace")]
276 {
277 true
278 }
279 #[cfg(not(feature = "backtrace"))]
280 {
281 false
282 }
283}
284
285//--------------------------------------------------------------------------------------------------