From be052b2b2605b89925342f092a43f27449dce4a9 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 11 May 2021 20:31:31 +0800 Subject: [PATCH] Bump version of rust_decimal and add more functions. --- Cargo.toml | 5 +++-- src/dynamic.rs | 22 ++++++++++++++++++++++ src/fn_builtin.rs | 8 ++++++++ src/packages/arithmetic.rs | 28 ++++++++++++---------------- src/packages/iter_basic.rs | 14 +++++--------- src/packages/math_basic.rs | 27 ++++++++++++++++++++++++++- 6 files changed, 76 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 28a6511d..dd2d32de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ no_float = [] # no floating-point f32_float = [] # set FLOAT=f32 only_i32 = [] # set INT=i32 (useful for 32-bit systems) only_i64 = [] # set INT=i64 (default) and disable support for all other integer types -decimal = ["rust_decimal"] # add the Decimal number type +decimal = ["rust_decimal/std"] # add the Decimal number type no_index = [] # no arrays and indexing no_object = [] # no custom objects no_function = ["no_closure"] # no script-defined functions (meaning no closures) @@ -92,8 +92,9 @@ default_features = false optional = true [dependencies.rust_decimal] -version = "1.11" +version = "1.13" default_features = false +features = ["maths"] optional = true [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/src/dynamic.rs b/src/dynamic.rs index 3ec2b1d7..5b1a01d5 100644 --- a/src/dynamic.rs +++ b/src/dynamic.rs @@ -777,6 +777,10 @@ impl Dynamic { pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG, AccessMode::ReadWrite)); /// A [`Dynamic`] containing the integer one. pub const ONE: Dynamic = Self(Union::Int(1, DEFAULT_TAG, AccessMode::ReadWrite)); + /// A [`Dynamic`] containing the integer two. + pub const TWO: Dynamic = Self(Union::Int(2, DEFAULT_TAG, AccessMode::ReadWrite)); + /// A [`Dynamic`] containing the integer ten. + pub const TEN: Dynamic = Self(Union::Int(10, DEFAULT_TAG, AccessMode::ReadWrite)); /// A [`Dynamic`] containing the integer negative one. pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG, AccessMode::ReadWrite)); /// A [`Dynamic`] containing `0.0`. @@ -797,6 +801,24 @@ impl Dynamic { DEFAULT_TAG, AccessMode::ReadWrite, )); + /// A [`Dynamic`] containing `2.0`. + /// + /// Not available under `no_float`. + #[cfg(not(feature = "no_float"))] + pub const FLOAT_TWO: Dynamic = Self(Union::Float( + FloatWrapper::const_new(2.0), + DEFAULT_TAG, + AccessMode::ReadWrite, + )); + /// A [`Dynamic`] containing `10.0`. + /// + /// Not available under `no_float`. + #[cfg(not(feature = "no_float"))] + pub const FLOAT_TEN: Dynamic = Self(Union::Float( + FloatWrapper::const_new(10.0), + DEFAULT_TAG, + AccessMode::ReadWrite, + )); /// A [`Dynamic`] containing the `-1.0`. /// /// Not available under `no_float`. diff --git a/src/fn_builtin.rs b/src/fn_builtin.rs index 87f7bcba..b95b0fcf 100644 --- a/src/fn_builtin.rs +++ b/src/fn_builtin.rs @@ -184,15 +184,19 @@ pub fn get_builtin_binary_op_fn( "*" => impl_op!(from Decimal => multiply($xx, $yy)), "/" => impl_op!(from Decimal => divide($xx, $yy)), "%" => impl_op!(from Decimal => modulo($xx, $yy)), + "**" => impl_op!(from Decimal => power($xx, $yy)), _ => () } } else { + use rust_decimal::MathematicalOps; + match op { "+" => impl_op!(from Decimal => $xx + $yy), "-" => impl_op!(from Decimal => $xx - $yy), "*" => impl_op!(from Decimal => $xx * $yy), "/" => impl_op!(from Decimal => $xx / $yy), "%" => impl_op!(from Decimal => $xx % $yy), + "**" => impl_op!(from Decimal => $xx.powd($yy)), _ => () } } @@ -522,15 +526,19 @@ pub fn get_builtin_op_assignment_fn( "*=" => impl_op!(from $x => multiply($xx, $yy)), "/=" => impl_op!(from $x => divide($xx, $yy)), "%=" => impl_op!(from $x => modulo($xx, $yy)), + "**=" => impl_op!(from $x => power($xx, $yy)), _ => return None, } } else { + use rust_decimal::MathematicalOps; + match op { "+=" => impl_op!(from $x += $yy), "-=" => impl_op!(from $x -= $yy), "*=" => impl_op!(from $x *= $yy), "/=" => impl_op!(from $x /= $yy), "%=" => impl_op!(from $x %= $yy), + "**=" => impl_op!(from $x => $xx.powd($yy)), _ => return None, } } diff --git a/src/packages/arithmetic.rs b/src/packages/arithmetic.rs index e70ef146..27d639c1 100644 --- a/src/packages/arithmetic.rs +++ b/src/packages/arithmetic.rs @@ -5,9 +5,6 @@ use crate::{def_package, EvalAltResult, Position, INT}; #[cfg(feature = "no_std")] use std::prelude::v1::*; -#[cfg(not(feature = "no_float"))] -use crate::FLOAT; - #[cfg(feature = "no_std")] #[cfg(not(feature = "no_float"))] use num_traits::Float; @@ -77,7 +74,7 @@ macro_rules! gen_arithmetic_functions { } else if y < 0 { 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!("Power overflow: {} ~ {}", x, y))) + x.checked_pow(y as u32).ok_or_else(|| make_err(format!("Exponential overflow: {} ~ {}", x, y))) } } else { Ok(x.pow(y as u32)) @@ -423,23 +420,13 @@ mod f64_functions { 1 } } - #[rhai_fn(name = "**", return_raw)] - pub fn pow_f_i(x: FLOAT, y: INT) -> Result> { - if cfg!(not(feature = "unchecked")) && y > (i32::MAX as INT) { - Err(make_err(format!( - "Number raised to too large an index: {} ~ {}", - x, y - ))) - } else { - Ok(x.powi(y as i32)) - } - } } #[cfg(feature = "decimal")] #[export_module] pub mod decimal_functions { - use rust_decimal::{prelude::Zero, Decimal}; + use num_traits::Pow; + use rust_decimal::{prelude::Zero, Decimal, MathematicalOps}; #[rhai_fn(skip, return_raw)] pub fn add(x: Decimal, y: Decimal) -> Result> { @@ -495,6 +482,15 @@ pub mod decimal_functions { Ok(x % y) } } + #[rhai_fn(skip, return_raw)] + pub fn power(x: Decimal, y: Decimal) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.checked_powd(y) + .ok_or_else(|| make_err(format!("Exponential overflow: {} + {}", x, y))) + } else { + Ok(x.pow(y)) + } + } #[rhai_fn(name = "-")] pub fn neg(x: Decimal) -> Decimal { -x diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index 927821a8..b7739151 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -253,15 +253,11 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, { impl StepDecimalRange { pub fn new(from: Decimal, to: Decimal, step: Decimal) -> Result> { #[cfg(not(feature = "unchecked"))] - { - use num_traits::Zero; - - if step.is_zero() { - return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), - Box::new(EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE)), - crate::Position::NONE, - ).into(); - } + if step.is_zero() { + return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), + Box::new(EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE)), + crate::Position::NONE, + ).into(); } Ok(Self(from, to, step)) diff --git a/src/packages/math_basic.rs b/src/packages/math_basic.rs index 56cc7105..9301ea46 100644 --- a/src/packages/math_basic.rs +++ b/src/packages/math_basic.rs @@ -222,6 +222,7 @@ mod float_functions { pub fn log(x: FLOAT, base: FLOAT) -> FLOAT { x.log(base) } + #[rhai_fn(name = "log")] pub fn log10(x: FLOAT) -> FLOAT { x.log10() } @@ -305,9 +306,33 @@ mod float_functions { mod decimal_functions { use rust_decimal::{ prelude::{FromStr, RoundingStrategy}, - Decimal, + Decimal, MathematicalOps, }; + #[rhai_fn(return_raw)] + pub fn sqrt(x: Decimal) -> Result> { + if cfg!(not(feature = "unchecked")) { + x.sqrt() + .ok_or_else(|| make_err(format!("Error taking the square root of {}", x,))) + } else { + Ok(x.sqrt().unwrap()) + } + } + #[rhai_fn(return_raw)] + pub fn exp(x: Decimal) -> Result> { + if cfg!(not(feature = "unchecked")) { + if x > Decimal::from_parts(10, 0, 0, false, 0) { + Err(make_err(format!("Exponential overflow: e ** {}", x,))) + } else { + Ok(x.exp()) + } + } else { + Ok(x.exp()) + } + } + pub fn ln(x: Decimal) -> Decimal { + x.ln() + } #[rhai_fn(name = "floor", get = "floor")] pub fn floor(x: Decimal) -> Decimal { x.floor()