rhai/src/packages/math_basic.rs

252 lines
6.8 KiB
Rust
Raw Normal View History

2020-08-22 16:26:49 +02:00
#![allow(non_snake_case)]
2020-04-21 17:01:10 +02:00
use crate::def_package;
use crate::parser::INT;
2020-08-13 08:57:46 +02:00
use crate::plugin::*;
#[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-07-31 16:30:23 +02:00
#[allow(dead_code)]
#[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)]
#[cfg(not(feature = "only_i32"))]
2020-04-20 18:24:25 +02:00
pub const MAX_INT: INT = i64::MAX;
2020-08-22 16:26:49 +02:00
macro_rules! gen_conversion_functions {
($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => {
pub mod $root { $(pub mod $arg_type {
use super::super::*;
#[export_fn]
#[inline(always)]
pub fn $func_name(x: $arg_type) -> $result_type {
x as $result_type
2020-08-22 16:26:49 +02:00
}
})* }
2020-08-22 16:26:49 +02:00
}
}
macro_rules! reg_functions {
2020-08-24 16:37:44 +02:00
($mod_name:ident += $root:ident :: $func_name:ident ( $($arg_type:ident),+ ) ) => { $(
set_exported_fn!($mod_name, stringify!($func_name), $root::$arg_type::$func_name);
)* }
2020-08-22 16:26:49 +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-09-13 16:12:11 +02:00
combine_with_exported_module!(lib, "float", float_functions);
2020-04-21 17:01:10 +02:00
2020-08-13 08:57:46 +02:00
// Trig functions
2020-09-13 16:12:11 +02:00
combine_with_exported_module!(lib, "trig", trig_functions);
2020-08-13 08:57:46 +02:00
2020-08-22 16:26:49 +02:00
reg_functions!(lib += basic_to_float::to_float(INT));
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
{
reg_functions!(lib += numbers_to_float::to_float(i8, u8, i16, u16, i32, u32, i64, u32));
2020-06-17 10:50:46 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(target_arch = "wasm32"))]
reg_functions!(lib += num_128_to_float::to_float(i128, u128));
2020-04-21 17:01:10 +02:00
}
}
2020-08-22 16:26:49 +02:00
reg_functions!(lib += basic_to_int::to_int(char));
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
2020-04-21 17:01:10 +02:00
{
2020-08-22 16:26:49 +02:00
reg_functions!(lib += numbers_to_int::to_int(i8, u8, i16, u16, i32, u32, i64, u64));
2020-08-13 08:57:46 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(target_arch = "wasm32"))]
reg_functions!(lib += num_128_to_int::to_int(i128, u128));
}
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;
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn sin(x: FLOAT) -> FLOAT {
x.to_radians().sin()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn cos(x: FLOAT) -> FLOAT {
x.to_radians().cos()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn tan(x: FLOAT) -> FLOAT {
x.to_radians().tan()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn sinh(x: FLOAT) -> FLOAT {
x.to_radians().sinh()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn cosh(x: FLOAT) -> FLOAT {
x.to_radians().cosh()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn tanh(x: FLOAT) -> FLOAT {
x.to_radians().tanh()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn asin(x: FLOAT) -> FLOAT {
x.asin().to_degrees()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn acos(x: FLOAT) -> FLOAT {
x.acos().to_degrees()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn atan(x: FLOAT) -> FLOAT {
x.atan().to_degrees()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn asinh(x: FLOAT) -> FLOAT {
x.asinh().to_degrees()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn acosh(x: FLOAT) -> FLOAT {
x.acosh().to_degrees()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
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;
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn sqrt(x: FLOAT) -> FLOAT {
x.sqrt()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn exp(x: FLOAT) -> FLOAT {
x.exp()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn ln(x: FLOAT) -> FLOAT {
x.ln()
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn log(x: FLOAT, base: FLOAT) -> FLOAT {
x.log(base)
}
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn log10(x: FLOAT) -> FLOAT {
x.log10()
}
#[rhai_fn(name = "floor", get = "floor")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn floor(x: FLOAT) -> FLOAT {
x.floor()
}
#[rhai_fn(name = "ceiling", get = "ceiling")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn ceiling(x: FLOAT) -> FLOAT {
x.ceil()
}
#[rhai_fn(name = "round", get = "round")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn round(x: FLOAT) -> FLOAT {
x.ceil()
}
#[rhai_fn(name = "int", get = "int")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn int(x: FLOAT) -> FLOAT {
x.trunc()
}
#[rhai_fn(name = "fraction", get = "fraction")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn fraction(x: FLOAT) -> FLOAT {
x.fract()
}
#[rhai_fn(name = "is_nan", get = "is_nan")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn is_nan(x: FLOAT) -> bool {
x.is_nan()
}
#[rhai_fn(name = "is_finite", get = "is_finite")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn is_finite(x: FLOAT) -> bool {
x.is_finite()
}
#[rhai_fn(name = "is_infinite", get = "is_infinite")]
2020-08-20 16:11:41 +02:00
#[inline(always)]
2020-08-14 07:43:26 +02:00
pub fn is_infinite(x: FLOAT) -> bool {
x.is_infinite()
}
2020-08-22 16:26:49 +02:00
#[rhai_fn(name = "to_int", return_raw)]
#[inline]
pub fn f32_to_int(x: f32) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) {
EvalAltResult::ErrorArithmetic(
format!("Integer overflow: to_int({})", x),
Position::none(),
)
.into()
} else {
Ok((x.trunc() as INT).into())
}
}
#[rhai_fn(name = "to_int", return_raw)]
#[inline]
pub fn f64_to_int(x: f64) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) {
EvalAltResult::ErrorArithmetic(
format!("Integer overflow: to_int({})", x),
Position::none(),
)
.into()
} else {
Ok((x.trunc() as INT).into())
}
}
2020-08-13 08:57:46 +02:00
}
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "no_float"))]
gen_conversion_functions!(basic_to_float => to_float (INT) -> FLOAT);
#[cfg(not(feature = "no_float"))]
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
gen_conversion_functions!(numbers_to_float => to_float (i8, u8, i16, u16, i32, u32, i64, u64) -> FLOAT);
#[cfg(not(feature = "no_float"))]
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
#[cfg(not(target_arch = "wasm32"))]
gen_conversion_functions!(num_128_to_float => to_float (i128, u128) -> FLOAT);
gen_conversion_functions!(basic_to_int => to_int (char) -> INT);
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
gen_conversion_functions!(numbers_to_int => to_int (i8, u8, i16, u16, i32, u32, i64, u64) -> INT);
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
#[cfg(not(target_arch = "wasm32"))]
gen_conversion_functions!(num_128_to_int => to_int (i128, u128) -> INT);