use super::Args;
use super::FfiContext;
use super::Result;
use super::macros::*;
use crate::interpreter::RuntimeErrorKind;
use crate::quantity::Quantity;
use crate::typechecker::type_scheme::TypeScheme;
use crate::value::Value;
pub fn mod_(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let x = quantity_arg!(args);
let y = quantity_arg!(args);
let x_value = x.unsafe_value().to_f64();
let y_value = y.convert_to(x.unit()).unwrap().unsafe_value().to_f64();
return_quantity!(x_value.rem_euclid(y_value), x.unit().clone())
}
macro_rules! simple_scalar_math_function {
($name:ident, $op:ident) => {
pub fn $name(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let value = scalar_arg!(args).to_f64();
return_scalar!(value.$op())
}
};
}
pub fn abs(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let arg = quantity_arg!(args);
return_quantity!(arg.unsafe_value().to_f64().abs(), arg.unit().clone())
}
simple_scalar_math_function!(round, round);
simple_scalar_math_function!(floor, floor);
simple_scalar_math_function!(ceil, ceil);
simple_scalar_math_function!(trunc, trunc);
simple_scalar_math_function!(fract, fract);
simple_scalar_math_function!(sin, sin);
simple_scalar_math_function!(cos, cos);
simple_scalar_math_function!(tan, tan);
simple_scalar_math_function!(asin, asin);
simple_scalar_math_function!(acos, acos);
simple_scalar_math_function!(atan, atan);
pub fn atan2(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let y = quantity_arg!(args);
let x = quantity_arg!(args);
let y_value = y.unsafe_value().to_f64();
let x_value = x.convert_to(y.unit()).unwrap().unsafe_value().to_f64();
return_scalar!(y_value.atan2(x_value))
}
simple_scalar_math_function!(sinh, sinh);
simple_scalar_math_function!(cosh, cosh);
simple_scalar_math_function!(tanh, tanh);
simple_scalar_math_function!(asinh, asinh);
simple_scalar_math_function!(acosh, acosh);
simple_scalar_math_function!(atanh, atanh);
simple_scalar_math_function!(exp, exp);
simple_scalar_math_function!(ln, ln);
simple_scalar_math_function!(log10, log10);
simple_scalar_math_function!(log2, log2);
pub fn gamma(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let input = scalar_arg!(args).to_f64();
return_scalar!(crate::gamma::gamma(input))
}
pub fn is_nan(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let arg = quantity_arg!(args);
return_boolean!(arg.unsafe_value().to_f64().is_nan())
}
pub fn is_infinite(
_ctx: &mut FfiContext,
mut args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
let arg = quantity_arg!(args);
return_boolean!(arg.unsafe_value().to_f64().is_infinite())
}
pub fn random(
_ctx: &mut FfiContext,
_args: Args,
_return_type: &TypeScheme,
) -> Result<Value, Box<RuntimeErrorKind>> {
return_scalar!(rand::random::<f64>())
}