2020-04-21 17:01:10 +02:00
|
|
|
use crate::def_package;
|
2020-04-20 18:11:25 +02:00
|
|
|
use crate::parser::INT;
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use crate::parser::FLOAT;
|
|
|
|
|
2020-07-26 09:53:22 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use crate::{result::EvalAltResult, token::Position};
|
|
|
|
|
2020-07-20 17:23:12 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
2020-07-31 16:30:23 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use num_traits::float::Float;
|
2020-07-20 14:23:35 +02:00
|
|
|
|
2020-07-26 09:53:22 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use crate::stdlib::{boxed::Box, format};
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
#[allow(dead_code)]
|
2020-04-20 18:11:25 +02:00
|
|
|
#[cfg(feature = "only_i32")]
|
2020-04-20 18:24:25 +02:00
|
|
|
pub const MAX_INT: INT = i32::MAX;
|
2020-07-31 16:30:23 +02:00
|
|
|
#[allow(dead_code)]
|
2020-04-20 18:11:25 +02:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
2020-04-20 18:24:25 +02:00
|
|
|
pub const MAX_INT: INT = i64::MAX;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-04-22 08:55:40 +02:00
|
|
|
def_package!(crate:BasicMathPackage:"Basic mathematic functions.", lib, {
|
2020-04-21 17:01:10 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
|
|
|
// Advanced math functions
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("sin", |x: FLOAT| Ok(x.to_radians().sin()));
|
|
|
|
lib.set_fn_1("cos", |x: FLOAT| Ok(x.to_radians().cos()));
|
|
|
|
lib.set_fn_1("tan", |x: FLOAT| Ok(x.to_radians().tan()));
|
|
|
|
lib.set_fn_1("sinh", |x: FLOAT| Ok(x.to_radians().sinh()));
|
|
|
|
lib.set_fn_1("cosh", |x: FLOAT| Ok(x.to_radians().cosh()));
|
|
|
|
lib.set_fn_1("tanh", |x: FLOAT| Ok(x.to_radians().tanh()));
|
|
|
|
lib.set_fn_1("asin", |x: FLOAT| Ok(x.asin().to_degrees()));
|
|
|
|
lib.set_fn_1("acos", |x: FLOAT| Ok(x.acos().to_degrees()));
|
|
|
|
lib.set_fn_1("atan", |x: FLOAT| Ok(x.atan().to_degrees()));
|
|
|
|
lib.set_fn_1("asinh", |x: FLOAT| Ok(x.asinh().to_degrees()));
|
|
|
|
lib.set_fn_1("acosh", |x: FLOAT| Ok(x.acosh().to_degrees()));
|
|
|
|
lib.set_fn_1("atanh", |x: FLOAT| Ok(x.atanh().to_degrees()));
|
|
|
|
lib.set_fn_1("sqrt", |x: FLOAT| Ok(x.sqrt()));
|
|
|
|
lib.set_fn_1("exp", |x: FLOAT| Ok(x.exp()));
|
|
|
|
lib.set_fn_1("ln", |x: FLOAT| Ok(x.ln()));
|
|
|
|
lib.set_fn_2("log", |x: FLOAT, base: FLOAT| Ok(x.log(base)));
|
|
|
|
lib.set_fn_1("log10", |x: FLOAT| Ok(x.log10()));
|
|
|
|
lib.set_fn_1("floor", |x: FLOAT| Ok(x.floor()));
|
|
|
|
lib.set_fn_1("ceiling", |x: FLOAT| Ok(x.ceil()));
|
|
|
|
lib.set_fn_1("round", |x: FLOAT| Ok(x.ceil()));
|
|
|
|
lib.set_fn_1("int", |x: FLOAT| Ok(x.trunc()));
|
|
|
|
lib.set_fn_1("fraction", |x: FLOAT| Ok(x.fract()));
|
|
|
|
lib.set_fn_1("is_nan", |x: FLOAT| Ok(x.is_nan()));
|
|
|
|
lib.set_fn_1("is_finite", |x: FLOAT| Ok(x.is_finite()));
|
|
|
|
lib.set_fn_1("is_infinite", |x: FLOAT| Ok(x.is_infinite()));
|
2020-04-21 17:01:10 +02:00
|
|
|
|
2020-05-30 04:30:21 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
{
|
|
|
|
lib.set_getter_fn("floor", |x: &mut FLOAT| Ok(x.floor()));
|
|
|
|
lib.set_getter_fn("ceiling", |x: &mut FLOAT| Ok(x.ceil()));
|
|
|
|
lib.set_getter_fn("round", |x: &mut FLOAT| Ok(x.ceil()));
|
|
|
|
lib.set_getter_fn("int", |x: &mut FLOAT| Ok(x.trunc()));
|
|
|
|
lib.set_getter_fn("fraction", |x: &mut FLOAT| Ok(x.fract()));
|
|
|
|
lib.set_getter_fn("is_nan", |x: &mut FLOAT| Ok(x.is_nan()));
|
|
|
|
lib.set_getter_fn("is_finite", |x: &mut FLOAT| Ok(x.is_finite()));
|
|
|
|
lib.set_getter_fn("is_infinite", |x: &mut FLOAT| Ok(x.is_infinite()));
|
|
|
|
}
|
|
|
|
|
2020-04-21 17:01:10 +02:00
|
|
|
// Register conversion functions
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_float", |x: INT| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: f32| Ok(x as FLOAT));
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && cfg!(not(feature = "only_i64")) {
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_float", |x: i8| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: u8| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: i16| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: u16| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: i32| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: u32| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: i64| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: u64| Ok(x as FLOAT));
|
2020-06-17 10:50:46 +02:00
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(not(target_arch = "wasm32")) {
|
2020-06-17 10:50:46 +02:00
|
|
|
lib.set_fn_1("to_float", |x: i128| Ok(x as FLOAT));
|
|
|
|
lib.set_fn_1("to_float", |x: u128| Ok(x as FLOAT));
|
|
|
|
}
|
2020-04-21 17:01:10 +02:00
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_int", |ch: char| Ok(ch as INT));
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && cfg!(not(feature = "only_i64")) {
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_int", |x: i8| Ok(x as INT));
|
|
|
|
lib.set_fn_1("to_int", |x: u8| Ok(x as INT));
|
|
|
|
lib.set_fn_1("to_int", |x: i16| Ok(x as INT));
|
|
|
|
lib.set_fn_1("to_int", |x: u16| Ok(x as INT));
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) {
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_int", |x: i32| Ok(x as INT));
|
|
|
|
lib.set_fn_1("to_int", |x: u64| Ok(x as INT));
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(feature = "only_i64") {
|
|
|
|
lib.set_fn_1("to_int", |x: u32| Ok(x as INT));
|
|
|
|
}
|
2020-04-21 17:01:10 +02:00
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-04-21 17:01:10 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1(
|
2020-04-21 17:01:10 +02:00
|
|
|
"to_int",
|
|
|
|
|x: f32| {
|
|
|
|
if x > (MAX_INT as f32) {
|
2020-04-21 17:25:12 +02:00
|
|
|
return Err(Box::new(EvalAltResult::ErrorArithmetic(
|
2020-04-21 17:01:10 +02:00
|
|
|
format!("Integer overflow: to_int({})", x),
|
|
|
|
Position::none(),
|
2020-04-21 17:25:12 +02:00
|
|
|
)));
|
2020-04-21 17:01:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(x.trunc() as INT)
|
|
|
|
},
|
|
|
|
);
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1(
|
2020-04-21 17:01:10 +02:00
|
|
|
"to_int",
|
|
|
|
|x: FLOAT| {
|
|
|
|
if x > (MAX_INT as FLOAT) {
|
2020-04-21 17:25:12 +02:00
|
|
|
return Err(Box::new(EvalAltResult::ErrorArithmetic(
|
2020-04-21 17:01:10 +02:00
|
|
|
format!("Integer overflow: to_int({})", x),
|
|
|
|
Position::none(),
|
2020-04-21 17:25:12 +02:00
|
|
|
)));
|
2020-04-21 17:01:10 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(x.trunc() as INT)
|
|
|
|
},
|
|
|
|
);
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2020-07-31 16:30:23 +02:00
|
|
|
if cfg!(feature = "unchecked") {
|
2020-05-13 13:21:42 +02:00
|
|
|
lib.set_fn_1("to_int", |x: f32| Ok(x as INT));
|
|
|
|
lib.set_fn_1("to_int", |x: f64| Ok(x as INT));
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-21 17:01:10 +02:00
|
|
|
});
|