Skip to main content

complex_bessel/
types.rs

1//! Core types for Bessel function computation.
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::vec::Vec;
5use core::fmt;
6
7use num_complex::Complex;
8
9use crate::machine::BesselFloat;
10
11/// Status of the computation result.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
13pub enum Accuracy {
14    /// Computation within normal precision bounds (full machine precision).
15    Normal,
16    /// Result computed but may have lost more than half of significant digits.
17    /// Occurs when |z| or ν exceeds ~32767 for f64.
18    Reduced,
19}
20
21/// Result of an Airy function computation, returned by `_raw` functions
22/// (e.g., [`airy_raw`](crate::airy_raw)).
23///
24/// Single-value convenience functions (`airy`, `biry`, …) do not expose
25/// this type; they return only the computed value and discard the status.
26#[derive(Debug, Clone, Copy, PartialEq)]
27pub struct AiryResult<T: BesselFloat> {
28    /// Computed function value.
29    pub value: Complex<T>,
30    /// Precision status of the computation.
31    ///
32    /// [`Accuracy::Reduced`] indicates that |z| is large enough
33    /// for more than half of significant digits to be lost.
34    pub status: Accuracy,
35}
36
37/// Result of a sequence computation, returned by `_seq` functions
38/// (e.g., [`besselk_seq`](crate::besselk_seq)).
39///
40/// Single-value convenience functions (`besselj`, `besselk`, …) do not expose
41/// this type; they return only the computed value and discard the status.
42#[cfg(feature = "alloc")]
43#[derive(Debug, Clone, PartialEq)]
44pub struct BesselResult<T: BesselFloat> {
45    /// Computed function values for orders ν, ν+1, ..., ν+n-1.
46    pub values: Vec<Complex<T>>,
47    /// Number of leading components set to zero due to underflow.
48    pub underflow_count: usize,
49    /// Precision status of the computation.
50    ///
51    /// Single-value convenience functions do not expose this status;
52    /// use a `_seq` function to inspect it when needed.
53    pub status: Accuracy,
54}
55
56/// Scaling option for Bessel function computation.
57///
58/// The `_scaled` variant returns `factor · f(z)`, where factor is:
59/// - J, Y: `exp(-|Im(z)|)`
60/// - I: `exp(-|Re(z)|)`
61/// - K: `exp(z)`
62/// - H^(1): `exp(-iz)`
63/// - H^(2): `exp(iz)`
64/// - Ai, Ai': `exp(ζ)` where `ζ = (2/3) · z · √z`
65/// - Bi, Bi': `exp(-|Re(ζ)|)` where `ζ = (2/3) · z · √z`
66#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
67pub enum Scaling {
68    /// No scaling applied.
69    Unscaled,
70    /// Exponential scaling to prevent overflow/underflow.
71    Exponential,
72}
73
74/// Kind of Hankel function.
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76pub(crate) enum HankelKind {
77    /// H^(1), Hankel function of the first kind.
78    First,
79    /// H^(2), Hankel function of the second kind.
80    Second,
81}
82
83/// Selects I or K function path in uniform asymptotic expansion.
84///
85/// Controls the prefactor (1/sqrt(2π) vs sqrt(π/2)) and whether the
86/// asymptotic sum uses straight or alternating signs.
87#[derive(Debug, Clone, Copy, PartialEq, Eq)]
88pub(crate) enum IkFlag {
89    /// I function (Fortran ikflg=1): straight sum, sqrt(1/2π) prefactor.
90    I,
91    /// K function (Fortran ikflg=2): alternating sum, sqrt(π/2) prefactor.
92    K,
93}
94
95/// Controls whether the full asymptotic sum is computed or only phi/zeta.
96///
97/// When only the leading-order overflow/underflow test is needed (e.g. in
98/// ZUOIK), the expensive sum computation can be skipped.
99#[derive(Debug, Clone, Copy, PartialEq, Eq)]
100pub(crate) enum SumOption {
101    /// Compute all parameters including the asymptotic sum (Fortran ipmtr=0).
102    Full,
103    /// Compute phi/zeta only, skip the sum (Fortran ipmtr=1, for overflow pre-check).
104    SkipSum,
105}
106
107/// Selects Airy function value or its derivative.
108#[derive(Debug, Clone, Copy, PartialEq, Eq)]
109pub(crate) enum AiryDerivative {
110    /// Ai(z) or Bi(z).
111    Value,
112    /// Ai'(z) or Bi'(z).
113    Derivative,
114}
115
116/// Error type for Bessel function computation.
117#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
118pub enum Error {
119    /// Invalid input (e.g., z=0 for K/Y/H, n < 1 in sequence functions).
120    InvalidInput,
121    /// Overflow: |z| or ν too large, or |z| too small.
122    Overflow,
123    /// Complete loss of significant digits; |z| or ν too large for meaningful computation.
124    TotalPrecisionLoss,
125    /// Algorithm did not meet termination criteria.
126    ConvergenceFailure,
127}
128
129impl fmt::Display for Error {
130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131        match self {
132            Error::InvalidInput => {
133                write!(f, "invalid input: check z and nu constraints")
134            }
135            Error::Overflow => {
136                write!(f, "overflow: result magnitude exceeds representable range")
137            }
138            Error::TotalPrecisionLoss => {
139                write!(f, "total precision loss: no significant digits remain")
140            }
141            Error::ConvergenceFailure => {
142                write!(
143                    f,
144                    "convergence failure: algorithm did not meet termination criteria"
145                )
146            }
147        }
148    }
149}
150
151#[cfg(feature = "std")]
152impl std::error::Error for Error {}