use slatec_sys::special as raw;
use crate::special::{SpecialFunctionError, runtime};
fn validate(
function: &'static str,
x: f64,
coefficient_count: usize,
) -> Result<(), SpecialFunctionError> {
if !x.is_finite() || !(-1.0..=1.0).contains(&x) {
return Err(SpecialFunctionError::Domain {
function,
argument: "x",
value: x,
});
}
if coefficient_count == 0 || coefficient_count > 1000 {
return Err(SpecialFunctionError::Domain {
function,
argument: "coefficients.len()",
value: coefficient_count as f64,
});
}
Ok(())
}
pub fn chebyshev_series(x: f64, coefficients: &[f64]) -> Result<f64, SpecialFunctionError> {
validate("chebyshev_series", x, coefficients.len())?;
let _guard = runtime::lock_fnlib();
let (mut x, mut n) = (
x,
runtime::integer(
"chebyshev_series",
"coefficients.len()",
i32::try_from(coefficients.len()).map_err(|_| {
SpecialFunctionError::IntegerOverflow {
function: "chebyshev_series",
argument: "coefficients.len()",
}
})?,
)?,
);
Ok(unsafe { raw::dcsevl(&mut x, coefficients.as_ptr().cast_mut(), &mut n) })
}
#[cfg(feature = "special-f32")]
pub fn chebyshev_series_f32(x: f32, coefficients: &[f32]) -> Result<f32, SpecialFunctionError> {
validate("chebyshev_series_f32", f64::from(x), coefficients.len())?;
let _guard = runtime::lock_fnlib();
let (mut x, mut n) = (
x,
runtime::integer(
"chebyshev_series_f32",
"coefficients.len()",
i32::try_from(coefficients.len()).map_err(|_| {
SpecialFunctionError::IntegerOverflow {
function: "chebyshev_series_f32",
argument: "coefficients.len()",
}
})?,
)?,
);
Ok(unsafe { raw::csevl(&mut x, coefficients.as_ptr().cast_mut(), &mut n) })
}