Bump version of rust_decimal and add more functions.

This commit is contained in:
Stephen Chung 2021-05-11 20:31:31 +08:00
parent 97c8194d17
commit be052b2b26
6 changed files with 76 additions and 28 deletions

View File

@ -32,7 +32,7 @@ no_float = [] # no floating-point
f32_float = [] # set FLOAT=f32 f32_float = [] # set FLOAT=f32
only_i32 = [] # set INT=i32 (useful for 32-bit systems) only_i32 = [] # set INT=i32 (useful for 32-bit systems)
only_i64 = [] # set INT=i64 (default) and disable support for all other integer types 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_index = [] # no arrays and indexing
no_object = [] # no custom objects no_object = [] # no custom objects
no_function = ["no_closure"] # no script-defined functions (meaning no closures) no_function = ["no_closure"] # no script-defined functions (meaning no closures)
@ -92,8 +92,9 @@ default_features = false
optional = true optional = true
[dependencies.rust_decimal] [dependencies.rust_decimal]
version = "1.11" version = "1.13"
default_features = false default_features = false
features = ["maths"]
optional = true optional = true
[target.'cfg(target_arch = "wasm32")'.dependencies] [target.'cfg(target_arch = "wasm32")'.dependencies]

View File

@ -777,6 +777,10 @@ impl Dynamic {
pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG, AccessMode::ReadWrite)); pub const ZERO: Dynamic = Self(Union::Int(0, DEFAULT_TAG, AccessMode::ReadWrite));
/// A [`Dynamic`] containing the integer one. /// A [`Dynamic`] containing the integer one.
pub const ONE: Dynamic = Self(Union::Int(1, DEFAULT_TAG, AccessMode::ReadWrite)); 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. /// A [`Dynamic`] containing the integer negative one.
pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG, AccessMode::ReadWrite)); pub const NEGATIVE_ONE: Dynamic = Self(Union::Int(-1, DEFAULT_TAG, AccessMode::ReadWrite));
/// A [`Dynamic`] containing `0.0`. /// A [`Dynamic`] containing `0.0`.
@ -797,6 +801,24 @@ impl Dynamic {
DEFAULT_TAG, DEFAULT_TAG,
AccessMode::ReadWrite, 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`. /// A [`Dynamic`] containing the `-1.0`.
/// ///
/// Not available under `no_float`. /// Not available under `no_float`.

View File

@ -184,15 +184,19 @@ pub fn get_builtin_binary_op_fn(
"*" => impl_op!(from Decimal => multiply($xx, $yy)), "*" => impl_op!(from Decimal => multiply($xx, $yy)),
"/" => impl_op!(from Decimal => divide($xx, $yy)), "/" => impl_op!(from Decimal => divide($xx, $yy)),
"%" => impl_op!(from Decimal => modulo($xx, $yy)), "%" => impl_op!(from Decimal => modulo($xx, $yy)),
"**" => impl_op!(from Decimal => power($xx, $yy)),
_ => () _ => ()
} }
} else { } else {
use rust_decimal::MathematicalOps;
match op { 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 * $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 => multiply($xx, $yy)),
"/=" => impl_op!(from $x => divide($xx, $yy)), "/=" => impl_op!(from $x => divide($xx, $yy)),
"%=" => impl_op!(from $x => modulo($xx, $yy)), "%=" => impl_op!(from $x => modulo($xx, $yy)),
"**=" => impl_op!(from $x => power($xx, $yy)),
_ => return None, _ => return None,
} }
} else { } else {
use rust_decimal::MathematicalOps;
match op { 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 *= $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, _ => return None,
} }
} }

View File

@ -5,9 +5,6 @@ use crate::{def_package, EvalAltResult, Position, INT};
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
use std::prelude::v1::*; use std::prelude::v1::*;
#[cfg(not(feature = "no_float"))]
use crate::FLOAT;
#[cfg(feature = "no_std")] #[cfg(feature = "no_std")]
#[cfg(not(feature = "no_float"))] #[cfg(not(feature = "no_float"))]
use num_traits::Float; use num_traits::Float;
@ -77,7 +74,7 @@ macro_rules! gen_arithmetic_functions {
} else if y < 0 { } else if y < 0 {
Err(make_err(format!("Integer raised to a negative index: {} ~ {}", x, y))) Err(make_err(format!("Integer raised to a negative index: {} ~ {}", x, y)))
} else { } 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 { } else {
Ok(x.pow(y as u32)) Ok(x.pow(y as u32))
@ -423,23 +420,13 @@ mod f64_functions {
1 1
} }
} }
#[rhai_fn(name = "**", return_raw)]
pub fn pow_f_i(x: FLOAT, y: INT) -> Result<FLOAT, Box<EvalAltResult>> {
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")] #[cfg(feature = "decimal")]
#[export_module] #[export_module]
pub mod decimal_functions { 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)] #[rhai_fn(skip, return_raw)]
pub fn add(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> { pub fn add(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
@ -495,6 +482,15 @@ pub mod decimal_functions {
Ok(x % y) Ok(x % y)
} }
} }
#[rhai_fn(skip, return_raw)]
pub fn power(x: Decimal, y: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
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 = "-")] #[rhai_fn(name = "-")]
pub fn neg(x: Decimal) -> Decimal { pub fn neg(x: Decimal) -> Decimal {
-x -x

View File

@ -253,15 +253,11 @@ def_package!(crate:BasicIteratorPackage:"Basic range iterators.", lib, {
impl StepDecimalRange { impl StepDecimalRange {
pub fn new(from: Decimal, to: Decimal, step: Decimal) -> Result<Self, Box<EvalAltResult>> { pub fn new(from: Decimal, to: Decimal, step: Decimal) -> Result<Self, Box<EvalAltResult>> {
#[cfg(not(feature = "unchecked"))] #[cfg(not(feature = "unchecked"))]
{ if step.is_zero() {
use num_traits::Zero; return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(),
Box::new(EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE)),
if step.is_zero() { crate::Position::NONE,
return EvalAltResult::ErrorInFunctionCall("range".to_string(), "".to_string(), ).into();
Box::new(EvalAltResult::ErrorArithmetic("step value cannot be zero".to_string(), crate::Position::NONE)),
crate::Position::NONE,
).into();
}
} }
Ok(Self(from, to, step)) Ok(Self(from, to, step))

View File

@ -222,6 +222,7 @@ mod float_functions {
pub fn log(x: FLOAT, base: FLOAT) -> FLOAT { pub fn log(x: FLOAT, base: FLOAT) -> FLOAT {
x.log(base) x.log(base)
} }
#[rhai_fn(name = "log")]
pub fn log10(x: FLOAT) -> FLOAT { pub fn log10(x: FLOAT) -> FLOAT {
x.log10() x.log10()
} }
@ -305,9 +306,33 @@ mod float_functions {
mod decimal_functions { mod decimal_functions {
use rust_decimal::{ use rust_decimal::{
prelude::{FromStr, RoundingStrategy}, prelude::{FromStr, RoundingStrategy},
Decimal, Decimal, MathematicalOps,
}; };
#[rhai_fn(return_raw)]
pub fn sqrt(x: Decimal) -> Result<Decimal, Box<EvalAltResult>> {
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<Decimal, Box<EvalAltResult>> {
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")] #[rhai_fn(name = "floor", get = "floor")]
pub fn floor(x: Decimal) -> Decimal { pub fn floor(x: Decimal) -> Decimal {
x.floor() x.floor()