use scirs2_core::numeric::Complex64;
use scirs2_core::numeric::Zero;
use std::f64::consts::PI;
use crate::error::{SpecialError, SpecialResult};
#[allow(dead_code)]
pub fn fresnel(x: f64) -> SpecialResult<(f64, f64)> {
if x.is_nan() {
return Err(SpecialError::DomainError(
"NaN input to fresnel".to_string(),
));
}
if x == 0.0 {
return Ok((0.0, 0.0));
}
if x.abs() > 6.0 {
let (s, c) = fresnel_asymptotic(x)?;
return Ok((s, c));
}
fresnel_power_series(x)
}
#[allow(dead_code)]
pub fn fresnel_complex(z: Complex64) -> SpecialResult<(Complex64, Complex64)> {
if z.is_nan() {
return Err(SpecialError::DomainError(
"NaN input to fresnel_complex".to_string(),
));
}
if z.is_zero() {
return Ok((Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0)));
}
if z.norm() > 6.0 {
let (s, c) = fresnel_complex_asymptotic(z)?;
return Ok((s, c));
}
fresnel_complex_power_series(z)
}
#[allow(dead_code)]
fn fresnel_power_series(x: f64) -> SpecialResult<(f64, f64)> {
let sign = x.signum();
let ax = x.abs();
if ax < 1e-100 {
return Ok((0.0, 0.0));
}
let pi_half = PI / 2.0;
let t = pi_half * ax * ax;
let t2 = t * t;
let mut c_sum = 0.0;
let mut c_term = 1.0; for n in 0..50 {
let denom = (4 * n + 1) as f64;
c_sum += c_term / denom;
let next_factor = -t2 / (((2 * n + 1) * (2 * n + 2)) as f64);
c_term *= next_factor;
if c_term.abs() / denom < 1e-16 * c_sum.abs().max(1e-300) {
break;
}
}
let c = ax * c_sum;
let mut s_sum = 0.0;
let mut s_term = 1.0; for n in 0..50 {
let denom = (4 * n + 3) as f64;
s_sum += s_term / denom;
let next_factor = -t2 / (((2 * n + 2) * (2 * n + 3)) as f64);
s_term *= next_factor;
if s_term.abs() / denom < 1e-16 * s_sum.abs().max(1e-300) {
break;
}
}
let s = ax * t * s_sum;
Ok((sign * s, sign * c))
}
#[allow(dead_code)]
fn fresnel_asymptotic(x: f64) -> SpecialResult<(f64, f64)> {
let sign = x.signum();
let x = x.abs();
if x > 1e100 {
return Ok((sign * 0.5, sign * 0.5));
}
let z = if x > 1e7 {
let scaled_x = x / 1e7;
PI * scaled_x * scaled_x * 1e14 / 2.0
} else {
PI * x * x / 2.0
};
let reduced_z = if z > 1e10 {
let two_pi = 2.0 * PI;
z % two_pi
} else {
z
};
let sin_z = reduced_z.sin();
let cos_z = reduced_z.cos();
if x > 20.0 {
let f_first_term = 1.0 / (PI * x);
let g_first_term = 1.0 / (PI * 3.0 * 2.0 * z);
let s = 0.5 - f_first_term * cos_z - g_first_term * sin_z;
let c = 0.5 + f_first_term * sin_z - g_first_term * cos_z;
return Ok((sign * s, sign * c));
}
let z2 = z * z;
let z2_inv = 1.0 / z2;
let mut f = 1.0 / (PI * x);
let mut g = 0.0;
let mut prev_f = f;
let mut prev_g = g;
let mut num_stable_terms = 0;
for k in 1..25 {
let k_f64 = k as f64;
let mut z2_pow_k: f64 = z2_inv; for _ in 1..k {
z2_pow_k *= z2_inv;
if z2_pow_k.abs() < 1e-300 {
break; }
}
let f_term =
if k % 2 == 1 { -1.0 } else { 1.0 } * (4.0 * k_f64 - 1.0) * z2_pow_k / (PI * x);
let g_term = if k % 2 == 1 { -1.0 } else { 1.0 } * (4.0 * k_f64 + 1.0) * z2_pow_k
/ ((2.0 * k_f64 + 1.0) * PI);
f += f_term;
g += g_term;
let abs_tol = 1e-15;
let f_rel_tol = 1e-15 * f.abs().max(1e-300);
let g_rel_tol = 1e-15 * g.abs().max(1e-300);
if f_term.abs() < abs_tol && g_term.abs() < abs_tol {
break; }
if f_term.abs() < f_rel_tol && g_term.abs() < g_rel_tol {
break; }
if (f - prev_f).abs() < f_rel_tol && (g - prev_g).abs() < g_rel_tol {
num_stable_terms += 1;
if num_stable_terms > 2 {
break; }
} else {
num_stable_terms = 0;
}
if f_term.abs() > 100.0 * prev_f.abs() || g_term.abs() > 100.0 * prev_g.abs() {
f = prev_f;
g = prev_g;
break;
}
prev_f = f;
prev_g = g;
}
let s = 0.5 - f * cos_z - g * sin_z;
let c = 0.5 + f * sin_z - g * cos_z;
Ok((sign * s, sign * c))
}
#[allow(dead_code)]
fn fresnel_complex_power_series(z: Complex64) -> SpecialResult<(Complex64, Complex64)> {
if z.norm() < 1e-100 {
return Ok((Complex64::new(0.0, 0.0), Complex64::new(0.0, 0.0)));
}
let pi_half = Complex64::new(PI / 2.0, 0.0);
let t = pi_half * z * z;
let t2 = t * t;
let mut c_sum = Complex64::new(0.0, 0.0);
let mut c_term = Complex64::new(1.0, 0.0);
for n in 0..80 {
let denom = (4 * n + 1) as f64;
c_sum += c_term / denom;
let next_factor = -t2 / Complex64::new(((2 * n + 1) * (2 * n + 2)) as f64, 0.0);
c_term *= next_factor;
if !c_term.is_finite() {
break;
}
if c_term.norm() / denom < 1e-16 * c_sum.norm().max(1e-300) && n > 3 {
break;
}
}
let c = z * c_sum;
let mut s_sum = Complex64::new(0.0, 0.0);
let mut s_term = Complex64::new(1.0, 0.0);
for n in 0..80 {
let denom = (4 * n + 3) as f64;
s_sum += s_term / denom;
let next_factor = -t2 / Complex64::new(((2 * n + 2) * (2 * n + 3)) as f64, 0.0);
s_term *= next_factor;
if !s_term.is_finite() {
break;
}
if s_term.norm() / denom < 1e-16 * s_sum.norm().max(1e-300) && n > 3 {
break;
}
}
let s = z * t * s_sum;
Ok((s, c))
}
#[allow(dead_code)]
fn fresnel_complex_asymptotic(z: Complex64) -> SpecialResult<(Complex64, Complex64)> {
if !z.is_finite() {
return Err(SpecialError::DomainError(
"Infinite or NaN input to fresnel_complex_asymptotic".to_string(),
));
}
if z.norm() > 1e100 {
return Ok((Complex64::new(0.5, 0.0), Complex64::new(0.5, 0.0)));
}
let pi_z2_half = if z.norm() > 1e7 {
let scaled_z = z / 1e7;
PI * scaled_z * scaled_z * 1e14 / 2.0
} else {
PI * z * z / 2.0
};
let reduced_pi_z2_half = if pi_z2_half.norm() > 1e10 {
let two_pi = Complex64::new(2.0 * PI, 0.0);
let n = (pi_z2_half / two_pi).re.floor();
pi_z2_half - two_pi * Complex64::new(n, 0.0)
} else {
pi_z2_half
};
let sin_pi_z2_half = reduced_pi_z2_half.sin();
let cos_pi_z2_half = reduced_pi_z2_half.cos();
if z.norm() > 20.0 {
let f_first_term = Complex64::new(1.0, 0.0) / (PI * z);
let g_first_term = f_first_term / (3.0 * pi_z2_half);
let half = Complex64::new(0.5, 0.0);
let s = half - f_first_term * cos_pi_z2_half - g_first_term * sin_pi_z2_half;
let c = half + f_first_term * sin_pi_z2_half - g_first_term * cos_pi_z2_half;
return Ok((s, c));
}
let pi_z2_half_sq = pi_z2_half * pi_z2_half;
let mut f = Complex64::new(1.0, 0.0) / (PI * z);
let mut g = Complex64::new(0.0, 0.0);
let mut prev_f = f;
let mut prev_g = g;
let mut num_stable_terms = 0;
for k in 1..20 {
let k_f64 = k as f64;
let mut pi_z2_half_sq_pow_k = Complex64::new(1.0, 0.0);
for _ in 0..k {
pi_z2_half_sq_pow_k /= pi_z2_half_sq;
if !pi_z2_half_sq_pow_k.is_finite() || pi_z2_half_sq_pow_k.norm() < 1e-300 {
break;
}
}
let sign = if k % 2 == 1 { -1.0 } else { 1.0 };
let f_term = sign * (4.0 * k_f64 - 1.0) * pi_z2_half_sq_pow_k / (PI * z);
let g_term = sign * (4.0 * k_f64 + 1.0) * pi_z2_half_sq_pow_k / ((2.0 * k_f64 + 1.0) * PI);
if f_term.is_finite() {
f += f_term;
}
if g_term.is_finite() {
g += g_term;
}
let f_norm = f_term.norm();
let g_norm = g_term.norm();
let f_sum_norm = f.norm().max(1e-300);
let g_sum_norm = g.norm().max(1e-300);
if f_norm < 1e-15 && g_norm < 1e-15 {
break; }
if f_norm < 1e-15 * f_sum_norm && g_norm < 1e-15 * g_sum_norm {
break; }
if (f - prev_f).norm() < 1e-15 * f_sum_norm && (g - prev_g).norm() < 1e-15 * g_sum_norm {
num_stable_terms += 1;
if num_stable_terms > 2 {
break; }
} else {
num_stable_terms = 0;
}
if f_norm > 100.0 * prev_f.norm() || g_norm > 100.0 * prev_g.norm() {
f = prev_f;
g = prev_g;
break;
}
prev_f = f;
prev_g = g;
}
let half = Complex64::new(0.5, 0.0);
let s = half - f * cos_pi_z2_half - g * sin_pi_z2_half;
let c = half + f * sin_pi_z2_half - g * cos_pi_z2_half;
if !s.is_finite() || !c.is_finite() {
let s_approx = Complex64::new(0.5, 0.0);
let c_approx = Complex64::new(0.5, 0.0);
return Ok((s_approx, c_approx));
}
Ok((s, c))
}
#[allow(dead_code)]
pub fn fresnels(x: f64) -> SpecialResult<f64> {
let (s, _) = fresnel(x)?;
Ok(s)
}
#[allow(dead_code)]
pub fn fresnelc(x: f64) -> SpecialResult<f64> {
let (_, c) = fresnel(x)?;
Ok(c)
}
#[allow(dead_code)]
pub fn mod_fresnel_plus(x: f64) -> SpecialResult<(Complex64, Complex64)> {
if x.is_nan() {
return Err(SpecialError::DomainError(
"NaN input to mod_fresnel_plus".to_string(),
));
}
if x.abs() < 1e-100 {
let sqrt_pi = PI.sqrt();
let exp_i_pi_4 = Complex64::new(1.0, 0.0) * Complex64::new(0.5, 0.5).sqrt();
let f_plus_0 = sqrt_pi * exp_i_pi_4 / 2.0;
let k_plus_0 = Complex64::new(0.5, 0.0);
return Ok((f_plus_0, k_plus_0));
}
if x.abs() > 1e100 {
let zero = Complex64::new(0.0, 0.0);
return Ok((zero, zero));
}
let z = x.abs();
let (s, c) = fresnel(z)?;
let sqrt_pi = PI.sqrt();
let sqrt_pi_inv = 1.0 / sqrt_pi;
let phase = if z > 1e7 {
let scaled_z = z / 1e7;
let scaled_z_sq = scaled_z * scaled_z * 1e14;
Complex64::new(0.0, scaled_z_sq + PI / 4.0)
} else {
Complex64::new(0.0, z * z + PI / 4.0)
};
let reduced_phase = if phase.im.abs() > 100.0 {
let two_pi = 2.0 * PI;
let n = (phase.im / two_pi).floor();
Complex64::new(phase.re, phase.im - n * two_pi)
} else {
phase
};
let exp_phase = reduced_phase.exp();
let exp_i_pi_4 = Complex64::new(0.5, 0.5).sqrt();
let f_plus = if x >= 0.0 {
let halfminus_c = if z > 10.0 {
let _z_sq = z * z;
let pi_z = PI * z;
1.0 / (2.0 * pi_z) * z.cos() } else {
0.5 - c
};
let minus_s = if z > 10.0 {
let _z_sq = z * z;
let pi_z = PI * z;
-0.5 + 1.0 / (2.0 * pi_z) * z.sin() } else {
-s
};
let halfminus_cminus_is = Complex64::new(halfminus_c, minus_s);
halfminus_cminus_is * sqrt_pi * exp_i_pi_4
} else {
let half_plus_c = if z > 10.0 {
let _z_sq = z * z;
let pi_z = PI * z;
0.5 + 1.0 / (2.0 * pi_z) * z.cos()
} else {
0.5 + c
};
let plus_s = if z > 10.0 {
let _z_sq = z * z;
let pi_z = PI * z;
0.5 - 1.0 / (2.0 * pi_z) * z.sin()
} else {
s
};
let half_plus_c_plus_is = Complex64::new(half_plus_c, plus_s);
half_plus_c_plus_is * sqrt_pi * exp_i_pi_4
};
let k_plus_unnormalized = exp_phase.conj() * f_plus;
let k_plus = k_plus_unnormalized * sqrt_pi_inv;
if !f_plus.is_finite() || !k_plus.is_finite() {
if x.abs() > 10.0 {
let decay_factor = 1.0 / x.abs();
let f_plus_approx = Complex64::new(decay_factor, decay_factor);
let k_plus_approx = Complex64::new(decay_factor, -decay_factor) * sqrt_pi_inv;
return Ok((f_plus_approx, k_plus_approx));
}
}
Ok((f_plus, k_plus))
}
#[allow(dead_code)]
pub fn mod_fresnelminus(x: f64) -> SpecialResult<(Complex64, Complex64)> {
if x.is_nan() {
return Err(SpecialError::DomainError(
"NaN input to mod_fresnelminus".to_string(),
));
}
if x.abs() < 1e-100 {
let sqrt_pi = PI.sqrt();
let expminus_i_pi_4 = Complex64::new(1.0, 0.0) * Complex64::new(0.5, -0.5).sqrt();
let fminus_0 = sqrt_pi * expminus_i_pi_4 / 2.0;
let kminus_0 = Complex64::new(0.5, 0.0);
return Ok((fminus_0, kminus_0));
}
if x.abs() > 1e100 {
let zero = Complex64::new(0.0, 0.0);
return Ok((zero, zero));
}
let z = x.abs();
let (s, c) = fresnel(z)?;
let sqrt_pi = PI.sqrt();
let sqrt_pi_inv = 1.0 / sqrt_pi;
let phase = if z > 1e7 {
let scaled_z = z / 1e7;
let scaled_z_sq = scaled_z * scaled_z * 1e14;
Complex64::new(0.0, scaled_z_sq + PI / 4.0)
} else {
Complex64::new(0.0, z * z + PI / 4.0)
};
let reduced_phase = if phase.im.abs() > 100.0 {
let two_pi = 2.0 * PI;
let n = (phase.im / two_pi).floor();
Complex64::new(phase.re, phase.im - n * two_pi)
} else {
phase
};
let exp_phase = reduced_phase.exp();
let expminus_i_pi_4 = Complex64::new(0.5, -0.5).sqrt();
let fminus = if x >= 0.0 {
let halfminus_c = if z > 10.0 {
let pi_z = PI * z;
1.0 / (2.0 * pi_z) * z.cos() } else {
0.5 - c
};
let plus_s = if z > 10.0 {
let pi_z = PI * z;
0.5 - 1.0 / (2.0 * pi_z) * z.sin() } else {
s
};
let halfminus_c_plus_is = Complex64::new(halfminus_c, plus_s);
halfminus_c_plus_is * sqrt_pi * expminus_i_pi_4
} else {
let half_plus_c = if z > 10.0 {
let pi_z = PI * z;
0.5 + 1.0 / (2.0 * pi_z) * z.cos()
} else {
0.5 + c
};
let minus_s = if z > 10.0 {
let pi_z = PI * z;
-0.5 + 1.0 / (2.0 * pi_z) * z.sin()
} else {
-s
};
let half_plus_cminus_is = Complex64::new(half_plus_c, minus_s);
half_plus_cminus_is * sqrt_pi * expminus_i_pi_4
};
let kminus_unnormalized = exp_phase * fminus;
let kminus = kminus_unnormalized * sqrt_pi_inv;
if !fminus.is_finite() || !kminus.is_finite() {
if x.abs() > 10.0 {
let decay_factor = 1.0 / x.abs();
let fminus_approx = Complex64::new(decay_factor, -decay_factor);
let kminus_approx = Complex64::new(decay_factor, decay_factor) * sqrt_pi_inv;
return Ok((fminus_approx, kminus_approx));
}
}
Ok((fminus, kminus))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_fresnel_at_zero() {
let (s, c) = fresnel(0.0).expect("fresnel(0) failed");
assert!((s - 0.0).abs() < 1e-14, "S(0) should be 0, got {s}");
assert!((c - 0.0).abs() < 1e-14, "C(0) should be 0, got {c}");
}
#[test]
fn test_fresnel_at_one() {
let (s, c) = fresnel(1.0).expect("fresnel(1) failed");
assert!((s - 0.438_259_147).abs() < 1e-6, "S(1) ~ 0.438259, got {s}");
assert!((c - 0.779_893_400).abs() < 1e-6, "C(1) ~ 0.779893, got {c}");
}
#[test]
fn test_fresnel_at_two() {
let (s, c) = fresnel(2.0).expect("fresnel(2) failed");
assert!((s - 0.343_415).abs() < 1e-4, "S(2) ~ 0.3434, got {s}");
assert!((c - 0.488_253).abs() < 1e-4, "C(2) ~ 0.4883, got {c}");
}
#[test]
fn test_fresnel_large_x_approaches_half() {
let (s, c) = fresnel(50.0).expect("fresnel(50) failed");
assert!((s - 0.5).abs() < 0.05, "S(50) should be near 0.5, got {s}");
assert!((c - 0.5).abs() < 0.05, "C(50) should be near 0.5, got {c}");
}
#[test]
fn test_fresnel_odd_symmetry() {
let (s_pos, c_pos) = fresnel(1.5).expect("fresnel(1.5) failed");
let (s_neg, c_neg) = fresnel(-1.5).expect("fresnel(-1.5) failed");
assert!(
(s_neg + s_pos).abs() < 1e-10,
"S should be odd: S(1.5)={s_pos}, S(-1.5)={s_neg}"
);
assert!(
(c_neg + c_pos).abs() < 1e-10,
"C should be odd: C(1.5)={c_pos}, C(-1.5)={c_neg}"
);
}
#[test]
fn test_fresnel_nan_input() {
let result = fresnel(f64::NAN);
assert!(
result.is_err(),
"fresnel with NaN input should return error"
);
}
#[test]
fn test_fresnels_at_zero() {
let s = fresnels(0.0).expect("fresnels(0) failed");
assert!((s - 0.0).abs() < 1e-14, "S(0) should be 0, got {s}");
}
#[test]
fn test_fresnels_at_one() {
let s = fresnels(1.0).expect("fresnels(1) failed");
assert!((s - 0.438_259_147).abs() < 1e-6, "S(1) ~ 0.438259, got {s}");
}
#[test]
fn test_fresnels_matches_fresnel() {
let s1 = fresnels(2.5).expect("fresnels(2.5) failed");
let (s2, _) = fresnel(2.5).expect("fresnel(2.5) failed");
assert!(
(s1 - s2).abs() < 1e-10,
"fresnels should match fresnel: {s1} vs {s2}"
);
}
#[test]
fn test_fresnels_nan() {
let result = fresnels(f64::NAN);
assert!(
result.is_err(),
"fresnels with NaN input should return error"
);
}
#[test]
fn test_fresnels_negative() {
let s_pos = fresnels(1.0).expect("fresnels(1) failed");
let s_neg = fresnels(-1.0).expect("fresnels(-1) failed");
assert!((s_neg + s_pos).abs() < 1e-10, "S should be odd function");
}
#[test]
fn test_fresnelc_at_zero() {
let c = fresnelc(0.0).expect("fresnelc(0) failed");
assert!((c - 0.0).abs() < 1e-14, "C(0) should be 0, got {c}");
}
#[test]
fn test_fresnelc_at_one() {
let c = fresnelc(1.0).expect("fresnelc(1) failed");
assert!((c - 0.779_893_400).abs() < 1e-6, "C(1) ~ 0.779893, got {c}");
}
#[test]
fn test_fresnelc_matches_fresnel() {
let c1 = fresnelc(2.5).expect("fresnelc(2.5) failed");
let (_, c2) = fresnel(2.5).expect("fresnel(2.5) failed");
assert!(
(c1 - c2).abs() < 1e-10,
"fresnelc should match fresnel: {c1} vs {c2}"
);
}
#[test]
fn test_fresnelc_nan() {
let result = fresnelc(f64::NAN);
assert!(
result.is_err(),
"fresnelc with NaN input should return error"
);
}
#[test]
fn test_fresnelc_negative() {
let c_pos = fresnelc(1.0).expect("fresnelc(1) failed");
let c_neg = fresnelc(-1.0).expect("fresnelc(-1) failed");
assert!((c_neg + c_pos).abs() < 1e-10, "C should be odd function");
}
#[test]
fn test_fresnel_complex_real_axis() {
let z = Complex64::new(1.0, 0.0);
let (s_c, c_c) = fresnel_complex(z).expect("fresnel_complex failed");
let (s_r, c_r) = fresnel(1.0).expect("fresnel failed");
assert!(
(s_c.re - s_r).abs() < 1e-8,
"complex fresnel S on real axis should match: {s_c} vs {s_r}"
);
assert!(
s_c.im.abs() < 1e-8,
"imaginary part of S on real axis should be ~0"
);
assert!(
(c_c.re - c_r).abs() < 1e-8,
"complex fresnel C on real axis should match: {c_c} vs {c_r}"
);
}
#[test]
fn test_fresnel_complex_at_zero() {
let z = Complex64::new(0.0, 0.0);
let (s, c) = fresnel_complex(z).expect("fresnel_complex(0) failed");
assert!(s.norm() < 1e-14, "S(0) should be 0");
assert!(c.norm() < 1e-14, "C(0) should be 0");
}
#[test]
fn test_fresnel_complex_purely_imaginary() {
let z = Complex64::new(0.0, 1.0);
let (s, c) = fresnel_complex(z).expect("fresnel_complex(i) failed");
assert!(s.is_finite(), "S(i) should be finite");
assert!(c.is_finite(), "C(i) should be finite");
}
#[test]
fn test_fresnel_complex_nan() {
let z = Complex64::new(f64::NAN, 0.0);
let result = fresnel_complex(z);
assert!(
result.is_err(),
"fresnel_complex with NaN should return error"
);
}
#[test]
fn test_fresnel_complex_moderate() {
let z = Complex64::new(1.0, 0.5);
let (s, c) = fresnel_complex(z).expect("fresnel_complex(1+0.5i) failed");
assert!(s.is_finite(), "S(1+0.5i) should be finite");
assert!(c.is_finite(), "C(1+0.5i) should be finite");
}
#[test]
fn test_mod_fresnel_plus_at_zero() {
let (f_plus, k_plus) = mod_fresnel_plus(0.0).expect("mod_fresnel_plus(0) failed");
assert!(f_plus.is_finite(), "F+(0) should be finite");
assert!(k_plus.is_finite(), "K+(0) should be finite");
}
#[test]
fn test_mod_fresnel_plus_at_one() {
let (f_plus, k_plus) = mod_fresnel_plus(1.0).expect("mod_fresnel_plus(1) failed");
assert!(f_plus.is_finite(), "F+(1) should be finite");
assert!(k_plus.is_finite(), "K+(1) should be finite");
}
#[test]
fn test_mod_fresnel_plus_moderate_x() {
let (f_plus, k_plus) = mod_fresnel_plus(5.0).expect("mod_fresnel_plus(5) failed");
assert!(f_plus.is_finite(), "F+(5) should be finite");
assert!(k_plus.is_finite(), "K+(5) should be finite");
}
#[test]
fn test_mod_fresnel_plus_negative() {
let (f_plus, k_plus) = mod_fresnel_plus(-1.0).expect("mod_fresnel_plus(-1) failed");
assert!(f_plus.is_finite(), "F+(-1) should be finite");
assert!(k_plus.is_finite(), "K+(-1) should be finite");
}
#[test]
fn test_mod_fresnel_plus_large_x() {
let (f_plus, k_plus) = mod_fresnel_plus(20.0).expect("mod_fresnel_plus(20) failed");
assert!(f_plus.is_finite(), "F+(20) should be finite");
assert!(k_plus.is_finite(), "K+(20) should be finite");
}
#[test]
fn test_mod_fresnelminus_at_zero() {
let (fminus, kminus) = mod_fresnelminus(0.0).expect("mod_fresnelminus(0) failed");
assert!(fminus.is_finite(), "F-(0) should be finite");
assert!(kminus.is_finite(), "K-(0) should be finite");
}
#[test]
fn test_mod_fresnelminus_at_one() {
let (fminus, kminus) = mod_fresnelminus(1.0).expect("mod_fresnelminus(1) failed");
assert!(fminus.is_finite(), "F-(1) should be finite");
assert!(kminus.is_finite(), "K-(1) should be finite");
}
#[test]
fn test_mod_fresnelminus_moderate_x() {
let (fminus, kminus) = mod_fresnelminus(5.0).expect("mod_fresnelminus(5) failed");
assert!(fminus.is_finite(), "F-(5) should be finite");
assert!(kminus.is_finite(), "K-(5) should be finite");
}
#[test]
fn test_mod_fresnelminus_negative() {
let (fminus, kminus) = mod_fresnelminus(-1.0).expect("mod_fresnelminus(-1) failed");
assert!(fminus.is_finite(), "F-(-1) should be finite");
assert!(kminus.is_finite(), "K-(-1) should be finite");
}
#[test]
fn test_mod_fresnelminus_large_x() {
let (fminus, kminus) = mod_fresnelminus(20.0).expect("mod_fresnelminus(20) failed");
assert!(fminus.is_finite(), "F-(20) should be finite");
assert!(kminus.is_finite(), "K-(20) should be finite");
}
}