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 {}