use crate::ArgSpec;
use crate::Globals;
use crate::NativeModule;
use crate::RcStr;
use crate::Result;
use crate::Value;
use std::collections::HashMap;
pub(super) fn new() -> NativeModule {
NativeModule::new("a.math", |builder| {
builder
.val("pi", "", std::f64::consts::PI)
.val("tau", "", std::f64::consts::PI * 2.0)
.val("e", "", std::f64::consts::E)
.func("sin", ["x"], "Computes sin in radians", wrap1(f64::sin))
.func("cos", ["x"], "Computes cos in radians", wrap1(f64::cos))
.func("tan", ["x"], "Computes tan in radians", wrap1(f64::tan))
.func("asin", ["x"], "Computes asin in radians", wrap1(f64::asin))
.func("acos", ["x"], "Computes acos in radians", wrap1(f64::acos))
.func("atan", ["x"], "Computes atan in radians", wrap1(f64::atan))
.func(
"atan2",
["y", "x"],
"Computes atan2 in radians",
wrap2(f64::atan2),
)
.func("sinh", ["x"], "Computes sinh in radians", wrap1(f64::sinh))
.func("cosh", ["x"], "Computes cosh in radians", wrap1(f64::cosh))
.func("tanh", ["x"], "Computes tanh in radians", wrap1(f64::tanh))
.func(
"log",
ArgSpec::builder().req("x").def("base", std::f64::consts::E),
"Computes the logarithm.\nIf not specified, the base defaults to e",
wrap2(f64::log),
)
.func("log10", ["x"], "Computes log base 10", wrap1(f64::log10))
.func("abs", ["x"], "Absolute value", wrap1(f64::abs))
.func(
"sqrt",
["x"],
"Returns the square root of a number",
wrap1(f64::sqrt),
)
.func(
"ln",
["x"],
"Computes the natural logarithm",
wrap1(f64::ln),
)
.func("log2", ["x"], "Computes log base 2", wrap1(f64::log2));
})
}
fn wrap1<F: Fn(f64) -> f64 + 'static>(
f: F,
) -> impl Fn(&mut Globals, Vec<Value>, Option<HashMap<RcStr, Value>>) -> Result<Value> + 'static {
move |_, args, _| {
let x = args.into_iter().next().unwrap().number()?;
Ok(Value::from(f(x)))
}
}
fn wrap2<F: Fn(f64, f64) -> f64 + 'static>(
f: F,
) -> impl Fn(&mut Globals, Vec<Value>, Option<HashMap<RcStr, Value>>) -> Result<Value> + 'static {
move |_, args, _| {
let mut args = args.into_iter();
let a = args.next().unwrap().number()?;
let b = args.next().unwrap().number()?;
Ok(Value::from(f(a, b)))
}
}