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)]
14pub mod error;
106pub mod error_context;
107pub mod error_wrappers;
108pub use error::{SpecialError, SpecialResult};
109
110mod 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
173pub use airy::{ai, ai_zeros, aie, aip, airye, bi, bi_zeros, bie, bip, itairy};
177pub use airy::complex::{ai_complex, aip_complex, bi_complex, bip_complex};
179pub use bessel::{
180 h1vp,
181 h2vp,
182 hankel1,
184 hankel1e,
185 hankel2,
186 hankel2e,
187 i0,
189 i0_prime,
191 i0e,
192 i1,
193 i1_prime,
194 i1e,
195 iv,
196 iv_prime,
197 ive,
198 ivp,
199 j0,
200 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 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_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 itj0y0,
242 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 bdtr,
266 bdtr_array,
267 bdtrc,
268 bdtri,
269 bdtrik,
270 bdtrin,
271 btdtria,
273 btdtrib,
274 chdtr,
276 chdtrc,
277 chdtri,
278 fdtr,
280 fdtrc,
281 fdtridfd,
282 gdtr,
284 gdtrc,
285 gdtria,
286 gdtrib,
287 gdtrix,
288 kolmogi,
289 kolmogorov,
291 log_ndtr,
292 nbdtr,
294 nbdtrc,
295 nbdtri,
296 ndtr,
298 ndtr_array,
299 ndtri,
300 ndtri_exp,
301 pdtr,
303 pdtrc,
304 pdtri,
305 pdtrik,
306 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 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};
340pub use gamma::complex::{beta_complex, digamma_complex, gamma_complex, loggamma_complex};
342pub use bessel::complex::{i0_complex, j0_complex, j1_complex, jn_complex, jv_complex, k0_complex};
344pub 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 cbrt,
376 cbrt_array,
378 cosdg,
379 cosm1,
381 cotdg,
382 diric,
384 exp10,
385 exp10_array,
386 exp2,
387 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 radian,
401 round,
402 round_array,
403 sindg,
404 softplus,
405 spherical_distance,
406 tandg,
407 xlog1py,
408 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#[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#[cfg(feature = "parallel")]
432pub use simd_ops::{
433 adaptive_gamma_processing, benchmark_parallel_performance, gamma_f64_parallel, j0_f64_parallel,
434};
435
436#[cfg(all(feature = "simd", feature = "parallel"))]
438pub use simd_ops::gamma_f32_simd_parallel;
439
440pub use erf::{dawsn, erf, erfc, erfcinv, erfcx, erfi, erfinv, wofz};
442
443#[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 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 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 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 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 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 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}