#[inline]
pub fn sin(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::sin(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.sin()
}
}
#[inline]
pub fn cos(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::cos(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.cos()
}
}
#[inline]
pub fn sin_cos(x: f64) -> (f64, f64) {
#[cfg(feature = "portable-fp")]
{
libm::sincos(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.sin_cos()
}
}
#[inline]
pub fn atan2(y: f64, x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::atan2(y, x)
}
#[cfg(not(feature = "portable-fp"))]
{
y.atan2(x)
}
}
#[inline]
pub fn acos(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::acos(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.acos()
}
}
#[inline]
pub fn pow(x: f64, y: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::pow(x, y)
}
#[cfg(not(feature = "portable-fp"))]
{
x.powf(y)
}
}
#[inline]
pub fn tanh(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::tanh(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.tanh()
}
}
#[inline]
pub fn exp(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::exp(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.exp()
}
}
#[inline]
pub fn ln(x: f64) -> f64 {
#[cfg(feature = "portable-fp")]
{
libm::log(x)
}
#[cfg(not(feature = "portable-fp"))]
{
x.ln()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn agrees_with_std_to_a_few_ulp() {
let xs: [f64; 12] = [
-3.0,
-1.25,
-0.5,
-1e-9,
0.0,
1e-9,
0.5,
1.0,
1.25,
2.0,
3.0,
std::f64::consts::TAU,
];
for x in xs {
let tol = 8.0 * f64::EPSILON * (1.0 + x.abs());
assert!((sin(x) - x.sin()).abs() <= tol, "sin({x})");
assert!((cos(x) - x.cos()).abs() <= tol, "cos({x})");
assert!((tanh(x) - x.tanh()).abs() <= tol, "tanh({x})");
let (s, c) = sin_cos(x);
assert_eq!((s, c), (sin(x), cos(x)), "sin_cos({x}) tuple order");
assert!((atan2(x, 1.5) - x.atan2(1.5)).abs() <= tol, "atan2({x})");
if x > 0.0 {
assert!((pow(x, 1.5) - x.powf(1.5)).abs() <= 8.0 * tol, "pow({x})");
assert!((ln(x) - x.ln()).abs() <= 8.0 * tol, "ln({x})");
}
}
assert!((acos(0.25) - 0.25f64.acos()).abs() <= 8.0 * f64::EPSILON);
}
}