2020-08-22 16:26:49 +02:00
|
|
|
#![allow(non_snake_case)]
|
|
|
|
|
2020-08-13 08:57:46 +02:00
|
|
|
use crate::plugin::*;
|
2021-12-27 05:27:31 +01:00
|
|
|
use crate::{def_package, Position, RhaiResultOf, ERR, INT, INT_BASE};
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-12-06 13:52:47 +01:00
|
|
|
use crate::FLOAT;
|
2020-07-26 09:53:22 +02:00
|
|
|
|
2021-03-29 07:40:33 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use num_traits::Float;
|
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
use rust_decimal::Decimal;
|
|
|
|
|
2021-02-13 16:25:22 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
use super::arithmetic::make_err;
|
|
|
|
|
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
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
macro_rules! gen_conversion_as_functions {
|
2020-08-22 16:26:49 +02:00
|
|
|
($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => {
|
2020-08-28 17:13:38 +02:00
|
|
|
pub mod $root { $(pub mod $arg_type {
|
|
|
|
use super::super::*;
|
|
|
|
|
|
|
|
#[export_fn]
|
|
|
|
pub fn $func_name(x: $arg_type) -> $result_type {
|
|
|
|
x as $result_type
|
2020-08-22 16:26:49 +02:00
|
|
|
}
|
2020-08-28 17:13:38 +02:00
|
|
|
})* }
|
2020-08-22 16:26:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-13 15:19:46 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
2021-02-13 13:57:56 +01:00
|
|
|
macro_rules! gen_conversion_into_functions {
|
|
|
|
($root:ident => $func_name:ident ( $($arg_type:ident),+ ) -> $result_type:ty) => {
|
|
|
|
pub mod $root { $(pub mod $arg_type {
|
|
|
|
use super::super::*;
|
|
|
|
|
|
|
|
#[export_fn]
|
|
|
|
pub fn $func_name(x: $arg_type) -> $result_type {
|
|
|
|
x.into()
|
|
|
|
}
|
|
|
|
})* }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
def_package! {
|
|
|
|
/// Basic mathematical package.
|
|
|
|
crate::BasicMathPackage => |lib| {
|
|
|
|
lib.standard = true;
|
2021-11-05 16:22:05 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
// Integer functions
|
|
|
|
combine_with_exported_module!(lib, "int", int_functions);
|
2020-10-19 17:49:01 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
reg_functions!(lib += basic_to_int::to_int(char));
|
2020-10-19 17:49:01 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
{
|
|
|
|
reg_functions!(lib += numbers_to_int::to_int(i8, u8, i16, u16, i32, u32, i64, u64));
|
2020-10-19 17:49:01 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
|
|
reg_functions!(lib += num_128_to_int::to_int(i128, u128));
|
|
|
|
}
|
2020-10-19 17:49:01 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
{
|
|
|
|
// Floating point functions
|
|
|
|
combine_with_exported_module!(lib, "float", float_functions);
|
2020-04-21 17:01:10 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
// Trig functions
|
|
|
|
combine_with_exported_module!(lib, "trig", trig_functions);
|
2020-08-13 08:57:46 +02:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
reg_functions!(lib += basic_to_float::to_float(INT));
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2021-12-20 04:42:39 +01: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
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
|
|
|
reg_functions!(lib += num_128_to_float::to_float(i128, u128));
|
|
|
|
}
|
2020-04-21 17:01:10 +02:00
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
// Decimal functions
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
{
|
|
|
|
combine_with_exported_module!(lib, "decimal", decimal_functions);
|
2021-02-13 13:57:56 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
reg_functions!(lib += basic_to_decimal::to_decimal(INT));
|
2021-02-13 13:57:56 +01:00
|
|
|
|
2021-12-20 04:42:39 +01:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
reg_functions!(lib += numbers_to_decimal::to_decimal(i8, u8, i16, u16, i32, u32, i64, u64));
|
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
2021-12-20 04:42:39 +01:00
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-10-19 17:49:01 +02:00
|
|
|
#[export_module]
|
|
|
|
mod int_functions {
|
|
|
|
#[rhai_fn(name = "parse_int", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn parse_int_radix(string: &str, radix: INT) -> RhaiResultOf<INT> {
|
2021-07-24 08:11:16 +02:00
|
|
|
if !(2..=36).contains(&radix) {
|
2021-12-27 05:27:31 +01:00
|
|
|
return Err(ERR::ErrorArithmetic(
|
2020-11-20 09:52:28 +01:00
|
|
|
format!("Invalid radix: '{}'", radix),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
2021-10-19 17:52:58 +02:00
|
|
|
.into());
|
2020-10-19 17:49:01 +02:00
|
|
|
}
|
2020-08-13 08:57:46 +02:00
|
|
|
|
2021-12-18 10:07:30 +01:00
|
|
|
INT_BASE::from_str_radix(string.trim(), radix as u32)
|
|
|
|
.map(|v| v as INT)
|
|
|
|
.map_err(|err| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-12-18 10:07:30 +01:00
|
|
|
format!("Error parsing integer number '{}': {}", string, err),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
2020-10-19 17:49:01 +02:00
|
|
|
#[rhai_fn(name = "parse_int", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn parse_int(string: &str) -> RhaiResultOf<INT> {
|
2021-08-13 07:42:39 +02:00
|
|
|
parse_int_radix(string, 10)
|
2020-10-19 17:49:01 +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-10-29 04:37:51 +01:00
|
|
|
use crate::FLOAT;
|
2020-08-14 07:43:26 +02:00
|
|
|
|
|
|
|
pub fn sin(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.sin()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn cos(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.cos()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn tan(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.tan()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn sinh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.sinh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn cosh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.cosh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn tanh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.tanh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn asin(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.asin()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn acos(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.acos()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn atan(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.atan()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
2021-02-17 05:27:27 +01:00
|
|
|
#[rhai_fn(name = "atan")]
|
|
|
|
pub fn atan2(x: FLOAT, y: FLOAT) -> FLOAT {
|
|
|
|
x.atan2(y)
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn asinh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.asinh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn acosh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.acosh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
pub fn atanh(x: FLOAT) -> FLOAT {
|
2021-02-10 05:10:50 +01:00
|
|
|
x.atanh()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
2021-02-17 05:27:27 +01:00
|
|
|
pub fn hypot(x: FLOAT, y: FLOAT) -> FLOAT {
|
|
|
|
x.hypot(y)
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[export_module]
|
2020-08-14 18:04:10 +02:00
|
|
|
mod float_functions {
|
2020-10-29 04:37:51 +01:00
|
|
|
use crate::FLOAT;
|
2020-08-14 07:43:26 +02:00
|
|
|
|
2021-02-09 08:57:38 +01:00
|
|
|
#[rhai_fn(name = "E")]
|
|
|
|
pub fn e() -> FLOAT {
|
|
|
|
#[cfg(not(feature = "f32_float"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
return std::f64::consts::E;
|
2021-02-09 08:57:38 +01:00
|
|
|
#[cfg(feature = "f32_float")]
|
2021-04-17 09:15:54 +02:00
|
|
|
return std::f32::consts::E;
|
2021-02-09 08:57:38 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "PI")]
|
|
|
|
pub fn pi() -> FLOAT {
|
|
|
|
#[cfg(not(feature = "f32_float"))]
|
2021-04-17 09:15:54 +02:00
|
|
|
return std::f64::consts::PI;
|
2021-02-09 08:57:38 +01:00
|
|
|
#[cfg(feature = "f32_float")]
|
2021-04-17 09:15:54 +02:00
|
|
|
return std::f32::consts::PI;
|
2021-02-09 08:57:38 +01:00
|
|
|
}
|
|
|
|
pub fn to_radians(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_radians()
|
|
|
|
}
|
|
|
|
pub fn to_degrees(x: FLOAT) -> FLOAT {
|
|
|
|
x.to_degrees()
|
|
|
|
}
|
2020-08-14 07:43:26 +02:00
|
|
|
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)
|
|
|
|
}
|
2021-05-11 14:31:31 +02:00
|
|
|
#[rhai_fn(name = "log")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn log10(x: FLOAT) -> FLOAT {
|
|
|
|
x.log10()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "floor", get = "floor")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn floor(x: FLOAT) -> FLOAT {
|
|
|
|
x.floor()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "ceiling", get = "ceiling")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn ceiling(x: FLOAT) -> FLOAT {
|
|
|
|
x.ceil()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "round", get = "round")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn round(x: FLOAT) -> FLOAT {
|
2021-02-13 16:25:22 +01:00
|
|
|
x.round()
|
2020-08-14 07:43:26 +02:00
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "int", get = "int")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn int(x: FLOAT) -> FLOAT {
|
|
|
|
x.trunc()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "fraction", get = "fraction")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn fraction(x: FLOAT) -> FLOAT {
|
|
|
|
x.fract()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "is_nan", get = "is_nan")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn is_nan(x: FLOAT) -> bool {
|
|
|
|
x.is_nan()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "is_finite", get = "is_finite")]
|
2020-08-14 07:43:26 +02:00
|
|
|
pub fn is_finite(x: FLOAT) -> bool {
|
|
|
|
x.is_finite()
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "is_infinite", get = "is_infinite")]
|
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)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn f32_to_int(x: f32) -> RhaiResultOf<INT> {
|
2020-08-22 16:26:49 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f32) {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(
|
|
|
|
ERR::ErrorArithmetic(format!("Integer overflow: to_int({})", x), Position::NONE)
|
|
|
|
.into(),
|
2020-11-20 09:52:28 +01:00
|
|
|
)
|
2020-08-22 16:26:49 +02:00
|
|
|
} else {
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(x.trunc() as INT)
|
2020-08-22 16:26:49 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "to_int", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn f64_to_int(x: f64) -> RhaiResultOf<INT> {
|
2020-08-22 16:26:49 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) && x > (MAX_INT as f64) {
|
2021-12-27 05:27:31 +01:00
|
|
|
Err(
|
|
|
|
ERR::ErrorArithmetic(format!("Integer overflow: to_int({})", x), Position::NONE)
|
|
|
|
.into(),
|
2020-11-20 09:52:28 +01:00
|
|
|
)
|
2020-08-22 16:26:49 +02:00
|
|
|
} else {
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(x.trunc() as INT)
|
2020-08-22 16:26:49 +02:00
|
|
|
}
|
|
|
|
}
|
2020-09-23 06:00:03 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn parse_float(string: &str) -> RhaiResultOf<FLOAT> {
|
2021-08-13 07:42:39 +02:00
|
|
|
string.trim().parse::<FLOAT>().map_err(|err| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-08-13 07:42:39 +02:00
|
|
|
format!("Error parsing floating-point number '{}': {}", string, err),
|
2021-03-22 04:18:09 +01:00
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
2020-09-23 06:00:03 +02:00
|
|
|
}
|
2020-11-01 08:48:48 +01:00
|
|
|
#[cfg(not(feature = "f32_float"))]
|
2021-10-20 10:22:12 +02:00
|
|
|
#[rhai_fn(name = "to_float")]
|
|
|
|
pub fn f32_to_f64(x: f32) -> f64 {
|
|
|
|
x as f64
|
2020-11-01 08:48:48 +01:00
|
|
|
}
|
2020-08-13 08:57:46 +02:00
|
|
|
}
|
2020-08-22 16:26:49 +02:00
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
#[export_module]
|
|
|
|
mod decimal_functions {
|
2021-02-15 05:07:45 +01:00
|
|
|
use rust_decimal::{
|
|
|
|
prelude::{FromStr, RoundingStrategy},
|
2021-05-11 14:31:31 +02:00
|
|
|
Decimal, MathematicalOps,
|
2021-02-15 05:07:45 +01:00
|
|
|
};
|
2021-10-20 10:22:12 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
use std::convert::TryFrom;
|
2021-02-13 13:57:56 +01:00
|
|
|
|
2021-08-11 10:09:04 +02:00
|
|
|
#[cfg(feature = "no_float")]
|
2021-10-20 10:22:12 +02:00
|
|
|
#[rhai_fn(name = "PI")]
|
|
|
|
pub fn pi() -> Decimal {
|
|
|
|
Decimal::PI
|
|
|
|
}
|
|
|
|
#[cfg(feature = "no_float")]
|
|
|
|
#[rhai_fn(name = "E")]
|
|
|
|
pub fn e() -> Decimal {
|
|
|
|
Decimal::E
|
|
|
|
}
|
|
|
|
#[cfg(feature = "no_float")]
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn parse_float(s: &str) -> RhaiResultOf<Decimal> {
|
2021-10-21 13:30:58 +02:00
|
|
|
parse_decimal(s)
|
2021-08-11 10:09:04 +02:00
|
|
|
}
|
|
|
|
|
2021-09-15 04:41:35 +02:00
|
|
|
pub fn sin(x: Decimal) -> Decimal {
|
|
|
|
x.sin()
|
|
|
|
}
|
|
|
|
pub fn cos(x: Decimal) -> Decimal {
|
|
|
|
x.cos()
|
|
|
|
}
|
|
|
|
pub fn tan(x: Decimal) -> Decimal {
|
|
|
|
x.tan()
|
|
|
|
}
|
2021-05-11 14:31:31 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn sqrt(x: Decimal) -> RhaiResultOf<Decimal> {
|
2021-05-22 13:14:24 +02:00
|
|
|
x.sqrt()
|
|
|
|
.ok_or_else(|| make_err(format!("Error taking the square root of {}", x,)))
|
2021-05-11 14:31:31 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn exp(x: Decimal) -> RhaiResultOf<Decimal> {
|
2021-05-11 14:31:31 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
2021-05-24 06:12:29 +02:00
|
|
|
x.checked_exp()
|
|
|
|
.ok_or_else(|| make_err(format!("Exponential overflow: e ** {}", x,)))
|
2021-05-11 14:31:31 +02:00
|
|
|
} else {
|
|
|
|
Ok(x.exp())
|
|
|
|
}
|
|
|
|
}
|
2021-08-11 12:15:17 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn ln(x: Decimal) -> RhaiResultOf<Decimal> {
|
2021-08-11 12:15:17 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
x.checked_ln()
|
|
|
|
.ok_or_else(|| make_err(format!("Error taking the natural log of {}", x)))
|
|
|
|
} else {
|
|
|
|
Ok(x.ln())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "log", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn log10(x: Decimal) -> RhaiResultOf<Decimal> {
|
2021-08-11 12:15:17 +02:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
x.checked_log10()
|
|
|
|
.ok_or_else(|| make_err(format!("Error taking the log of {}", x)))
|
|
|
|
} else {
|
|
|
|
Ok(x.log10())
|
|
|
|
}
|
2021-05-11 14:31:31 +02:00
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
#[rhai_fn(name = "floor", get = "floor")]
|
|
|
|
pub fn floor(x: Decimal) -> Decimal {
|
|
|
|
x.floor()
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "ceiling", get = "ceiling")]
|
|
|
|
pub fn ceiling(x: Decimal) -> Decimal {
|
|
|
|
x.ceil()
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "round", get = "round")]
|
|
|
|
pub fn round(x: Decimal) -> Decimal {
|
2021-02-13 16:25:22 +01:00
|
|
|
x.round()
|
|
|
|
}
|
2021-02-15 05:07:45 +01:00
|
|
|
#[rhai_fn(name = "round", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn round_dp(x: Decimal, dp: INT) -> RhaiResultOf<Decimal> {
|
2021-02-13 16:25:22 +01:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
if dp < 0 {
|
|
|
|
return Err(make_err(format!(
|
2021-05-24 06:12:29 +02:00
|
|
|
"Invalid number of digits for rounding: {}",
|
|
|
|
dp
|
2021-02-13 16:25:22 +01:00
|
|
|
)));
|
|
|
|
}
|
2021-05-24 06:12:29 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
|
|
|
return Ok(x);
|
|
|
|
}
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(x.round_dp(dp as u32))
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn round_up(x: Decimal, dp: INT) -> RhaiResultOf<Decimal> {
|
2021-02-13 16:25:22 +01:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
if dp < 0 {
|
|
|
|
return Err(make_err(format!(
|
2021-05-24 06:12:29 +02:00
|
|
|
"Invalid number of digits for rounding: {}",
|
|
|
|
dp
|
2021-02-13 16:25:22 +01:00
|
|
|
)));
|
|
|
|
}
|
2021-05-24 06:12:29 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
|
|
|
return Ok(x);
|
|
|
|
}
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
|
2021-04-18 15:35:55 +02:00
|
|
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::AwayFromZero))
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn round_down(x: Decimal, dp: INT) -> RhaiResultOf<Decimal> {
|
2021-02-13 16:25:22 +01:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
if dp < 0 {
|
|
|
|
return Err(make_err(format!(
|
2021-05-24 06:12:29 +02:00
|
|
|
"Invalid number of digits for rounding: {}",
|
|
|
|
dp
|
2021-02-13 16:25:22 +01:00
|
|
|
)));
|
|
|
|
}
|
2021-05-24 06:12:29 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
|
|
|
return Ok(x);
|
|
|
|
}
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
|
2021-04-18 15:35:55 +02:00
|
|
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::ToZero))
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn round_half_up(x: Decimal, dp: INT) -> RhaiResultOf<Decimal> {
|
2021-02-13 16:25:22 +01:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
if dp < 0 {
|
|
|
|
return Err(make_err(format!(
|
2021-05-24 06:12:29 +02:00
|
|
|
"Invalid number of digits for rounding: {}",
|
|
|
|
dp
|
2021-02-13 16:25:22 +01:00
|
|
|
)));
|
|
|
|
}
|
2021-05-24 06:12:29 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
|
|
|
return Ok(x);
|
|
|
|
}
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
|
2021-04-18 15:35:55 +02:00
|
|
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::MidpointAwayFromZero))
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn round_half_down(x: Decimal, dp: INT) -> RhaiResultOf<Decimal> {
|
2021-02-13 16:25:22 +01:00
|
|
|
if cfg!(not(feature = "unchecked")) {
|
|
|
|
if dp < 0 {
|
|
|
|
return Err(make_err(format!(
|
2021-05-24 06:12:29 +02:00
|
|
|
"Invalid number of digits for rounding: {}",
|
|
|
|
dp
|
2021-02-13 16:25:22 +01:00
|
|
|
)));
|
|
|
|
}
|
2021-05-24 06:12:29 +02:00
|
|
|
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
|
|
|
|
return Ok(x);
|
|
|
|
}
|
2021-02-13 16:25:22 +01:00
|
|
|
}
|
|
|
|
|
2021-04-18 15:35:55 +02:00
|
|
|
Ok(x.round_dp_with_strategy(dp as u32, RoundingStrategy::MidpointTowardZero))
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "int", get = "int")]
|
|
|
|
pub fn int(x: Decimal) -> Decimal {
|
|
|
|
x.trunc()
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "fraction", get = "fraction")]
|
|
|
|
pub fn fraction(x: Decimal) -> Decimal {
|
|
|
|
x.fract()
|
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn parse_decimal(string: &str) -> RhaiResultOf<Decimal> {
|
2021-08-13 07:42:39 +02:00
|
|
|
Decimal::from_str(string)
|
2021-08-13 08:04:27 +02:00
|
|
|
.or_else(|_| Decimal::from_scientific(string))
|
2021-02-13 13:57:56 +01:00
|
|
|
.map_err(|err| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-08-13 07:42:39 +02:00
|
|
|
format!("Error parsing decimal number '{}': {}", string, err),
|
2021-02-13 13:57:56 +01:00
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
|
|
|
}
|
2021-03-22 08:16:01 +01:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-10-20 10:22:12 +02:00
|
|
|
#[rhai_fn(name = "to_decimal", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn f32_to_decimal(x: f32) -> RhaiResultOf<Decimal> {
|
2021-10-20 10:22:12 +02:00
|
|
|
Decimal::try_from(x).map_err(|_| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-10-20 10:22:12 +02:00
|
|
|
format!("Cannot convert to Decimal: to_decimal({})", x),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(name = "to_decimal", return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn f64_to_decimal(x: f64) -> RhaiResultOf<Decimal> {
|
2021-10-20 10:22:12 +02:00
|
|
|
Decimal::try_from(x).map_err(|_| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-10-20 10:22:12 +02:00
|
|
|
format!("Cannot convert to Decimal: to_decimal({})", x),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[rhai_fn(return_raw)]
|
2021-12-25 16:49:14 +01:00
|
|
|
pub fn to_float(x: Decimal) -> RhaiResultOf<FLOAT> {
|
2021-10-20 10:22:12 +02:00
|
|
|
FLOAT::try_from(x).map_err(|_| {
|
2021-12-27 05:27:31 +01:00
|
|
|
ERR::ErrorArithmetic(
|
2021-10-20 10:22:12 +02:00
|
|
|
format!("Cannot convert to floating-point: to_float({})", x),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into()
|
|
|
|
})
|
2021-03-22 08:16:01 +01:00
|
|
|
}
|
2021-02-13 13:57:56 +01:00
|
|
|
}
|
|
|
|
|
2020-08-22 16:26:49 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(basic_to_float => to_float (INT) -> FLOAT);
|
2020-08-22 16:26:49 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(numbers_to_float => to_float (i8, u8, i16, u16, i32, u32, i64, u64) -> FLOAT);
|
2020-08-22 16:26:49 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-02-19 08:50:48 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(num_128_to_float => to_float (i128, u128) -> FLOAT);
|
2020-08-22 16:26:49 +02:00
|
|
|
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(basic_to_int => to_int (char) -> INT);
|
2020-08-22 16:26:49 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(numbers_to_int => to_int (i8, u8, i16, u16, i32, u32, i64, u64) -> INT);
|
2020-08-22 16:26:49 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
2021-02-19 08:50:48 +01:00
|
|
|
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
|
2021-02-13 13:57:56 +01:00
|
|
|
gen_conversion_as_functions!(num_128_to_int => to_int (i128, u128) -> INT);
|
|
|
|
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
gen_conversion_into_functions!(basic_to_decimal => to_decimal (INT) -> Decimal);
|
|
|
|
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
gen_conversion_into_functions!(numbers_to_decimal => to_decimal (i8, u8, i16, u16, i32, u32, i64, u64) -> Decimal);
|