Skip to main content

complex_bessel/
types.rs

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