pub mod bessel;
pub mod common;
pub mod elliptic;
pub mod error_functions;
pub mod gamma;
pub mod hypergeometric;
pub mod orthogonal;
pub use error_functions::{erf, erfc, erfcinv, erfinv};
pub use gamma::{beta, betainc, digamma, gamma, gammainc, gammaln};
pub use bessel::{bessel_i, bessel_j, bessel_k, bessel_y};
pub use elliptic::{ellipe, ellipeinc, ellipf, ellipk, jacobi_elliptic};
pub use hypergeometric::{exp1, expi, fresnel, lambertw, lambertwm1, polylog, shichi, sici, zeta};
pub use orthogonal::{
airy_ai, airy_bi, associated_legendre_p, legendre_p, spherical_harmonic, struve_h,
};
#[cfg(test)]
mod tests {
use super::*;
use crate::array::Array;
use approx::assert_relative_eq;
#[test]
fn test_erf() {
let values = Array::from_vec(vec![0.0, 0.5, 1.0, -0.5]);
let result = erf(&values);
assert_relative_eq!(result.to_vec()[0], 0.0, epsilon = 1e-8);
assert_relative_eq!(result.to_vec()[1], 0.5204998778130465, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[2], 0.8427007929497149, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[3], -0.5204998778130465, epsilon = 1e-4);
}
#[test]
fn test_erfc() {
let values = Array::from_vec(vec![0.0, 0.5, 1.0, 2.0]);
let result = erfc(&values);
assert_relative_eq!(result.to_vec()[0], 1.0, epsilon = 1e-8);
assert_relative_eq!(result.to_vec()[1], 0.4795001221869535, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[2], 0.15729920705028513, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[3], 0.0046777349810472645, epsilon = 1e-4);
}
#[test]
fn test_gamma() {
let values = Array::from_vec(vec![1.0, 2.0, 3.0, 4.0, 5.0]);
let result = gamma(&values);
assert_relative_eq!(result.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[1], 1.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[2], 2.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[3], 6.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[4], 24.0, epsilon = 1e-10);
}
#[test]
fn test_bessel_j() {
let values = Array::from_vec(vec![0.0, 1.0, 2.0, 5.0]);
let j0 = bessel_j(0, &values);
assert_relative_eq!(j0.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(j0.to_vec()[1], 0.7651976865579666, epsilon = 1e-4);
let j1 = bessel_j(1, &values);
assert_relative_eq!(j1.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(j1.to_vec()[1], 0.44005058574493355, epsilon = 1e-4);
}
#[test]
fn test_ellipk() {
let values = Array::from_vec(vec![0.0, 0.5, 0.9]);
let result = ellipk(&values);
assert_relative_eq!(
result.to_vec()[0],
std::f64::consts::PI / 2.0,
epsilon = 1e-10
);
assert!(result.to_vec()[1] > std::f64::consts::PI / 2.0);
assert!(result.to_vec()[2] > result.to_vec()[1]);
}
#[test]
fn test_beta() {
let a = Array::from_vec(vec![1.0, 2.0, 3.0]);
let b = Array::from_vec(vec![1.0, 2.0, 3.0]);
let result = beta(&a, &b).expect("beta should succeed");
assert_relative_eq!(result.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[1], 1.0 / 6.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[2], 1.0 / 30.0, epsilon = 1e-10);
}
#[test]
fn test_betainc() {
let a = Array::from_vec(vec![1.0, 2.0]);
let b = Array::from_vec(vec![1.0, 2.0]);
let x = Array::from_vec(vec![0.5, 0.5]);
let result = betainc(&a, &b, &x).expect("betainc should succeed");
assert_relative_eq!(result.to_vec()[0], 0.5, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[1], 0.5, epsilon = 1e-4);
}
#[test]
fn test_zeta() {
let s = Array::from_vec(vec![2.0, 3.0, 4.0]);
let result = zeta(&s);
assert_relative_eq!(
result.to_vec()[0],
std::f64::consts::PI.powi(2) / 6.0,
epsilon = 1e-3
);
assert_relative_eq!(result.to_vec()[1], 1.2020569, epsilon = 1e-3);
assert_relative_eq!(
result.to_vec()[2],
std::f64::consts::PI.powi(4) / 90.0,
epsilon = 1e-3
);
}
#[test]
fn test_airy_ai() {
let x = Array::from_vec(vec![0.0, 1.0, -1.0]);
let result = airy_ai(&x);
assert_relative_eq!(result.to_vec()[0], 0.35502805388781724, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[1], 0.13529241631288141, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[2], 0.5355608832923521, epsilon = 1e-4);
}
#[test]
fn test_airy_bi() {
let x = Array::from_vec(vec![0.0, 1.0, -1.0]);
let result = airy_bi(&x);
assert_relative_eq!(result.to_vec()[0], 0.61492662744600073, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[1], 1.2074283264132947, epsilon = 1e-4);
assert_relative_eq!(result.to_vec()[2], 0.10399738949694461, epsilon = 1e-4);
}
#[test]
fn test_sici() {
let x = Array::from_vec(vec![0.0, 1.0, 2.0]);
let (si, ci) = sici(&x);
assert_relative_eq!(si.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(si.to_vec()[1], 0.9460830703671830, epsilon = 1e-3);
assert_relative_eq!(si.to_vec()[2], 1.6054129768026948, epsilon = 1e-3);
assert_relative_eq!(ci.to_vec()[1], 0.33740392290096813, epsilon = 1e-3);
assert_relative_eq!(ci.to_vec()[2], 0.4229808287748649, epsilon = 1e-3);
}
#[test]
fn test_fresnel() {
let x = Array::from_vec(vec![0.0, 1.0, 2.0]);
let (s, c) = fresnel(&x);
assert_relative_eq!(s.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(c.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(s.to_vec()[1], 0.43825914739035476, epsilon = 1e-3);
assert_relative_eq!(c.to_vec()[1], 0.7798934003768228, epsilon = 1e-3);
}
#[test]
fn test_expi() {
let x = Array::from_vec(vec![1.0, 2.0]);
let result = expi(&x);
assert_relative_eq!(result.to_vec()[0], 1.8951178163559368, epsilon = 1e-3);
assert_relative_eq!(result.to_vec()[1], 4.954234356001890, epsilon = 1e-3);
}
#[test]
fn test_exp1() {
let x = Array::from_vec(vec![1.0, 2.0]);
let result = exp1(&x);
assert_relative_eq!(result.to_vec()[0], 0.21938393439552027, epsilon = 1e-3);
assert_relative_eq!(result.to_vec()[1], 0.04890051070806112, epsilon = 1e-3);
}
#[test]
fn test_legendre_p() {
let x = Array::from_vec(vec![0.0, 0.5, 1.0]);
let p0 = legendre_p(0, &x).expect("legendre_p should succeed");
assert_relative_eq!(p0.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(p0.to_vec()[1], 1.0, epsilon = 1e-10);
assert_relative_eq!(p0.to_vec()[2], 1.0, epsilon = 1e-10);
let p1 = legendre_p(1, &x).expect("legendre_p should succeed");
assert_relative_eq!(p1.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(p1.to_vec()[1], 0.5, epsilon = 1e-10);
assert_relative_eq!(p1.to_vec()[2], 1.0, epsilon = 1e-10);
let p2 = legendre_p(2, &x).expect("legendre_p should succeed");
assert_relative_eq!(p2.to_vec()[0], -0.5, epsilon = 1e-10); assert_relative_eq!(p2.to_vec()[1], -0.125, epsilon = 1e-10); assert_relative_eq!(p2.to_vec()[2], 1.0, epsilon = 1e-10); }
#[test]
fn test_associated_legendre_p() {
let x = Array::from_vec(vec![0.0, 0.5, 1.0]);
let p11 = associated_legendre_p(1, 1, &x).expect("associated_legendre_p should succeed");
assert_relative_eq!(p11.to_vec()[0], -1.0, epsilon = 1e-10); assert_relative_eq!(p11.to_vec()[1], -0.8660254037844386, epsilon = 1e-10); assert_relative_eq!(p11.to_vec()[2], 0.0, epsilon = 1e-10); }
#[test]
fn test_spherical_harmonic() {
let theta = Array::from_vec(vec![std::f64::consts::PI / 2.0]);
let phi = Array::from_vec(vec![0.0]);
let y00 =
spherical_harmonic(0, 0, &theta, &phi).expect("spherical_harmonic should succeed");
assert_relative_eq!(y00.to_vec()[0], 0.2820947917738782, epsilon = 1e-4);
}
#[test]
fn test_jacobi_elliptic_special_cases() {
let u = Array::from_vec(vec![0.0, 1.0, 2.0]);
let (sn, cn, dn) = jacobi_elliptic(&u, 0.0).expect("jacobi_elliptic should succeed");
assert_relative_eq!(sn.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(cn.to_vec()[0], 1.0, epsilon = 1e-10);
assert_relative_eq!(dn.to_vec()[0], 1.0, epsilon = 1e-10);
}
#[test]
fn test_incomplete_elliptic_integrals() {
let phi = Array::from_vec(vec![0.0]);
let m = Array::from_vec(vec![0.5]);
let f = ellipf(&phi, &m).expect("ellipf should succeed");
assert_relative_eq!(f.to_vec()[0], 0.0, epsilon = 1e-10);
let e = ellipeinc(&phi, &m).expect("ellipeinc should succeed");
assert_relative_eq!(e.to_vec()[0], 0.0, epsilon = 1e-10);
}
#[test]
fn test_lambertw() {
let x = Array::from_vec(vec![0.0, 1.0]);
let result = lambertw(&x);
assert_relative_eq!(result.to_vec()[0], 0.0, epsilon = 1e-10);
assert_relative_eq!(result.to_vec()[1], 0.5671432904097839, epsilon = 1e-6);
}
#[test]
fn test_lambertw_identity() {
let x = Array::from_vec(vec![0.5, 1.0, 2.0, 5.0]);
let w = lambertw(&x);
for i in 0..x.to_vec().len() {
let x_val: f64 = x.to_vec()[i];
let w_val: f64 = w.to_vec()[i];
let reconstructed = w_val * w_val.exp();
assert_relative_eq!(reconstructed, x_val, epsilon = 1e-8);
}
}
#[test]
fn test_polylog() {
let z = Array::from_vec(vec![0.5]);
let result = polylog(2.0, &z);
assert_relative_eq!(result.to_vec()[0], 0.5822405264650125, epsilon = 1e-3);
}
#[test]
fn test_struve_h() {
let x = Array::from_vec(vec![0.0, 1.0]);
let result = struve_h(0, &x);
assert_relative_eq!(result.to_vec()[0], 0.0, epsilon = 1e-10);
assert!(result.to_vec()[1] > 0.3 && result.to_vec()[1] < 0.7);
}
}