Refine Decimal rounding.

This commit is contained in:
Stephen Chung 2021-02-15 12:07:45 +08:00
parent 40e4a92401
commit f5c2903071

View File

@ -302,7 +302,10 @@ mod float_functions {
#[cfg(feature = "decimal")] #[cfg(feature = "decimal")]
#[export_module] #[export_module]
mod decimal_functions { mod decimal_functions {
use rust_decimal::{prelude::FromStr, Decimal}; use rust_decimal::{
prelude::{FromStr, RoundingStrategy},
Decimal,
};
#[rhai_fn(name = "floor", get = "floor")] #[rhai_fn(name = "floor", get = "floor")]
pub fn floor(x: Decimal) -> Decimal { pub fn floor(x: Decimal) -> Decimal {
@ -316,14 +319,11 @@ mod decimal_functions {
pub fn round(x: Decimal) -> Decimal { pub fn round(x: Decimal) -> Decimal {
x.round() x.round()
} }
#[rhai_fn(return_raw)] #[rhai_fn(name = "round", return_raw)]
pub fn round_dp(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn round_dp(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) { if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
return Err(make_err(format!( return Ok(x.into());
"Decimal value {} round to too many decimal points: {}",
x, dp
)));
} }
if dp < 0 { if dp < 0 {
return Err(make_err(format!( return Err(make_err(format!(
@ -333,16 +333,13 @@ mod decimal_functions {
} }
} }
Ok(Dynamic::from(x.round_dp(dp as u32))) Ok(x.round_dp(dp as u32).into())
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn round_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn round_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) { if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
return Err(make_err(format!( return Ok(x.into());
"Decimal value {} round to too many decimal points: {}",
x, dp
)));
} }
if dp < 0 { if dp < 0 {
return Err(make_err(format!( return Err(make_err(format!(
@ -352,19 +349,16 @@ mod decimal_functions {
} }
} }
Ok(Dynamic::from(x.round_dp_with_strategy( Ok(
dp as u32, x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundUp)
rust_decimal::prelude::RoundingStrategy::RoundUp, .into(),
))) )
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn round_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn round_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) { if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
return Err(make_err(format!( return Ok(x.into());
"Decimal value {} round to too many decimal points: {}",
x, dp
)));
} }
if dp < 0 { if dp < 0 {
return Err(make_err(format!( return Err(make_err(format!(
@ -374,19 +368,16 @@ mod decimal_functions {
} }
} }
Ok(Dynamic::from(x.round_dp_with_strategy( Ok(
dp as u32, x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundDown)
rust_decimal::prelude::RoundingStrategy::RoundDown, .into(),
))) )
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn round_half_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn round_half_up(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) { if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
return Err(make_err(format!( return Ok(x.into());
"Decimal value {} round to too many decimal points: {}",
x, dp
)));
} }
if dp < 0 { if dp < 0 {
return Err(make_err(format!( return Err(make_err(format!(
@ -396,19 +387,16 @@ mod decimal_functions {
} }
} }
Ok(Dynamic::from(x.round_dp_with_strategy( Ok(
dp as u32, x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfUp)
rust_decimal::prelude::RoundingStrategy::RoundHalfUp, .into(),
))) )
} }
#[rhai_fn(return_raw)] #[rhai_fn(return_raw)]
pub fn round_half_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> { pub fn round_half_down(x: Decimal, dp: INT) -> Result<Dynamic, Box<EvalAltResult>> {
if cfg!(not(feature = "unchecked")) { if cfg!(not(feature = "unchecked")) {
if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) { if cfg!(not(feature = "only_i32")) && dp > (u32::MAX as INT) {
return Err(make_err(format!( return Ok(x.into());
"Decimal value {} round to too many decimal points: {}",
x, dp
)));
} }
if dp < 0 { if dp < 0 {
return Err(make_err(format!( return Err(make_err(format!(
@ -418,10 +406,10 @@ mod decimal_functions {
} }
} }
Ok(Dynamic::from(x.round_dp_with_strategy( Ok(
dp as u32, x.round_dp_with_strategy(dp as u32, RoundingStrategy::RoundHalfDown)
rust_decimal::prelude::RoundingStrategy::RoundHalfDown, .into(),
))) )
} }
#[rhai_fn(name = "int", get = "int")] #[rhai_fn(name = "int", get = "int")]
pub fn int(x: Decimal) -> Decimal { pub fn int(x: Decimal) -> Decimal {