Provide short-cuts to Decimal calculations.

This commit is contained in:
Stephen Chung 2021-02-15 17:42:33 +08:00
parent f5c2903071
commit 909d48caed
2 changed files with 88 additions and 22 deletions

View File

@ -1325,8 +1325,6 @@ pub fn run_builtin_binary_op(
x: &Dynamic, x: &Dynamic,
y: &Dynamic, y: &Dynamic,
) -> Result<Option<Dynamic>, Box<EvalAltResult>> { ) -> Result<Option<Dynamic>, Box<EvalAltResult>> {
use crate::packages::arithmetic::arith_basic::INT::functions::*;
let args_type = x.type_id(); let args_type = x.type_id();
let second_type = y.type_id(); let second_type = y.type_id();
@ -1358,6 +1356,8 @@ pub fn run_builtin_binary_op(
let y = y.clone().cast::<INT>(); let y = y.clone().cast::<INT>();
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
use crate::packages::arithmetic::arith_basic::INT::functions::*;
match op { match op {
"+" => return add(x, y).map(Some), "+" => return add(x, y).map(Some),
"-" => return subtract(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::<rust_decimal::Decimal>() {
let x = x.clone().cast::<rust_decimal::Decimal>();
let y = y.clone().cast::<rust_decimal::Decimal>();
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) Ok(None)
} }
@ -1474,8 +1512,6 @@ pub fn run_builtin_op_assignment(
x: &mut Dynamic, x: &mut Dynamic,
y: &Dynamic, y: &Dynamic,
) -> Result<Option<()>, Box<EvalAltResult>> { ) -> Result<Option<()>, Box<EvalAltResult>> {
use crate::packages::arithmetic::arith_basic::INT::functions::*;
let args_type = x.type_id(); let args_type = x.type_id();
let second_type = y.type_id(); let second_type = y.type_id();
@ -1498,13 +1534,15 @@ pub fn run_builtin_op_assignment(
let mut x = x.write_lock::<INT>().unwrap(); let mut x = x.write_lock::<INT>().unwrap();
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
use crate::packages::arithmetic::arith_basic::INT::functions::*;
match op { match op {
"+=" => return Ok(Some(*x = add(*x, y)?.as_int().unwrap())), "+=" => return Ok(Some(*x = add(*x, y)?.as_int().unwrap())),
"-=" => return Ok(Some(*x = subtract(*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 = multiply(*x, y)?.as_int().unwrap())),
"/=" => return Ok(Some(*x = divide(*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 = 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_right(*x, y)?.as_int().unwrap())),
"<<=" => return Ok(Some(*x = shift_left(*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 /= 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)),
"<<=" => 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 /= 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::<rust_decimal::Decimal>() {
let y = y.clone().cast::<rust_decimal::Decimal>();
let mut x = x.write_lock::<rust_decimal::Decimal>().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) Ok(None)
} }

View File

@ -357,7 +357,7 @@ mod decimal_functions {
use rust_decimal::{prelude::Zero, Decimal}; use rust_decimal::{prelude::Zero, Decimal};
#[rhai_fn(name = "+", return_raw)] #[rhai_fn(name = "+", return_raw)]
pub fn add_dd(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn add(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
x.checked_add(y) x.checked_add(y)
.ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y))) .ok_or_else(|| make_err(format!("Addition overflow: {} + {}", x, y)))
@ -368,14 +368,14 @@ mod decimal_functions {
} }
#[rhai_fn(name = "+", return_raw)] #[rhai_fn(name = "+", return_raw)]
pub fn add_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn add_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
add_dd(x.into(), y) add(x.into(), y)
} }
#[rhai_fn(name = "+", return_raw)] #[rhai_fn(name = "+", return_raw)]
pub fn add_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn add_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
add_dd(x, y.into()) add(x, y.into())
} }
#[rhai_fn(name = "-", return_raw)] #[rhai_fn(name = "-", return_raw)]
pub fn subtract_dd(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn subtract(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
x.checked_sub(y) x.checked_sub(y)
.ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y))) .ok_or_else(|| make_err(format!("Subtraction overflow: {} - {}", x, y)))
@ -386,14 +386,14 @@ mod decimal_functions {
} }
#[rhai_fn(name = "-", return_raw)] #[rhai_fn(name = "-", return_raw)]
pub fn subtract_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn subtract_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
subtract_dd(x.into(), y) subtract(x.into(), y)
} }
#[rhai_fn(name = "-", return_raw)] #[rhai_fn(name = "-", return_raw)]
pub fn subtract_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn subtract_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
subtract_dd(x, y.into()) subtract(x, y.into())
} }
#[rhai_fn(name = "*", return_raw)] #[rhai_fn(name = "*", return_raw)]
pub fn multiply_dd(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn multiply(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
x.checked_mul(y) x.checked_mul(y)
.ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y))) .ok_or_else(|| make_err(format!("Multiplication overflow: {} * {}", x, y)))
@ -404,14 +404,14 @@ mod decimal_functions {
} }
#[rhai_fn(name = "*", return_raw)] #[rhai_fn(name = "*", return_raw)]
pub fn multiply_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn multiply_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
multiply_dd(x.into(), y) multiply(x.into(), y)
} }
#[rhai_fn(name = "*", return_raw)] #[rhai_fn(name = "*", return_raw)]
pub fn multiply_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn multiply_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
multiply_dd(x, y.into()) multiply(x, y.into())
} }
#[rhai_fn(name = "/", return_raw)] #[rhai_fn(name = "/", return_raw)]
pub fn divide_dd(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn divide(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
// Detect division by zero // Detect division by zero
if y == Decimal::zero() { if y == Decimal::zero() {
@ -427,14 +427,14 @@ mod decimal_functions {
} }
#[rhai_fn(name = "/", return_raw)] #[rhai_fn(name = "/", return_raw)]
pub fn divide_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn divide_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
divide_dd(x.into(), y) divide(x.into(), y)
} }
#[rhai_fn(name = "/", return_raw)] #[rhai_fn(name = "/", return_raw)]
pub fn divide_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn divide_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
divide_dd(x, y.into()) divide(x, y.into())
} }
#[rhai_fn(name = "%", return_raw)] #[rhai_fn(name = "%", return_raw)]
pub fn modulo_dd(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn modulo(x: Decimal, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
x.checked_rem(y) x.checked_rem(y)
.ok_or_else(|| { .ok_or_else(|| {
@ -450,11 +450,11 @@ mod decimal_functions {
} }
#[rhai_fn(name = "%", return_raw)] #[rhai_fn(name = "%", return_raw)]
pub fn modulo_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> { pub fn modulo_id(x: INT, y: Decimal) -> Result<Dynamic, Box<EvalAltResult>> {
modulo_dd(x.into(), y) modulo(x.into(), y)
} }
#[rhai_fn(name = "%", return_raw)] #[rhai_fn(name = "%", return_raw)]
pub fn modulo_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn modulo_di(x: Decimal, y: INT) -> Result<Dynamic, Box<EvalAltResult>> {
modulo_dd(x, y.into()) modulo(x, y.into())
} }
#[rhai_fn(name = "-")] #[rhai_fn(name = "-")]
pub fn neg(x: Decimal) -> Decimal { pub fn neg(x: Decimal) -> Decimal {