2020-04-21 17:01:10 +02:00
|
|
|
use crate::def_package;
|
2020-08-15 02:37:16 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
2020-08-14 18:04:10 +02:00
|
|
|
use crate::engine::make_getter;
|
2020-04-20 18:11:25 +02:00
|
|
|
use crate::parser::INT;
|
2020-08-13 08:57:46 +02:00
|
|
|
use crate::plugin::*;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
|
|
|
#[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"))]
|
2020-08-06 04:17:32 +02:00
|
|
|
use crate::stdlib::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"))]
|
|
|
|
{
|
2020-08-13 08:57:46 +02:00
|
|
|
// Floating point functions
|
2020-08-14 18:04:10 +02:00
|
|
|
lib.combine(exported_module!(float_functions));
|
2020-04-21 17:01:10 +02:00
|
|
|
|
2020-08-13 08:57:46 +02:00
|
|
|
// Floating point properties
|
2020-05-30 04:30:21 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
{
|
2020-08-14 18:04:10 +02:00
|
|
|
set_exported_fn!(lib, make_getter("floor"), float_funcs::floor);
|
|
|
|
set_exported_fn!(lib, make_getter("ceiling"), float_funcs::ceiling);
|
|
|
|
set_exported_fn!(lib, make_getter("round"), float_funcs::round);
|
|
|
|
set_exported_fn!(lib, make_getter("int"), float_funcs::int);
|
|
|
|
set_exported_fn!(lib, make_getter("fraction"), float_funcs::fraction);
|
|
|
|
set_exported_fn!(lib, make_getter("is_nan"), float_funcs::is_nan);
|
|
|
|
set_exported_fn!(lib, make_getter("is_finite"), float_funcs::is_finite);
|
|
|
|
set_exported_fn!(lib, make_getter("is_infinite"), float_funcs::is_infinite);
|
2020-05-30 04:30:21 +02:00
|
|
|
}
|
|
|
|
|
2020-08-13 08:57:46 +02:00
|
|
|
// Trig functions
|
2020-08-14 18:04:10 +02:00
|
|
|
lib.combine(exported_module!(trig_functions));
|
2020-08-13 08:57:46 +02:00
|
|
|
|
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-08-13 08:57:46 +02:00
|
|
|
lib.set_fn_1("to_int", |x: f32| {
|
|
|
|
if x > (MAX_INT as f32) {
|
|
|
|
return EvalAltResult::ErrorArithmetic(
|
|
|
|
format!("Integer overflow: to_int({})", x),
|
|
|
|
Position::none(),
|
|
|
|
)
|
|
|
|
.into();
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(x.trunc() as INT)
|
|
|
|
});
|
|
|
|
lib.set_fn_1("to_int", |x: FLOAT| {
|
|
|
|
if x > (MAX_INT as FLOAT) {
|
|
|
|
return EvalAltResult::ErrorArithmetic(
|
|
|
|
format!("Integer overflow: to_int({})", x),
|
|
|
|
Position::none(),
|
|
|
|
)
|
|
|
|
.into();
|
|
|
|
}
|
|
|
|
|
|
|
|
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-08-14 07:43:26 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[export_module]
|
2020-08-14 18:04:10 +02:00
|
|
|
mod trig_functions {
|
2020-08-14 07:43:26 +02:00
|
|
|
use crate::parser::FLOAT;
|
|
|
|
|
|
|
|
pub fn sin(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().sin()
|
|
|
|
}
|
|
|
|
pub fn cos(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().cos()
|
|
|
|
}
|
|
|
|
pub fn tan(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().tan()
|
|
|
|
}
|
|
|
|
pub fn sinh(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().sinh()
|
|
|
|
}
|
|
|
|
pub fn cosh(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().cosh()
|
|
|
|
}
|
|
|
|
pub fn tanh(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians().tanh()
|
|
|
|
}
|
|
|
|
pub fn asin(x: FLOAT) -> FLOAT {
|
|
|
|
x.asin().to_degrees()
|
|
|
|
}
|
|
|
|
pub fn acos(x: FLOAT) -> FLOAT {
|
|
|
|
x.acos().to_degrees()
|
|
|
|
}
|
|
|
|
pub fn atan(x: FLOAT) -> FLOAT {
|
|
|
|
x.atan().to_degrees()
|
|
|
|
}
|
|
|
|
pub fn asinh(x: FLOAT) -> FLOAT {
|
|
|
|
x.asinh().to_degrees()
|
|
|
|
}
|
|
|
|
pub fn acosh(x: FLOAT) -> FLOAT {
|
|
|
|
x.acosh().to_degrees()
|
|
|
|
}
|
|
|
|
pub fn atanh(x: FLOAT) -> FLOAT {
|
|
|
|
x.atanh().to_degrees()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[export_module]
|
2020-08-14 18:04:10 +02:00
|
|
|
mod float_functions {
|
2020-08-14 07:43:26 +02:00
|
|
|
use crate::parser::FLOAT;
|
|
|
|
|
|
|
|
pub fn sqrt(x: FLOAT) -> FLOAT {
|
|
|
|
x.sqrt()
|
|
|
|
}
|
|
|
|
pub fn exp(x: FLOAT) -> FLOAT {
|
|
|
|
x.exp()
|
|
|
|
}
|
|
|
|
pub fn ln(x: FLOAT) -> FLOAT {
|
|
|
|
x.ln()
|
|
|
|
}
|
|
|
|
pub fn log(x: FLOAT, base: FLOAT) -> FLOAT {
|
|
|
|
x.log(base)
|
|
|
|
}
|
|
|
|
pub fn log10(x: FLOAT) -> FLOAT {
|
|
|
|
x.log10()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
pub fn floor(x: FLOAT) -> FLOAT {
|
|
|
|
float_funcs::floor(x)
|
|
|
|
}
|
|
|
|
pub fn ceiling(x: FLOAT) -> FLOAT {
|
|
|
|
float_funcs::ceiling(x)
|
|
|
|
}
|
|
|
|
pub fn round(x: FLOAT) -> FLOAT {
|
|
|
|
float_funcs::round(x)
|
|
|
|
}
|
|
|
|
pub fn int(x: FLOAT) -> FLOAT {
|
|
|
|
float_funcs::int(x)
|
|
|
|
}
|
|
|
|
pub fn fraction(x: FLOAT) -> FLOAT {
|
|
|
|
float_funcs::fraction(x)
|
|
|
|
}
|
|
|
|
pub fn is_nan(x: FLOAT) -> bool {
|
|
|
|
float_funcs::is_nan(x)
|
|
|
|
}
|
|
|
|
pub fn is_finite(x: FLOAT) -> bool {
|
|
|
|
float_funcs::is_finite(x)
|
|
|
|
}
|
|
|
|
pub fn is_infinite(x: FLOAT) -> bool {
|
|
|
|
float_funcs::is_infinite(x)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
mod float_funcs {
|
|
|
|
use crate::parser::FLOAT;
|
|
|
|
use crate::plugin::*;
|
2020-08-15 02:30:27 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use num_traits::float::Float;
|
2020-08-14 18:04:10 +02:00
|
|
|
|
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn floor(x: FLOAT) -> FLOAT {
|
|
|
|
x.floor()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn ceiling(x: FLOAT) -> FLOAT {
|
|
|
|
x.ceil()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn round(x: FLOAT) -> FLOAT {
|
|
|
|
x.ceil()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn int(x: FLOAT) -> FLOAT {
|
|
|
|
x.trunc()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn fraction(x: FLOAT) -> FLOAT {
|
|
|
|
x.fract()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn is_nan(x: FLOAT) -> bool {
|
|
|
|
x.is_nan()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn is_finite(x: FLOAT) -> bool {
|
|
|
|
x.is_finite()
|
|
|
|
}
|
2020-08-14 18:04:10 +02:00
|
|
|
#[export_fn]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn is_infinite(x: FLOAT) -> bool {
|
|
|
|
x.is_infinite()
|
|
|
|
}
|
2020-08-13 08:57:46 +02:00
|
|
|
}
|