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