use crate::{
exec::Interpreter,
js::{
function::NativeFunctionData,
value::{from_value, to_value, ResultValue, Value, ValueData},
},
};
use rand::random;
use std::f64;
pub fn abs(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.abs()
}))
}
pub fn acos(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.acos()
}))
}
pub fn asin(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.asin()
}))
}
pub fn atan(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.atan()
}))
}
pub fn atan2(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.atan2(args.get(1).unwrap().to_num())
}))
}
pub fn cbrt(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.cbrt()
}))
}
pub fn ceil(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.ceil()
}))
}
pub fn cos(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.cos()
}))
}
pub fn exp(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.exp()
}))
}
pub fn floor(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.floor()
}))
}
pub fn log(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.log(f64::consts::E)
}))
}
pub fn max(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
let mut max = f64::NEG_INFINITY;
for arg in args {
let num = arg.to_num();
max = max.max(num);
}
Ok(to_value(max))
}
pub fn min(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
let mut max = f64::INFINITY;
for arg in args {
let num = arg.to_num();
max = max.min(num);
}
Ok(to_value(max))
}
pub fn pow(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.len() >= 2 {
let num: f64 = from_value(args.get(0).unwrap().clone()).unwrap();
let power: f64 = from_value(args.get(1).unwrap().clone()).unwrap();
num.powf(power)
} else {
f64::NAN
}))
}
pub fn _random(_: &Value, _: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(random::<f64>()))
}
pub fn round(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.round()
}))
}
pub fn sin(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.sin()
}))
}
pub fn sqrt(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.sqrt()
}))
}
pub fn tan(_: &Value, args: &[Value], _: &Interpreter) -> ResultValue {
Ok(to_value(if args.is_empty() {
f64::NAN
} else {
from_value::<f64>(args.get(0).unwrap().clone())
.unwrap()
.tan()
}))
}
pub fn _create(global: &Value) -> Value {
let math = ValueData::new_obj(Some(global));
math.set_field_slice("E", to_value(f64::consts::E));
math.set_field_slice("LN2", to_value(f64::consts::LN_2));
math.set_field_slice("LN10", to_value(f64::consts::LN_10));
math.set_field_slice("LOG2E", to_value(f64::consts::LOG2_E));
math.set_field_slice("LOG10E", to_value(f64::consts::LOG10_E));
math.set_field_slice("SQRT1_2", to_value(0.5_f64.sqrt()));
math.set_field_slice("SQRT2", to_value(f64::consts::SQRT_2));
math.set_field_slice("PI", to_value(f64::consts::PI));
math.set_field_slice("abs", to_value(abs as NativeFunctionData));
math.set_field_slice("acos", to_value(acos as NativeFunctionData));
math.set_field_slice("asin", to_value(asin as NativeFunctionData));
math.set_field_slice("atan", to_value(atan as NativeFunctionData));
math.set_field_slice("atan2", to_value(atan2 as NativeFunctionData));
math.set_field_slice("cbrt", to_value(cbrt as NativeFunctionData));
math.set_field_slice("ceil", to_value(ceil as NativeFunctionData));
math.set_field_slice("cos", to_value(cos as NativeFunctionData));
math.set_field_slice("exp", to_value(exp as NativeFunctionData));
math.set_field_slice("floor", to_value(floor as NativeFunctionData));
math.set_field_slice("log", to_value(log as NativeFunctionData));
math.set_field_slice("max", to_value(max as NativeFunctionData));
math.set_field_slice("min", to_value(min as NativeFunctionData));
math.set_field_slice("pow", to_value(pow as NativeFunctionData));
math.set_field_slice("random", to_value(_random as NativeFunctionData));
math.set_field_slice("round", to_value(round as NativeFunctionData));
math.set_field_slice("sin", to_value(sin as NativeFunctionData));
math.set_field_slice("sqrt", to_value(sqrt as NativeFunctionData));
math.set_field_slice("tan", to_value(tan as NativeFunctionData));
math
}
pub fn init(global: &Value) {
global.set_field_slice("Math", _create(global));
}