From 909d48caed7fe87ead72967950a34374d8412cf7 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Mon, 15 Feb 2021 17:42:33 +0800 Subject: [PATCH 1/4] Provide short-cuts to Decimal calculations. --- src/fn_call.rs | 80 ++++++++++++++++++++++++++++++++++---- src/packages/arithmetic.rs | 30 +++++++------- 2 files changed, 88 insertions(+), 22 deletions(-) diff --git a/src/fn_call.rs b/src/fn_call.rs index bb928bb0..31c726de 100644 --- a/src/fn_call.rs +++ b/src/fn_call.rs @@ -1325,8 +1325,6 @@ pub fn run_builtin_binary_op( x: &Dynamic, y: &Dynamic, ) -> Result, Box> { - use crate::packages::arithmetic::arith_basic::INT::functions::*; - let args_type = x.type_id(); let second_type = y.type_id(); @@ -1358,6 +1356,8 @@ pub fn run_builtin_binary_op( let y = y.clone().cast::(); if cfg!(not(feature = "unchecked")) { + use crate::packages::arithmetic::arith_basic::INT::functions::*; + match op { "+" => return add(x, y).map(Some), "-" => return subtract(x, y).map(Some), @@ -1465,6 +1465,44 @@ pub fn run_builtin_binary_op( } } + #[cfg(feature = "decimal")] + if args_type == TypeId::of::() { + let x = x.clone().cast::(); + let y = y.clone().cast::(); + + if cfg!(not(feature = "unchecked")) { + use crate::packages::arithmetic::decimal_functions::*; + + match op { + "+" => return add(x, y).map(Some), + "-" => return subtract(x, y).map(Some), + "*" => return multiply(x, y).map(Some), + "/" => return divide(x, y).map(Some), + "%" => return modulo(x, y).map(Some), + _ => (), + } + } else { + match op { + "+" => return Ok(Some((x + y).into())), + "-" => return Ok(Some((x - y).into())), + "*" => return Ok(Some((x * y).into())), + "/" => return Ok(Some((x / y).into())), + "%" => return Ok(Some((x % y).into())), + _ => (), + } + } + + match op { + "==" => return Ok(Some((x == y).into())), + "!=" => return Ok(Some((x != y).into())), + ">" => return Ok(Some((x > y).into())), + ">=" => return Ok(Some((x >= y).into())), + "<" => return Ok(Some((x < y).into())), + "<=" => return Ok(Some((x <= y).into())), + _ => (), + } + } + Ok(None) } @@ -1474,8 +1512,6 @@ pub fn run_builtin_op_assignment( x: &mut Dynamic, y: &Dynamic, ) -> Result, Box> { - use crate::packages::arithmetic::arith_basic::INT::functions::*; - let args_type = x.type_id(); let second_type = y.type_id(); @@ -1498,13 +1534,15 @@ pub fn run_builtin_op_assignment( let mut x = x.write_lock::().unwrap(); if cfg!(not(feature = "unchecked")) { + use crate::packages::arithmetic::arith_basic::INT::functions::*; + match op { "+=" => return Ok(Some(*x = add(*x, y)?.as_int().unwrap())), "-=" => return Ok(Some(*x = subtract(*x, y)?.as_int().unwrap())), "*=" => return Ok(Some(*x = multiply(*x, y)?.as_int().unwrap())), "/=" => return Ok(Some(*x = divide(*x, y)?.as_int().unwrap())), "%=" => return Ok(Some(*x = modulo(*x, y)?.as_int().unwrap())), - "~=" => return Ok(Some(*x = power(*x, y)?.as_int().unwrap())), + "**=" => return Ok(Some(*x = power(*x, y)?.as_int().unwrap())), ">>=" => return Ok(Some(*x = shift_right(*x, y)?.as_int().unwrap())), "<<=" => return Ok(Some(*x = shift_left(*x, y)?.as_int().unwrap())), _ => (), @@ -1516,7 +1554,7 @@ pub fn run_builtin_op_assignment( "*=" => return Ok(Some(*x *= y)), "/=" => return Ok(Some(*x /= y)), "%=" => return Ok(Some(*x %= y)), - "~=" => return Ok(Some(*x = x.pow(y as u32))), + "**=" => return Ok(Some(*x = x.pow(y as u32))), ">>=" => return Ok(Some(*x = *x >> y)), "<<=" => return Ok(Some(*x = *x << y)), _ => (), @@ -1567,10 +1605,38 @@ pub fn run_builtin_op_assignment( "*=" => return Ok(Some(*x *= y)), "/=" => return Ok(Some(*x /= y)), "%=" => return Ok(Some(*x %= y)), - "~=" => return Ok(Some(*x = x.powf(y))), + "**=" => return Ok(Some(*x = x.powf(y))), _ => (), } } + #[cfg(feature = "decimal")] + if args_type == TypeId::of::() { + let y = y.clone().cast::(); + let mut x = x.write_lock::().unwrap(); + + if cfg!(not(feature = "unchecked")) { + use crate::packages::arithmetic::decimal_functions::*; + + match op { + "+=" => return Ok(Some(*x = add(*x, y)?.as_decimal().unwrap())), + "-=" => return Ok(Some(*x = subtract(*x, y)?.as_decimal().unwrap())), + "*=" => return Ok(Some(*x = multiply(*x, y)?.as_decimal().unwrap())), + "/=" => return Ok(Some(*x = divide(*x, y)?.as_decimal().unwrap())), + "%=" => return Ok(Some(*x = modulo(*x, y)?.as_decimal().unwrap())), + _ => (), + } + } else { + match op { + "+=" => return Ok(Some(*x += y)), + "-=" => return Ok(Some(*x -= y)), + "*=" => return Ok(Some(*x *= y)), + "/=" => return Ok(Some(*x /= y)), + "%=" => return Ok(Some(*x %= y)), + _ => (), + } + } + } + Ok(None) } diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index bfca6937..60837813 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -357,7 +357,7 @@ mod decimal_functions { use rust_decimal::{prelude::Zero, Decimal}; #[rhai_fn(name = "+", return_raw)] - pub fn add_dd(x: Decimal, y: Decimal) -> Result> { + pub fn add(x: Decimal, y: Decimal) -> Result> { if cfg!(not(feature = "unchecked")) { x.checked_add(y) .ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y))) @@ -368,14 +368,14 @@ mod decimal_functions { } #[rhai_fn(name = "+", return_raw)] pub fn add_id(x: INT, y: Decimal) -> Result> { - add_dd(x.into(), y) + add(x.into(), y) } #[rhai_fn(name = "+", return_raw)] pub fn add_di(x: Decimal, y: INT) -> Result> { - add_dd(x, y.into()) + add(x, y.into()) } #[rhai_fn(name = "-", return_raw)] - pub fn subtract_dd(x: Decimal, y: Decimal) -> Result> { + pub fn subtract(x: Decimal, y: Decimal) -> Result> { if cfg!(not(feature = "unchecked")) { x.checked_sub(y) .ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y))) @@ -386,14 +386,14 @@ mod decimal_functions { } #[rhai_fn(name = "-", return_raw)] pub fn subtract_id(x: INT, y: Decimal) -> Result> { - subtract_dd(x.into(), y) + subtract(x.into(), y) } #[rhai_fn(name = "-", return_raw)] pub fn subtract_di(x: Decimal, y: INT) -> Result> { - subtract_dd(x, y.into()) + subtract(x, y.into()) } #[rhai_fn(name = "*", return_raw)] - pub fn multiply_dd(x: Decimal, y: Decimal) -> Result> { + pub fn multiply(x: Decimal, y: Decimal) -> Result> { if cfg!(not(feature = "unchecked")) { x.checked_mul(y) .ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y))) @@ -404,14 +404,14 @@ mod decimal_functions { } #[rhai_fn(name = "*", return_raw)] pub fn multiply_id(x: INT, y: Decimal) -> Result> { - multiply_dd(x.into(), y) + multiply(x.into(), y) } #[rhai_fn(name = "*", return_raw)] pub fn multiply_di(x: Decimal, y: INT) -> Result> { - multiply_dd(x, y.into()) + multiply(x, y.into()) } #[rhai_fn(name = "/", return_raw)] - pub fn divide_dd(x: Decimal, y: Decimal) -> Result> { + pub fn divide(x: Decimal, y: Decimal) -> Result> { if cfg!(not(feature = "unchecked")) { // Detect division by zero if y == Decimal::zero() { @@ -427,14 +427,14 @@ mod decimal_functions { } #[rhai_fn(name = "/", return_raw)] pub fn divide_id(x: INT, y: Decimal) -> Result> { - divide_dd(x.into(), y) + divide(x.into(), y) } #[rhai_fn(name = "/", return_raw)] pub fn divide_di(x: Decimal, y: INT) -> Result> { - divide_dd(x, y.into()) + divide(x, y.into()) } #[rhai_fn(name = "%", return_raw)] - pub fn modulo_dd(x: Decimal, y: Decimal) -> Result> { + pub fn modulo(x: Decimal, y: Decimal) -> Result> { if cfg!(not(feature = "unchecked")) { x.checked_rem(y) .ok_or_else(|| { @@ -450,11 +450,11 @@ mod decimal_functions { } #[rhai_fn(name = "%", return_raw)] pub fn modulo_id(x: INT, y: Decimal) -> Result> { - modulo_dd(x.into(), y) + modulo(x.into(), y) } #[rhai_fn(name = "%", return_raw)] pub fn modulo_di(x: Decimal, y: INT) -> Result> { - modulo_dd(x, y.into()) + modulo(x, y.into()) } #[rhai_fn(name = "-")] pub fn neg(x: Decimal) -> Decimal { From b2ca8c34d1b7e6f39d9d23634d799bfe0617933c Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 17 Feb 2021 12:27:27 +0800 Subject: [PATCH 2/4] Add atan2 and hypot functions. --- RELEASES.md | 1 + src/packages/math_basic.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 89d2fd3b..e364c74b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -32,6 +32,7 @@ Enhancements ------------ * Functions resolution cache is used in more cases, making repeated function calls faster. +* Added `atan(x, y)` and `hypot(x, y)` to `BasicMathPackage`. Version 0.19.11 diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index 661afd26..5b8bc8dd 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -170,6 +170,10 @@ mod trig_functions { pub fn atan(x: FLOAT) -> FLOAT { x.atan() } + #[rhai_fn(name = "atan")] + pub fn atan2(x: FLOAT, y: FLOAT) -> FLOAT { + x.atan2(y) + } pub fn asinh(x: FLOAT) -> FLOAT { x.asinh() } @@ -179,6 +183,9 @@ mod trig_functions { pub fn atanh(x: FLOAT) -> FLOAT { x.atanh() } + pub fn hypot(x: FLOAT, y: FLOAT) -> FLOAT { + x.hypot(y) + } } #[cfg(not(feature = "no_float"))] From a2277d07f3d9b6326fc2fe7f95e048035636c603 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 17 Feb 2021 13:06:47 +0800 Subject: [PATCH 3/4] Add arithmetic operators between FLOAT and INT. --- RELEASES.md | 1 + src/packages/arithmetic.rs | 88 +++++++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index e364c74b..9e80f364 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -33,6 +33,7 @@ Enhancements * Functions resolution cache is used in more cases, making repeated function calls faster. * Added `atan(x, y)` and `hypot(x, y)` to `BasicMathPackage`. +* Added standard arithmetic operators between `FLOAT` and `INT`. Version 0.19.11 diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 60837813..39cae250 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -255,6 +255,48 @@ mod f32_functions { Ok(Dynamic::from(x.powf(y))) } } + + #[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) + } + #[rhai_fn(name = "-")] pub fn neg(x: f32) -> f32 { -x @@ -314,10 +356,52 @@ mod f64_functions { x % y } #[rhai_fn(name = "**", return_raw)] - pub fn pow_f_f(x: f64, y: f64) -> Result> { - Ok(Dynamic::from(x.powf(y))) + pub fn pow_f_f(x: f64, y: f64) -> f64 { + x.powf(y) } } + + #[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) + } + #[rhai_fn(name = "-")] pub fn neg(x: f64) -> f64 { -x From 678d0f5e338319bc70ee6f387701719959e3659b Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 17 Feb 2021 14:05:35 +0800 Subject: [PATCH 4/4] Fix f32_float build. --- src/packages/arithmetic.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index 39cae250..c86c61cc 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -250,9 +250,9 @@ mod f32_functions { pub fn modulo(x: f32, y: f32) -> f32 { x % y } - #[rhai_fn(name = "**", return_raw)] - pub fn pow_f_f(x: f32, y: f32) -> Result> { - Ok(Dynamic::from(x.powf(y))) + #[rhai_fn(name = "**")] + pub fn pow_f_f(x: f32, y: f32) -> f32 { + x.powf(y) } } @@ -355,7 +355,7 @@ mod f64_functions { pub fn modulo(x: f64, y: f64) -> f64 { x % y } - #[rhai_fn(name = "**", return_raw)] + #[rhai_fn(name = "**")] pub fn pow_f_f(x: f64, y: f64) -> f64 { x.powf(y) }