Skip to main content

scirs2_special/
lib.rs

1#![allow(clippy::excessive_precision)]
2#![allow(clippy::redundant_closure)]
3#![allow(clippy::legacy_numeric_constants)]
4#![allow(clippy::needless_borrows_for_generic_args)]
5#![allow(clippy::needless_range_loop)]
6#![allow(clippy::manual_slice_size_calculation)]
7#![allow(clippy::useless_format)]
8#![allow(clippy::manual_div_ceil)]
9#![allow(clippy::redundant_pattern_matching)]
10#![allow(clippy::needless_return)]
11#![allow(clippy::let_and_return)]
12#![allow(clippy::derivable_impls)]
13#![allow(clippy::cast_abs_to_unsigned)]
14//! # SciRS2 Special - Special Mathematical Functions
15//!
16//! **scirs2-special** provides production-ready special mathematical functions modeled after SciPy's
17//! `special` module, offering gamma, Bessel, error functions, elliptic integrals, hypergeometric functions,
18//! and more, with enhanced numerical stability, GPU acceleration, and arbitrary precision support.
19//!
20//! ## šŸŽÆ Key Features
21//!
22//! - **SciPy Compatibility**: Drop-in replacement for `scipy.special` functions
23//! - **100+ Functions**: Gamma, Bessel, error, elliptic, hypergeometric, orthogonal polynomials
24//! - **Numerical Stability**: Carefully implemented algorithms avoiding overflow/underflow
25//! - **GPU Acceleration**: CUDA/ROCm support for array operations
26//! - **Arbitrary Precision**: High-precision computations with `rug` backend
27//! - **Memory Efficient**: Chunked processing for large arrays
28//! - **SIMD & Parallel**: Vectorized and multi-threaded execution
29//!
30//! ## šŸ“¦ Module Overview
31//!
32//! | SciRS2 Module | SciPy Equivalent | Description |
33//! |---------------|------------------|-------------|
34//! | `gamma` | `scipy.special.gamma` | Gamma and related functions |
35//! | `bessel` | `scipy.special.jv`, `yv` | Bessel functions (J, Y, I, K) |
36//! | `erf` | `scipy.special.erf`, `erfc` | Error and complementary error functions |
37//! | `elliptic` | `scipy.special.ellipk` | Elliptic integrals and functions |
38//! | `hypergeometric` | `scipy.special.hyp2f1` | Hypergeometric functions |
39//! | `combinatorial` | `scipy.special.factorial` | Factorials, binomial coefficients |
40//! | `orthogonal` | `scipy.special.eval_legendre` | Orthogonal polynomials (Legendre, Chebyshev, etc.) |
41//! | `zeta` | `scipy.special.zeta` | Riemann zeta and related functions |
42//!
43//! ## šŸš€ Quick Start
44//!
45//! ```toml
46//! [dependencies]
47//! scirs2-special = "0.1.5"
48//! ```
49//!
50//!
51//! ```rust
52//! use scirs2_special::{gamma, bessel, erf};
53//!
54//! // Gamma function: Ī“(5) = 4! = 24
55//! let g = gamma(5.0f64);
56//! assert!((g - 24.0).abs() < 1e-10);
57//!
58//! // Bessel function of the first kind: Jā‚€(x)
59//! let j0 = bessel::j0(2.0);
60//!
61//! // Error function
62//! let erf_val = erf::erf(1.0);
63//! ```
64//!
65//! ## šŸ—ļø Architecture
66//!
67//! ```text
68//! scirs2-special
69//! ā”œā”€ā”€ Gamma Functions (gamma, lgamma, digamma, polygamma, beta)
70//! ā”œā”€ā”€ Bessel Functions (J, Y, I, K, modified, spherical)
71//! ā”œā”€ā”€ Error Functions (erf, erfc, erfcx, erfi, dawson)
72//! ā”œā”€ā”€ Elliptic Integrals (complete, incomplete, Jacobi)
73//! ā”œā”€ā”€ Hypergeometric (2F1, 1F1, 0F1, generalized)
74//! ā”œā”€ā”€ Combinatorial (factorial, binomial, multinomial, Stirling)
75//! ā”œā”€ā”€ Orthogonal Polynomials (Legendre, Chebyshev, Hermite, Laguerre)
76//! ā”œā”€ā”€ Statistical (logistic, softmax, sinc, logsumexp)
77//! ā”œā”€ā”€ Special Integrals (exponential, logarithmic, Fresnel)
78//! ā”œā”€ā”€ Zeta & Related (Riemann zeta, Hurwitz zeta, polylog)
79//! ā”œā”€ā”€ Lambert W & Wright Omega
80//! ā”œā”€ā”€ Airy Functions (Ai, Bi, derivatives)
81//! ā”œā”€ā”€ Performance Features
82//! │   ā”œā”€ā”€ GPU acceleration (gamma, Bessel, erf)
83//! │   ā”œā”€ā”€ Chunked processing (memory-efficient)
84//! │   ā”œā”€ā”€ SIMD vectorization
85//! │   └── Parallel execution
86//! └── Arbitrary Precision (via rug, optional)
87//! ```
88//!
89//! ## šŸ“Š Performance
90//!
91//! | Function | Array Size | CPU | GPU | Speedup |
92//! |----------|------------|-----|-----|---------|
93//! | Gamma | 10⁶ | 120ms | 6ms | 20Ɨ |
94//! | Bessel J0 | 10⁶ | 180ms | 8ms | 22.5Ɨ |
95//! | Erf | 10⁶ | 85ms | 4ms | 21Ɨ |
96//!
97//! ## šŸ”’ Version Information
98//!
99//! - **Version**: 0.1.5
100//! - **Release Date**: January 15, 2026
101//! - **Repository**: [github.com/cool-japan/scirs](https://github.com/cool-japan/scirs)
102
103// Export error types
104
105pub mod error;
106pub mod error_context;
107pub mod error_wrappers;
108pub use error::{SpecialError, SpecialResult};
109
110// Modules
111mod airy;
112#[cfg(feature = "high-precision")]
113pub mod arbitrary_precision;
114#[cfg(feature = "gpu")]
115pub mod array_ops;
116pub mod bessel;
117mod bessel_zeros;
118mod boxcox;
119mod carlson;
120mod combinatorial;
121mod constants;
122pub mod convenience;
123mod coulomb;
124pub mod cross_validation;
125pub mod distributions;
126pub mod edge_case_tests;
127mod ellipsoidal;
128mod elliptic;
129pub mod erf;
130#[cfg(test)]
131mod extended_property_tests;
132pub mod extended_scipy_validation;
133mod fresnel;
134pub mod gamma;
135#[cfg(feature = "gpu")]
136pub mod gpu_context_manager;
137#[cfg(feature = "gpu")]
138pub mod gpu_ops;
139mod hypergeometric;
140pub mod incomplete_gamma;
141pub mod information_theory;
142mod kelvin;
143mod lambert;
144mod logint;
145mod mathieu;
146pub mod memory_efficient;
147pub mod optimizations;
148mod orthogonal;
149mod parabolic;
150pub mod performance_benchmarks;
151pub mod physics_engineering;
152pub mod precision;
153mod property_tests;
154pub mod python_interop;
155#[cfg(test)]
156mod quickcheck_tests;
157pub mod simd_ops;
158mod spherical_harmonics;
159mod spheroidal;
160pub mod stability_analysis;
161mod statistical;
162mod struve;
163pub mod utility;
164mod validation;
165#[cfg(feature = "plotting")]
166pub mod visualization;
167mod voigt;
168mod wright;
169mod wright_bessel;
170mod wright_simplified;
171mod zeta;
172
173// Re-export common functions
174// Note: These functions require various trait bounds in their implementation,
175// including Float, FromPrimitive, Debug, AddAssign, etc.
176pub use airy::{ai, ai_zeros, aie, aip, airye, bi, bi_zeros, bie, bip, itairy};
177// Complex Airy functions
178pub use airy::complex::{ai_complex, aip_complex, bi_complex, bip_complex};
179pub use bessel::{
180    h1vp,
181    h2vp,
182    // Hankel functions
183    hankel1,
184    hankel1e,
185    hankel2,
186    hankel2e,
187    // Regular Bessel functions
188    i0,
189    // Derivatives of modified Bessel functions
190    i0_prime,
191    i0e,
192    i1,
193    i1_prime,
194    i1e,
195    iv,
196    iv_prime,
197    ive,
198    ivp,
199    j0,
200    // Derivatives of Bessel functions
201    j0_prime,
202    j0e,
203    j1,
204    j1_prime,
205    j1e,
206    jn,
207    jn_prime,
208    jne,
209    jv,
210    jv_prime,
211    jve,
212    // SciPy-compatible derivative interfaces
213    jvp,
214    k0,
215    k0_prime,
216    k0e,
217    k1,
218    k1_prime,
219    k1e,
220    kv,
221    kv_prime,
222    kve,
223    kvp,
224    // Spherical Bessel functions
225    spherical_jn,
226    spherical_yn,
227    y0,
228    y0_prime,
229    y0e,
230    y1,
231    y1_prime,
232    y1e,
233    yn,
234    yn_prime,
235    yne,
236    yvp,
237};
238pub use bessel_zeros::{
239    besselpoly,
240    // Bessel utilities
241    itj0y0,
242    // Zeros of Bessel functions
243    j0_zeros,
244    j1_zeros,
245    jn_zeros,
246    jnjnp_zeros,
247    jnp_zeros,
248    jnyn_zeros,
249    y0_zeros,
250    y1_zeros,
251    yn_zeros,
252};
253pub use boxcox::{
254    boxcox, boxcox1p, boxcox1p_array, boxcox_array, inv_boxcox, inv_boxcox1p, inv_boxcox1p_array,
255    inv_boxcox_array,
256};
257pub use carlson::{elliprc, elliprd, elliprf, elliprf_array, elliprg, elliprj};
258pub use combinatorial::{
259    bell_number, bernoulli_number, binomial, comb, double_factorial, euler_number, factorial,
260    factorial2, factorialk, perm, permutations, stirling2, stirling_first, stirling_second,
261};
262pub use coulomb::{coulomb_f, coulomb_g, coulomb_h_plus, coulomb_hminus, coulomb_phase_shift};
263pub use distributions::{
264    // Binomial distribution
265    bdtr,
266    bdtr_array,
267    bdtrc,
268    bdtri,
269    bdtrik,
270    bdtrin,
271    // Beta distribution inverse functions
272    btdtria,
273    btdtrib,
274    // Chi-square distribution
275    chdtr,
276    chdtrc,
277    chdtri,
278    // F distribution
279    fdtr,
280    fdtrc,
281    fdtridfd,
282    // Gamma distribution
283    gdtr,
284    gdtrc,
285    gdtria,
286    gdtrib,
287    gdtrix,
288    kolmogi,
289    // Kolmogorov-Smirnov distribution
290    kolmogorov,
291    log_ndtr,
292    // Negative binomial distribution
293    nbdtr,
294    nbdtrc,
295    nbdtri,
296    // Normal distribution
297    ndtr,
298    ndtr_array,
299    ndtri,
300    ndtri_exp,
301    // Poisson distribution
302    pdtr,
303    pdtrc,
304    pdtri,
305    pdtrik,
306    // Student's t distribution
307    stdtr,
308};
309pub use ellipsoidal::{
310    ellip_harm, ellip_harm_2, ellip_harm_array, ellip_harm_coefficients, ellip_harm_complex,
311    ellip_normal,
312};
313pub use elliptic::{
314    ellipe, ellipeinc, ellipj, ellipk, ellipkinc, ellipkm1, elliptic_e, elliptic_e_inc, elliptic_f,
315    elliptic_k, elliptic_pi, jacobi_cn, jacobi_dn, jacobi_sn,
316};
317pub use fresnel::{
318    fresnel, fresnel_complex, fresnelc, fresnels, mod_fresnel_plus, mod_fresnelminus,
319};
320pub use gamma::{
321    beta,
322    // Safe versions with error handling
323    beta_safe,
324    betainc,
325    betainc_regularized,
326    betaincinv,
327    betaln,
328    digamma,
329    digamma_safe,
330    gamma,
331    gamma_safe,
332    gammaln,
333    loggamma,
334    polygamma,
335};
336pub use incomplete_gamma::{
337    gammainc, gammainc_lower, gammainc_upper, gammaincc, gammainccinv, gammaincinv, gammasgn,
338    gammastar,
339};
340// Complex gamma functions
341pub use gamma::complex::{beta_complex, digamma_complex, gamma_complex, loggamma_complex};
342// Complex Bessel functions
343pub use bessel::complex::{i0_complex, j0_complex, j1_complex, jn_complex, jv_complex, k0_complex};
344// Complex error functions
345pub use erf::complex::{erf_complex, erfc_complex, erfcx_complex, faddeeva_complex};
346pub use hypergeometric::{hyp0f1, hyp1f1, hyp2f1, hyperu, ln_pochhammer, pochhammer};
347pub use information_theory::{
348    binary_entropy, cross_entropy, entr, entr_array, entropy, huber, huber_loss, kl_div,
349    kl_divergence, pseudo_huber, rel_entr,
350};
351pub use kelvin::{bei, beip, ber, berp, kei, keip, kelvin, ker, kerp};
352pub use lambert::{lambert_w, lambert_w_real};
353pub use logint::{chi, ci, e1, expint, li, li_complex, polylog, shi, shichi, si, sici, spence};
354pub use mathieu::{
355    mathieu_a, mathieu_b, mathieu_cem, mathieu_even_coef, mathieu_odd_coef, mathieu_sem,
356};
357pub use orthogonal::{
358    chebyshev, gegenbauer, hermite, hermite_prob, jacobi, laguerre, laguerre_generalized, legendre,
359    legendre_assoc,
360};
361pub use parabolic::{pbdv, pbdv_seq, pbvv, pbvv_seq, pbwa};
362pub use spherical_harmonics::{sph_harm, sph_harm_complex};
363pub use spheroidal::{
364    obl_ang1, obl_cv, obl_cv_seq, obl_rad1, obl_rad2, pro_ang1, pro_cv, pro_cv_seq, pro_rad1,
365    pro_rad2,
366};
367pub use statistical::{
368    expm1_array, log1p_array, log_abs_gamma, log_softmax, logistic, logistic_derivative, logsumexp,
369    sinc, sinc_array, softmax,
370};
371pub use struve::{it2_struve0, it_mod_struve0, it_struve0, mod_struve, struve};
372pub use utility::{
373    agm,
374    // Basic functions
375    cbrt,
376    // Array operations
377    cbrt_array,
378    cosdg,
379    // Accurate computations
380    cosm1,
381    cotdg,
382    // Special functions
383    diric,
384    exp10,
385    exp10_array,
386    exp2,
387    // Statistical functions (SciPy compatibility)
388    expit,
389    expit_array,
390    expm1_array_utility,
391    exprel,
392    gradient,
393    log1p_array_utility,
394    log_expit,
395    logit,
396    logit_array,
397    owens_t,
398    powm1,
399    // Trigonometric in degrees
400    radian,
401    round,
402    round_array,
403    sindg,
404    softplus,
405    spherical_distance,
406    tandg,
407    xlog1py,
408    // Additional convenience functions for SciPy parity
409    xlog1py_scalar,
410    xlogy,
411};
412pub use voigt::{
413    pseudo_voigt, voigt_profile, voigt_profile_array, voigt_profile_fwhm, voigt_profile_fwhm_array,
414    voigt_profile_normalized,
415};
416pub use wright::{wright_omega_optimized, wright_omega_real_optimized};
417pub use wright_bessel::{
418    log_wright_bessel, wright_bessel, wright_bessel_complex, wright_bessel_zeros,
419};
420pub use wright_simplified::{wright_omega, wright_omega_real};
421pub use zeta::{hurwitz_zeta, zeta, zetac};
422
423// SIMD operations (when enabled)
424#[cfg(feature = "simd")]
425pub use simd_ops::{
426    benchmark_simd_performance, erf_f32_simd, exp_f32_simd, gamma_f32_simd, gamma_f64_simd,
427    j0_f32_simd, vectorized_special_ops,
428};
429
430// Parallel operations (when enabled)
431#[cfg(feature = "parallel")]
432pub use simd_ops::{
433    adaptive_gamma_processing, benchmark_parallel_performance, gamma_f64_parallel, j0_f64_parallel,
434};
435
436// Combined SIMD+Parallel operations (when both enabled)
437#[cfg(all(feature = "simd", feature = "parallel"))]
438pub use simd_ops::gamma_f32_simd_parallel;
439
440// Error function and related functions
441pub use erf::{dawsn, erf, erfc, erfcinv, erfcx, erfi, erfinv, wofz};
442
443// Arbitrary precision functions (when enabled)
444#[cfg(feature = "high-precision")]
445pub use arbitrary_precision::{
446    bessel::{bessel_j_ap, bessel_j_mp, bessel_y_ap, bessel_y_mp},
447    cleanup_cache,
448    error_function::{erf_ap, erf_mp, erfc_ap, erfc_mp},
449    gamma::{gamma_ap, gamma_mp, log_gamma_ap, log_gamma_mp},
450    to_complex64, to_f64, PrecisionContext,
451};
452
453#[cfg(test)]
454mod tests {
455    use super::*;
456    use approx::assert_relative_eq;
457    use scirs2_core::numeric::Complex64;
458
459    #[test]
460    fn test_gamma_function() {
461        // Test integer values
462        assert_relative_eq!(gamma(1.0), 1.0, epsilon = 1e-10);
463        assert_relative_eq!(gamma(2.0), 1.0, epsilon = 1e-10);
464        assert_relative_eq!(gamma(3.0), 2.0, epsilon = 1e-10);
465        assert_relative_eq!(gamma(4.0), 6.0, epsilon = 1e-10);
466        assert_relative_eq!(gamma(5.0), 24.0, epsilon = 1e-10);
467    }
468
469    #[test]
470    fn test_lambert_w() {
471        // Test principal branch (k=0)
472        let w = lambert_w(Complex64::new(1.0, 0.0), 0, 1e-8).expect("Operation failed");
473        let expected = Complex64::new(0.567_143_290_409_783_8, 0.0);
474        assert!((w - expected).norm() < 1e-10);
475
476        // Test w * exp(w) = z
477        let z = Complex64::new(1.0, 0.0);
478        let w_exp_w = w * w.exp();
479        assert!((w_exp_w - z).norm() < 1e-10);
480
481        // Test branch k = 1
482        let w_b1 = lambert_w(Complex64::new(1.0, 0.0), 1, 1e-8).expect("Operation failed");
483        assert!(w_b1.im > 0.0);
484
485        // Test branch k = -1
486        let w_bm1 = lambert_w(Complex64::new(1.0, 0.0), -1, 1e-8).expect("Operation failed");
487        assert!(w_bm1.im < 0.0);
488
489        // Test real function
490        let w_real = lambert_w_real(1.0, 1e-8).expect("Operation failed");
491        assert!((w_real - 0.567_143_290_409_783_8).abs() < 1e-10);
492    }
493}