rhai/src/packages/arithmetic.rs

556 lines
18 KiB
Rust
Raw Normal View History

2020-08-22 16:26:49 +02:00
#![allow(non_snake_case)]
use crate::plugin::*;
2021-12-27 05:27:31 +01:00
use crate::{def_package, Position, RhaiError, RhaiResultOf, ERR, INT};
2021-04-17 09:15:54 +02:00
#[cfg(feature = "no_std")]
use std::prelude::v1::*;
2021-03-29 07:40:33 +02:00
#[cfg(feature = "no_std")]
#[cfg(not(feature = "no_float"))]
use num_traits::Float;
2022-01-03 16:16:47 +01:00
#[inline]
2021-12-25 16:49:14 +01:00
pub fn make_err(msg: impl Into<String>) -> RhaiError {
2021-12-27 05:27:31 +01:00
ERR::ErrorArithmetic(msg.into(), Position::NONE).into()
2020-08-31 05:46:32 +02:00
}
2020-08-22 16:26:49 +02:00
macro_rules! gen_arithmetic_functions {
($root:ident => $($arg_type:ident),+) => {
pub mod $root { $(pub mod $arg_type {
use super::super::*;
#[export_module]
pub mod functions {
#[rhai_fn(name = "+", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn add(x: $arg_type, y: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_add(y).ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x + y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = "-", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn subtract(x: $arg_type, y: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_sub(y).ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x - y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = "*", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn multiply(x: $arg_type, y: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_mul(y).ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x * y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = "/", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn divide(x: $arg_type, y: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
// Detect division by zero
if y == 0 {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Division by zero: {} / {}", x, y)))
2020-08-22 16:26:49 +02:00
} else {
2021-03-22 04:18:09 +01:00
x.checked_div(y).ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
2020-08-22 16:26:49 +02:00
}
} else {
2021-03-22 04:18:09 +01:00
Ok(x / y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = "%", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn modulo(x: $arg_type, y: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_rem(y).ok_or_else(|| make_err(format!("Modulo division by zero or overflow: {} % {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x % y)
}
}
2021-02-10 05:41:27 +01:00
#[rhai_fn(name = "**", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn power(x: $arg_type, y: INT) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Integer raised to too large an index: {} ~ {}", x, y)))
} else if y < 0 {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Integer raised to a negative index: {} ~ {}", x, y)))
} else {
x.checked_pow(y as u32).ok_or_else(|| make_err(format!("Exponential overflow: {} ~ {}", x, y)))
2020-08-22 16:26:49 +02:00
}
} else {
2021-03-22 04:18:09 +01:00
Ok(x.pow(y as u32))
2020-08-22 16:26:49 +02:00
}
}
2020-08-22 16:26:49 +02:00
#[rhai_fn(name = "<<", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn shift_left(x: $arg_type, y: INT) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Left-shift by too many bits: {} << {}", x, y)))
} else if y < 0 {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Left-shift by a negative number: {} << {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
x.checked_shl(y as u32).ok_or_else(|| make_err(format!("Left-shift by too many bits: {} << {}", x, y)))
2020-08-22 16:26:49 +02:00
}
} else {
2021-03-22 04:18:09 +01:00
Ok(x << y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = ">>", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn shift_right(x: $arg_type, y: INT) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && y > (u32::MAX as INT) {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Right-shift by too many bits: {} >> {}", x, y)))
} else if y < 0 {
2020-08-31 05:46:32 +02:00
Err(make_err(format!("Right-shift by a negative number: {} >> {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
x.checked_shr(y as u32).ok_or_else(|| make_err(format!("Right-shift by too many bits: {} >> {}", x, y)))
2020-08-22 16:26:49 +02:00
}
} else {
2021-03-22 04:18:09 +01:00
Ok(x >> y)
2020-08-22 16:26:49 +02:00
}
}
#[rhai_fn(name = "&")]
pub fn binary_and(x: $arg_type, y: $arg_type) -> $arg_type {
x & y
}
#[rhai_fn(name = "|")]
pub fn binary_or(x: $arg_type, y: $arg_type) -> $arg_type {
x | y
}
#[rhai_fn(name = "^")]
pub fn binary_xor(x: $arg_type, y: $arg_type) -> $arg_type {
x ^ y
2020-08-22 16:26:49 +02:00
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_zero", name = "is_zero")]
2021-06-27 16:10:52 +02:00
pub fn is_zero(x: $arg_type) -> bool {
x == 0
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_odd", name = "is_odd")]
2021-06-27 16:10:52 +02:00
pub fn is_odd(x: $arg_type) -> bool {
x % 2 != 0
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_even", name = "is_even")]
2021-06-27 16:10:52 +02:00
pub fn is_even(x: $arg_type) -> bool {
x % 2 == 0
}
2020-08-22 16:26:49 +02:00
}
})* }
}
}
2020-08-22 16:26:49 +02:00
macro_rules! gen_signed_functions {
($root:ident => $($arg_type:ident),+) => {
pub mod $root { $(pub mod $arg_type {
use super::super::*;
#[export_module]
pub mod functions {
#[rhai_fn(name = "-", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn neg(x: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_neg().ok_or_else(|| make_err(format!("Negation overflow: -{}", x)))
} else {
2021-03-22 04:18:09 +01:00
Ok(-x)
2020-08-22 16:26:49 +02:00
}
}
2020-12-21 10:39:37 +01:00
#[rhai_fn(name = "+")]
pub fn plus(x: $arg_type) -> $arg_type {
x
}
#[rhai_fn(return_raw)]
2021-12-25 16:49:14 +01:00
pub fn abs(x: $arg_type) -> RhaiResultOf<$arg_type> {
if cfg!(not(feature = "unchecked")) {
2021-03-22 04:18:09 +01:00
x.checked_abs().ok_or_else(|| make_err(format!("Negation overflow: -{}", x)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x.abs())
2020-08-22 16:26:49 +02:00
}
}
pub fn sign(x: $arg_type) -> INT {
2021-09-14 16:33:10 +02:00
x.signum() as INT
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 ; $($arg_type:ident),+ ) => { $(
2020-09-13 16:12:11 +02:00
combine_with_exported_module!($mod_name, "arithmetic", $root::$arg_type::functions);
2020-08-24 16:37:44 +02:00
)* }
2020-06-25 13:19:16 +02:00
}
2021-12-20 04:42:39 +01:00
def_package! {
/// Basic arithmetic package.
crate::ArithmeticPackage => |lib| {
lib.standard = true;
2021-12-20 04:42:39 +01:00
combine_with_exported_module!(lib, "int", int_functions);
reg_functions!(lib += signed_basic; INT);
2020-06-17 10:50:46 +02:00
2021-12-20 04:42:39 +01:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
{
reg_functions!(lib += arith_numbers; i8, u8, i16, u16, i32, u32, u64);
reg_functions!(lib += signed_numbers; i8, i16, i32);
2022-01-04 15:16:20 +01:00
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_arch = "wasm64"))]
2021-12-20 04:42:39 +01:00
{
reg_functions!(lib += arith_num_128; i128, u128);
reg_functions!(lib += signed_num_128; i128);
}
}
2020-08-22 16:26:49 +02:00
2021-12-20 04:42:39 +01:00
// Basic arithmetic for floating-point
#[cfg(not(feature = "no_float"))]
2020-08-22 16:26:49 +02:00
{
2021-12-20 04:42:39 +01:00
combine_with_exported_module!(lib, "f32", f32_functions);
combine_with_exported_module!(lib, "f64", f64_functions);
}
2020-08-22 16:26:49 +02:00
2021-12-20 04:42:39 +01:00
// Decimal functions
#[cfg(feature = "decimal")]
combine_with_exported_module!(lib, "decimal", decimal_functions);
2020-08-24 16:37:44 +02:00
}
2021-12-20 04:42:39 +01:00
}
2021-06-27 16:10:52 +02:00
#[export_module]
mod int_functions {
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_zero", name = "is_zero")]
2021-06-27 16:10:52 +02:00
pub fn is_zero(x: INT) -> bool {
x == 0
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_odd", name = "is_odd")]
2021-06-27 16:10:52 +02:00
pub fn is_odd(x: INT) -> bool {
x % 2 != 0
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_even", name = "is_even")]
2021-06-27 16:10:52 +02:00
pub fn is_even(x: INT) -> bool {
x % 2 == 0
}
}
2020-08-22 16:26:49 +02:00
gen_arithmetic_functions!(arith_basic => INT);
2020-06-17 10:50:46 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
gen_arithmetic_functions!(arith_numbers => i8, u8, i16, u16, i32, u32, u64);
2020-06-25 13:19:16 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
2022-01-04 15:16:20 +01:00
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_arch = "wasm64"))]
2020-08-22 16:26:49 +02:00
gen_arithmetic_functions!(arith_num_128 => i128, u128);
2020-06-25 13:19:16 +02:00
2020-08-22 16:26:49 +02:00
gen_signed_functions!(signed_basic => INT);
2020-04-21 17:01:10 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
gen_signed_functions!(signed_numbers => i8, i16, i32);
2020-04-21 17:01:10 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "only_i32"))]
#[cfg(not(feature = "only_i64"))]
2022-01-04 15:16:20 +01:00
#[cfg(not(target_arch = "wasm32"))]
#[cfg(not(target_arch = "wasm64"))]
2020-08-22 16:26:49 +02:00
gen_signed_functions!(signed_num_128 => i128);
2020-06-17 10:50:46 +02:00
2020-08-22 16:26:49 +02:00
#[cfg(not(feature = "no_float"))]
#[export_module]
2020-08-24 16:37:44 +02:00
mod f32_functions {
2020-11-01 08:48:48 +01:00
#[cfg(not(feature = "f32_float"))]
pub mod basic_arithmetic {
#[rhai_fn(name = "+")]
pub fn add(x: f32, y: f32) -> f32 {
x + y
}
#[rhai_fn(name = "-")]
pub fn subtract(x: f32, y: f32) -> f32 {
x - y
}
#[rhai_fn(name = "*")]
pub fn multiply(x: f32, y: f32) -> f32 {
x * y
}
#[rhai_fn(name = "/")]
pub fn divide(x: f32, y: f32) -> f32 {
x / y
}
#[rhai_fn(name = "%")]
pub fn modulo(x: f32, y: f32) -> f32 {
x % y
}
2021-02-17 07:05:35 +01:00
#[rhai_fn(name = "**")]
pub fn pow_f_f(x: f32, y: f32) -> f32 {
x.powf(y)
2020-11-01 08:48:48 +01:00
}
#[rhai_fn(name = "+")]
pub fn add_if(x: INT, y: f32) -> f32 {
(x as f32) + (y as f32)
}
#[rhai_fn(name = "+")]
pub fn add_fi(x: f32, y: INT) -> f32 {
(x as f32) + (y as f32)
}
#[rhai_fn(name = "-")]
pub fn subtract_if(x: INT, y: f32) -> f32 {
(x as f32) - (y as f32)
}
#[rhai_fn(name = "-")]
pub fn subtract_fi(x: f32, y: INT) -> f32 {
(x as f32) - (y as f32)
}
#[rhai_fn(name = "*")]
pub fn multiply_if(x: INT, y: f32) -> f32 {
(x as f32) * (y as f32)
}
#[rhai_fn(name = "*")]
pub fn multiply_fi(x: f32, y: INT) -> f32 {
(x as f32) * (y as f32)
}
#[rhai_fn(name = "/")]
pub fn divide_if(x: INT, y: f32) -> f32 {
(x as f32) / (y as f32)
}
#[rhai_fn(name = "/")]
pub fn divide_fi(x: f32, y: INT) -> f32 {
(x as f32) / (y as f32)
}
#[rhai_fn(name = "%")]
pub fn modulo_if(x: INT, y: f32) -> f32 {
(x as f32) % (y as f32)
}
#[rhai_fn(name = "%")]
pub fn modulo_fi(x: f32, y: INT) -> f32 {
(x as f32) % (y as f32)
}
}
2020-08-22 16:26:49 +02:00
#[rhai_fn(name = "-")]
2020-08-24 16:37:44 +02:00
pub fn neg(x: f32) -> f32 {
2020-08-22 16:26:49 +02:00
-x
}
2020-12-21 10:39:37 +01:00
#[rhai_fn(name = "+")]
pub fn plus(x: f32) -> f32 {
2021-02-13 13:57:56 +01:00
x
2020-12-21 10:39:37 +01:00
}
2020-08-24 16:37:44 +02:00
pub fn abs(x: f32) -> f32 {
2020-08-22 16:26:49 +02:00
x.abs()
}
2021-09-14 16:33:10 +02:00
#[rhai_fn(return_raw)]
2021-12-25 16:49:14 +01:00
pub fn sign(x: f32) -> RhaiResultOf<INT> {
2021-11-20 14:29:36 +01:00
match x.signum() {
_ if x == 0.0 => Ok(0),
x if x.is_nan() => Err(make_err("Sign of NaN is undefined")),
x => Ok(x as INT),
2020-07-31 16:30:23 +02:00
}
2020-04-21 17:01:10 +02:00
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_zero", name = "is_zero")]
2021-06-27 16:10:52 +02:00
pub fn is_zero(x: f32) -> bool {
x == 0.0
}
2021-02-10 05:41:27 +01:00
#[rhai_fn(name = "**", return_raw)]
2021-12-25 16:49:14 +01:00
pub fn pow_f_i(x: f32, y: INT) -> RhaiResultOf<f32> {
2020-08-24 16:37:44 +02:00
if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) {
2020-08-31 05:46:32 +02:00
Err(make_err(format!(
"Number raised to too large an index: {} ~ {}",
x, y
)))
2020-08-24 16:37:44 +02:00
} else {
2021-03-22 04:18:09 +01:00
Ok(x.powi(y as i32))
2020-08-24 16:37:44 +02:00
}
}
}
#[cfg(not(feature = "no_float"))]
#[export_module]
mod f64_functions {
2020-11-01 08:48:48 +01:00
#[cfg(feature = "f32_float")]
pub mod basic_arithmetic {
#[rhai_fn(name = "+")]
pub fn add(x: f64, y: f64) -> f64 {
x + y
}
#[rhai_fn(name = "-")]
pub fn subtract(x: f64, y: f64) -> f64 {
x - y
}
#[rhai_fn(name = "*")]
pub fn multiply(x: f64, y: f64) -> f64 {
x * y
}
#[rhai_fn(name = "/")]
pub fn divide(x: f64, y: f64) -> f64 {
x / y
}
#[rhai_fn(name = "%")]
pub fn modulo(x: f64, y: f64) -> f64 {
x % y
}
2021-02-17 07:05:35 +01:00
#[rhai_fn(name = "**")]
pub fn pow_f_f(x: f64, y: f64) -> f64 {
x.powf(y)
2020-11-01 08:48:48 +01:00
}
#[rhai_fn(name = "+")]
pub fn add_if(x: INT, y: f64) -> f64 {
(x as f64) + (y as f64)
}
#[rhai_fn(name = "+")]
pub fn add_fi(x: f64, y: INT) -> f64 {
(x as f64) + (y as f64)
}
#[rhai_fn(name = "-")]
pub fn subtract_if(x: INT, y: f64) -> f64 {
(x as f64) - (y as f64)
}
#[rhai_fn(name = "-")]
pub fn subtract_fi(x: f64, y: INT) -> f64 {
(x as f64) - (y as f64)
}
#[rhai_fn(name = "*")]
pub fn multiply_if(x: INT, y: f64) -> f64 {
(x as f64) * (y as f64)
}
#[rhai_fn(name = "*")]
pub fn multiply_fi(x: f64, y: INT) -> f64 {
(x as f64) * (y as f64)
}
#[rhai_fn(name = "/")]
pub fn divide_if(x: INT, y: f64) -> f64 {
(x as f64) / (y as f64)
}
#[rhai_fn(name = "/")]
pub fn divide_fi(x: f64, y: INT) -> f64 {
(x as f64) / (y as f64)
}
#[rhai_fn(name = "%")]
pub fn modulo_if(x: INT, y: f64) -> f64 {
(x as f64) % (y as f64)
}
#[rhai_fn(name = "%")]
pub fn modulo_fi(x: f64, y: INT) -> f64 {
(x as f64) % (y as f64)
}
}
2020-08-24 16:37:44 +02:00
#[rhai_fn(name = "-")]
pub fn neg(x: f64) -> f64 {
-x
}
2020-12-21 10:39:37 +01:00
#[rhai_fn(name = "+")]
pub fn plus(x: f64) -> f64 {
2021-02-13 13:57:56 +01:00
x
2020-12-21 10:39:37 +01:00
}
2020-08-24 16:37:44 +02:00
pub fn abs(x: f64) -> f64 {
x.abs()
}
2021-09-14 16:33:10 +02:00
#[rhai_fn(return_raw)]
2021-12-25 16:49:14 +01:00
pub fn sign(x: f64) -> RhaiResultOf<INT> {
2021-11-20 14:29:36 +01:00
match x.signum() {
_ if x == 0.0 => Ok(0),
x if x.is_nan() => Err(make_err("Sign of NaN is undefined")),
x => Ok(x as INT),
}
2020-04-21 17:01:10 +02:00
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_zero", name = "is_zero")]
2021-06-27 16:10:52 +02:00
pub fn is_zero(x: f64) -> bool {
x == 0.0
}
2020-08-22 16:26:49 +02:00
}
2021-02-13 13:57:56 +01:00
#[cfg(feature = "decimal")]
#[export_module]
2021-02-21 07:26:31 +01:00
pub mod decimal_functions {
use num_traits::Pow;
use rust_decimal::{prelude::Zero, Decimal, MathematicalOps};
2021-02-13 13:57:56 +01:00
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn add(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
2021-02-13 13:57:56 +01:00
if cfg!(not(feature = "unchecked")) {
x.checked_add(y)
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x + y)
2021-02-13 13:57:56 +01:00
}
}
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn subtract(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
2021-02-13 13:57:56 +01:00
if cfg!(not(feature = "unchecked")) {
x.checked_sub(y)
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x - y)
2021-02-13 13:57:56 +01:00
}
}
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn multiply(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
2021-02-13 13:57:56 +01:00
if cfg!(not(feature = "unchecked")) {
x.checked_mul(y)
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
} else {
2021-03-22 04:18:09 +01:00
Ok(x * y)
2021-02-13 13:57:56 +01:00
}
}
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn divide(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
2021-02-13 13:57:56 +01:00
if cfg!(not(feature = "unchecked")) {
// Detect division by zero
if y == Decimal::zero() {
Err(make_err(format!("Division by zero: {} / {}", x, y)))
} else {
x.checked_div(y)
.ok_or_else(|| make_err(format!("Division overflow: {} / {}", x, y)))
}
} else {
2021-03-22 04:18:09 +01:00
Ok(x / y)
2021-02-13 13:57:56 +01:00
}
}
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn modulo(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
2021-02-13 13:57:56 +01:00
if cfg!(not(feature = "unchecked")) {
2021-03-22 05:18:13 +01:00
x.checked_rem(y).ok_or_else(|| {
make_err(format!(
"Modulo division by zero or overflow: {} % {}",
x, y
))
})
2021-02-13 13:57:56 +01:00
} else {
2021-03-22 04:18:09 +01:00
Ok(x % y)
2021-02-13 13:57:56 +01:00
}
}
#[rhai_fn(skip, return_raw)]
2021-12-25 16:49:14 +01:00
pub fn power(x: Decimal, y: Decimal) -> RhaiResultOf<Decimal> {
if cfg!(not(feature = "unchecked")) {
x.checked_powd(y)
.ok_or_else(|| make_err(format!("Exponential overflow: {} + {}", x, y)))
} else {
Ok(x.pow(y))
}
}
2021-02-13 13:57:56 +01:00
#[rhai_fn(name = "-")]
pub fn neg(x: Decimal) -> Decimal {
-x
}
#[rhai_fn(name = "+")]
pub fn plus(x: Decimal) -> Decimal {
x
}
pub fn abs(x: Decimal) -> Decimal {
x.abs()
}
pub fn sign(x: Decimal) -> INT {
if x == Decimal::zero() {
0
} else if x.is_sign_negative() {
-1
} else {
1
}
}
2021-12-15 05:06:17 +01:00
#[rhai_fn(get = "is_zero", name = "is_zero")]
2021-06-27 16:10:52 +02:00
pub fn is_zero(x: Decimal) -> bool {
x.is_zero()
}
2021-02-13 13:57:56 +01:00
}