diff --git a/src/constants.rs b/src/constants.rs index 59f3366..a42940f 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -20,13 +20,13 @@ pub const SIGN_SHIFT: u32 = 31; // to the byte boundary for simplicity. pub const MAX_STR_BUFFER_SIZE: usize = 32; -// The maximum supported precision -pub const MAX_PRECISION: u8 = 28; +// The maximum supported [`Decimal::scale`] value +pub const MAX_SCALE: u8 = 28; #[cfg(not(feature = "legacy-ops"))] // u8 to i32 is infallible, therefore, this cast will never overflow -pub const MAX_PRECISION_I32: i32 = MAX_PRECISION as _; +pub const MAX_SCALE_I32: i32 = MAX_SCALE as _; // u8 to u32 is infallible, therefore, this cast will never overflow -pub const MAX_PRECISION_U32: u32 = MAX_PRECISION as _; +pub const MAX_SCALE_U32: u32 = MAX_SCALE as _; // 79,228,162,514,264,337,593,543,950,335 pub const MAX_I128_REPR: i128 = 0x0000_0000_FFFF_FFFF_FFFF_FFFF_FFFF_FFFF; diff --git a/src/decimal.rs b/src/decimal.rs index e34fbea..e828801 100644 --- a/src/decimal.rs +++ b/src/decimal.rs @@ -1,5 +1,5 @@ use crate::constants::{ - MAX_I128_REPR, MAX_PRECISION_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, SIGN_SHIFT, U32_MASK, U8_MASK, + MAX_I128_REPR, MAX_SCALE_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, SIGN_SHIFT, U32_MASK, U8_MASK, UNSIGN_MASK, }; use crate::ops; @@ -272,6 +272,14 @@ impl Decimal { /// assert_eq!(Decimal::ONE_THOUSAND, dec!(1000)); /// ``` pub const ONE_THOUSAND: Decimal = ONE_THOUSAND; + /// The maximum supported scale value. + /// + /// Some operations, such as [`Self::rescale`] may accept larger scale values, but these + /// operations will result in a final value with a scale no larger than this. + /// + /// Note that the maximum scale is _not_ the same as the maximum possible numeric precision in + /// base-10. + pub const MAX_SCALE: u32 = MAX_SCALE_U32; /// A constant representing π as 3.1415926535897932384626433833 /// @@ -385,7 +393,7 @@ impl Decimal { /// /// # Panics /// - /// This function panics if `scale` is > 28. + /// This function panics if `scale` is > [`Self::MAX_SCALE`]. /// /// # Example /// @@ -403,7 +411,7 @@ impl Decimal { } } - /// Checked version of `Decimal::new`. Will return `Err` instead of panicking at run-time. + /// Checked version of [`Self::new`]. Will return an error instead of panicking at run-time. /// /// # Example /// @@ -414,7 +422,7 @@ impl Decimal { /// assert!(max.is_err()); /// ``` pub const fn try_new(num: i64, scale: u32) -> crate::Result { - if scale > MAX_PRECISION_U32 { + if scale > Self::MAX_SCALE { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } let flags: u32 = scale << SCALE_SHIFT; @@ -444,7 +452,8 @@ impl Decimal { /// /// # Panics /// - /// This function panics if `scale` is > 28 or if `num` exceeds the maximum supported 96 bits. + /// This function panics if `scale` is > [`Self::MAX_SCALE`] or if `num` exceeds the maximum + /// supported 96 bits. /// /// # Example /// @@ -474,7 +483,7 @@ impl Decimal { /// assert!(max.is_err()); /// ``` pub const fn try_from_i128_with_scale(num: i128, scale: u32) -> crate::Result { - if scale > MAX_PRECISION_U32 { + if scale > Self::MAX_SCALE { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } let mut neg = false; @@ -504,14 +513,7 @@ impl Decimal { /// * `mid` - The middle 32 bits of a 96-bit integer. /// * `hi` - The high 32 bits of a 96-bit integer. /// * `negative` - `true` to indicate a negative number. - /// * `scale` - A power of 10 ranging from 0 to 28. - /// - /// # Caution: Undefined behavior - /// - /// While a scale greater than 28 can be passed in, it will be automatically capped by this - /// function at the maximum precision. The library opts towards this functionality as opposed - /// to a panic to ensure that the function can be treated as constant. This may lead to - /// undefined behavior in downstream applications and should be treated with caution. + /// * `scale` - A power of 10 ranging from 0 to [`Self::MAX_SCALE`]. /// /// # Example /// @@ -523,6 +525,7 @@ impl Decimal { /// ``` #[must_use] pub const fn from_parts(lo: u32, mid: u32, hi: u32, negative: bool, scale: u32) -> Decimal { + assert!(scale <= Self::MAX_SCALE, "Scale exceeds maximum supported scale"); Decimal { lo, mid, @@ -533,7 +536,7 @@ impl Decimal { } else { negative }, - scale % (MAX_PRECISION_U32 + 1), + scale, ), } } @@ -596,7 +599,7 @@ impl Decimal { // we've parsed 1.2 as the base and 10 as the exponent. To represent this within a // Decimal type we effectively store the mantissa as 12,000,000,000 and scale as // zero. - if exp > MAX_PRECISION_U32 { + if exp > Self::MAX_SCALE { return Err(Error::ScaleExceedsMaximumPrecision(exp)); } let mut exp = exp as usize; @@ -856,7 +859,7 @@ impl Decimal { /// # } /// ``` pub fn set_scale(&mut self, scale: u32) -> Result<(), Error> { - if scale > MAX_PRECISION_U32 { + if scale > Self::MAX_SCALE { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } self.flags = (scale << SCALE_SHIFT) | (self.flags & SIGN_MASK); @@ -870,7 +873,7 @@ impl Decimal { /// cause the newly created `Decimal` to perform rounding using the `MidpointAwayFromZero` strategy. /// /// Scales greater than the maximum precision that can be represented by `Decimal` will be - /// automatically rounded to either `Decimal::MAX_PRECISION` or the maximum precision that can + /// automatically rounded to either [`Self::MAX_SCALE`] or the maximum precision that can /// be represented with the given mantissa. /// /// # Arguments @@ -967,7 +970,7 @@ impl Decimal { hi: (bytes[12] as u32) | (bytes[13] as u32) << 8 | (bytes[14] as u32) << 16 | (bytes[15] as u32) << 24, }; // Scale must be bound to maximum precision. Only two values can be greater than this - if raw.scale() > MAX_PRECISION_U32 { + if raw.scale() > Self::MAX_SCALE { let mut bits = raw.mantissa_array3(); let remainder = match raw.scale() { 29 => ops::array::div_by_power::<1>(&mut bits), @@ -981,7 +984,7 @@ impl Decimal { raw.lo = bits[0]; raw.mid = bits[1]; raw.hi = bits[2]; - raw.flags = flags(raw.is_sign_negative(), MAX_PRECISION_U32); + raw.flags = flags(raw.is_sign_negative(), Self::MAX_SCALE); } raw } @@ -2204,7 +2207,7 @@ fn base2_to_decimal( // At this point, the mantissa has assimilated the exponent5, but // exponent10 might not be suitable for assignment. exponent10 must be - // in the range [-MAX_PRECISION..0], so the mantissa must be scaled up or + // in the range [-MAX_SCALE..0], so the mantissa must be scaled up or // down appropriately. while exponent10 > 0 { // In order to bring exponent10 down to 0, the mantissa should be @@ -2218,10 +2221,10 @@ fn base2_to_decimal( } } - // In order to bring exponent up to -MAX_PRECISION, the mantissa should + // In order to bring exponent up to -MAX_SCALE, the mantissa should // be divided by 10 to compensate. If the exponent10 is too small, this // will cause the mantissa to underflow and become 0. - while exponent10 < -(MAX_PRECISION_U32 as i32) { + while exponent10 < -(Decimal::MAX_SCALE as i32) { let rem10 = ops::array::div_by_u32(bits, 10); exponent10 += 1; if ops::array::is_all_zero(bits) { diff --git a/src/error.rs b/src/error.rs index 0bd8cfe..577b849 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,4 @@ -use crate::{constants::MAX_PRECISION_U32, Decimal}; +use crate::Decimal; use alloc::string::String; use core::fmt; @@ -57,7 +57,8 @@ impl fmt::Display for Error { Self::ScaleExceedsMaximumPrecision(ref scale) => { write!( f, - "Scale exceeds the maximum precision allowed: {scale} > {MAX_PRECISION_U32}" + "Scale exceeds the maximum precision allowed: {scale} > {}", + Decimal::MAX_SCALE ) } Self::ConversionTo(ref type_name) => { diff --git a/src/fuzz.rs b/src/fuzz.rs index 14f2e60..4ca6d01 100644 --- a/src/fuzz.rs +++ b/src/fuzz.rs @@ -8,7 +8,7 @@ impl Arbitrary<'_> for crate::Decimal { let mid = u32::arbitrary(u)?; let hi = u32::arbitrary(u)?; let negative = bool::arbitrary(u)?; - let scale = u32::arbitrary(u)?; + let scale = u32::arbitrary(u)? % (Self::MAX_SCALE + 1); Ok(Decimal::from_parts(lo, mid, hi, negative, scale)) } } diff --git a/src/ops/add.rs b/src/ops/add.rs index 9a0c5bd..b20aa2c 100644 --- a/src/ops/add.rs +++ b/src/ops/add.rs @@ -1,6 +1,4 @@ -use crate::constants::{ - MAX_I32_SCALE, MAX_PRECISION_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, U32_MASK, U32_MAX, -}; +use crate::constants::{MAX_I32_SCALE, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, U32_MASK, U32_MAX}; use crate::decimal::{CalculationResult, Decimal}; use crate::ops::common::{Buf24, Dec64}; @@ -263,7 +261,7 @@ fn unaligned_add( rescale_factor -= MAX_I32_SCALE; - if tmp64 > U32_MAX || scale > MAX_PRECISION_U32 { + if tmp64 > U32_MAX || scale > Decimal::MAX_SCALE { break; } else { high = tmp64 as u32; diff --git a/src/ops/array.rs b/src/ops/array.rs index ed3fce6..1f4d6ae 100644 --- a/src/ops/array.rs +++ b/src/ops/array.rs @@ -1,4 +1,4 @@ -use crate::constants::{MAX_PRECISION_U32, POWERS_10, U32_MASK}; +use crate::constants::{MAX_SCALE_U32, POWERS_10, U32_MASK}; /// Rescales the given decimal to new scale. /// e.g. with 1.23 and new scale 3 rescale the value to 1.230 @@ -15,7 +15,7 @@ fn rescale(value: &mut [u32; 3], value_scale: &mut u32, new_s } if is_all_zero(value) { - *value_scale = new_scale.min(MAX_PRECISION_U32); + *value_scale = new_scale.min(MAX_SCALE_U32); return; } diff --git a/src/ops/common.rs b/src/ops/common.rs index c29362d..56cfd94 100644 --- a/src/ops/common.rs +++ b/src/ops/common.rs @@ -1,4 +1,4 @@ -use crate::constants::{MAX_I32_SCALE, MAX_PRECISION_I32, POWERS_10}; +use crate::constants::{MAX_I32_SCALE, MAX_SCALE_I32, POWERS_10}; use crate::Decimal; #[derive(Debug)] @@ -96,12 +96,12 @@ impl Buf12 { return Some(x); } - if scale > MAX_PRECISION_I32 - 9 { + if scale > MAX_SCALE_I32 - 9 { // We can't scale by 10^9 without exceeding the max scale factor. // Instead, we'll try to scale by the most that we can and see if that works. // This is safe to do due to the check above. e.g. scale > 19 in the above, so it will // evaluate to 9 or less below. - x = (MAX_PRECISION_I32 - scale) as usize; + x = (MAX_SCALE_I32 - scale) as usize; if hi < POWER_OVERFLOW_VALUES[x - 1].data[2] { if x as i32 + scale < 0 { // We still overflow @@ -350,8 +350,8 @@ impl Buf24 { } // Make sure we scale enough to bring it into a valid range - if rescale_target < scale - MAX_PRECISION_I32 { - rescale_target = scale - MAX_PRECISION_I32; + if rescale_target < scale - MAX_SCALE_I32 { + rescale_target = scale - MAX_SCALE_I32; } if rescale_target > 0 { diff --git a/src/ops/div.rs b/src/ops/div.rs index aaebc9a..d6bede5 100644 --- a/src/ops/div.rs +++ b/src/ops/div.rs @@ -1,4 +1,4 @@ -use crate::constants::{MAX_PRECISION_I32, POWERS_10}; +use crate::constants::{MAX_SCALE_I32, POWERS_10}; use crate::decimal::{CalculationResult, Decimal}; use crate::ops::common::{Buf12, Buf16, Dec64}; @@ -260,7 +260,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu // We have a remainder so we effectively want to try to adjust the quotient and add // the remainder into the quotient. We do this below, however first of all we want // to try to avoid overflowing so we do that check first. - let will_overflow = if scale == MAX_PRECISION_I32 { + let will_overflow = if scale == MAX_SCALE_I32 { true } else { // Figure out how much we can scale by @@ -376,7 +376,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu // We have a remainder so we effectively want to try to adjust the quotient and add // the remainder into the quotient. We do this below, however first of all we want // to try to avoid overflowing so we do that check first. - let will_overflow = if scale == MAX_PRECISION_I32 { + let will_overflow = if scale == MAX_SCALE_I32 { true } else { // Figure out how much we can scale by @@ -467,7 +467,7 @@ pub(crate) fn div_impl(dividend: &Decimal, divisor: &Decimal) -> CalculationResu // We have a remainder so we effectively want to try to adjust the quotient and add // the remainder into the quotient. We do this below, however first of all we want // to try to avoid overflowing so we do that check first. - let will_overflow = if scale == MAX_PRECISION_I32 { + let will_overflow = if scale == MAX_SCALE_I32 { true } else { // Figure out how much we can scale by diff --git a/src/ops/legacy.rs b/src/ops/legacy.rs index 49f3981..7b9b228 100644 --- a/src/ops/legacy.rs +++ b/src/ops/legacy.rs @@ -1,5 +1,5 @@ use crate::{ - constants::{MAX_PRECISION_U32, POWERS_10, U32_MASK}, + constants::{POWERS_10, U32_MASK}, decimal::{CalculationResult, Decimal}, ops::array::{ add_by_internal, cmp_internal, div_by_u32, is_all_zero, mul_by_u32, mul_part, rescale_internal, shl1_internal, @@ -171,16 +171,16 @@ pub(crate) fn div_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { // Check for underflow let mut final_scale: u32 = quotient_scale as u32; - if final_scale > MAX_PRECISION_U32 { + if final_scale > Decimal::MAX_SCALE { let mut remainder = 0; // Division underflowed. We must remove some significant digits over using // an invalid scale. - while final_scale > MAX_PRECISION_U32 && !is_all_zero("ient) { + while final_scale > Decimal::MAX_SCALE && !is_all_zero("ient) { remainder = div_by_u32(&mut quotient, 10); final_scale -= 1; } - if final_scale > MAX_PRECISION_U32 { + if final_scale > Decimal::MAX_SCALE { // Result underflowed so set to zero final_scale = 0; quotient_negative = false; @@ -228,8 +228,8 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { let mut u64_result = u64_to_array(u64::from(my[0]) * u64::from(ot[0])); // If we're above max precision then this is a very small number - if final_scale > MAX_PRECISION_U32 { - final_scale -= MAX_PRECISION_U32; + if final_scale > Decimal::MAX_SCALE { + final_scale -= Decimal::MAX_SCALE; // If the number is above 19 then this will equate to zero. // This is because the max value in 64 bits is 1.84E19 @@ -258,7 +258,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { u64_result[0] += 1; } - final_scale = MAX_PRECISION_U32; + final_scale = Decimal::MAX_SCALE; } return CalculationResult::Ok(Decimal::from_parts( u64_result[0], @@ -350,17 +350,17 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { // If we're still above max precision then we'll try again to // reduce precision - we may be dealing with a limit of "0" - if final_scale > MAX_PRECISION_U32 { + if final_scale > Decimal::MAX_SCALE { // We're in an underflow situation // The easiest way to remove precision is to divide off the result - while final_scale > MAX_PRECISION_U32 && !is_all_zero(&product) { + while final_scale > Decimal::MAX_SCALE && !is_all_zero(&product) { div_by_u32(&mut product, 10); final_scale -= 1; } // If we're still at limit then we can't represent any // significant decimal digits and will return an integer only // Can also be invoked while representing 0. - if final_scale > MAX_PRECISION_U32 { + if final_scale > Decimal::MAX_SCALE { final_scale = 0; } } else if !(product[3] == 0 && product[4] == 0 && product[5] == 0) { diff --git a/src/ops/mul.rs b/src/ops/mul.rs index b367295..b0fe32a 100644 --- a/src/ops/mul.rs +++ b/src/ops/mul.rs @@ -1,4 +1,4 @@ -use crate::constants::{BIG_POWERS_10, MAX_I64_SCALE, MAX_PRECISION_U32, U32_MAX}; +use crate::constants::{BIG_POWERS_10, MAX_I64_SCALE, U32_MAX}; use crate::decimal::{CalculationResult, Decimal}; use crate::ops::common::Buf24; @@ -18,15 +18,15 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { if d2.hi() | d2.mid() == 0 { // We're multiplying two 32 bit integers, so we can take some liberties to optimize this. let mut low64 = d1.lo() as u64 * d2.lo() as u64; - if scale > MAX_PRECISION_U32 { + if scale > Decimal::MAX_SCALE { // We've exceeded maximum scale so we need to start reducing the precision (aka // rounding) until we have something that fits. // If we're too big then we effectively round to zero. - if scale > MAX_PRECISION_U32 + MAX_I64_SCALE { + if scale > Decimal::MAX_SCALE + MAX_I64_SCALE { return CalculationResult::Ok(Decimal::ZERO); } - scale -= MAX_PRECISION_U32 + 1; + scale -= Decimal::MAX_SCALE + 1; let mut power = BIG_POWERS_10[scale as usize]; let tmp = low64 / power; @@ -39,7 +39,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { low64 += 1; } - scale = MAX_PRECISION_U32; + scale = Decimal::MAX_SCALE; } // Early exit @@ -129,7 +129,7 @@ pub(crate) fn mul_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { // We may want to "rescale". This is the case if the mantissa is > 96 bits or if the scale // exceeds the maximum precision. let upper_word = product.upper_word(); - if upper_word > 2 || scale > MAX_PRECISION_U32 { + if upper_word > 2 || scale > Decimal::MAX_SCALE { scale = if let Some(new_scale) = product.rescale(upper_word, scale) { new_scale } else { diff --git a/src/ops/rem.rs b/src/ops/rem.rs index a79334e..fddd873 100644 --- a/src/ops/rem.rs +++ b/src/ops/rem.rs @@ -1,4 +1,4 @@ -use crate::constants::{MAX_I32_SCALE, MAX_PRECISION_I32, POWERS_10}; +use crate::constants::{MAX_I32_SCALE, MAX_SCALE_I32, POWERS_10}; use crate::decimal::{CalculationResult, Decimal}; use crate::ops::common::{Buf12, Buf16, Buf24, Dec64}; @@ -74,7 +74,7 @@ pub(crate) fn rem_impl(d1: &Decimal, d2: &Decimal) -> CalculationResult { loop { // Figure out how much we can scale by let power_scale; - if let Some(u) = quotient.find_scale(MAX_PRECISION_I32 + scale) { + if let Some(u) = quotient.find_scale(MAX_SCALE_I32 + scale) { if u >= POWERS_10.len() { power_scale = 9; } else { diff --git a/src/postgres/common.rs b/src/postgres/common.rs index e0fd9d9..0f2dea2 100644 --- a/src/postgres/common.rs +++ b/src/postgres/common.rs @@ -1,4 +1,3 @@ -use crate::constants::MAX_PRECISION_U32; use crate::{ ops::array::{div_by_u32, is_all_zero, mul_by_u32}, Decimal, @@ -44,7 +43,7 @@ impl Decimal { let fractionals_part_count = digits.len() as i32 + (-weight as i32) - 1; let integers_part_count = weight as i32 + 1; - let mut result = Decimal::ZERO; + let mut result = Self::ZERO; // adding integer part if integers_part_count > 0 { let (start_integers, last) = if integers_part_count > digits.len() as i32 { @@ -54,25 +53,25 @@ impl Decimal { }; let integers: Vec<_> = digits.drain(..last as usize).collect(); for digit in integers { - result = result.checked_mul(Decimal::from_i128_with_scale(10i128.pow(4), 0))?; - result = result.checked_add(Decimal::new(digit as i64, 0))?; + result = result.checked_mul(Self::from_i128_with_scale(10i128.pow(4), 0))?; + result = result.checked_add(Self::new(digit as i64, 0))?; } - result = result.checked_mul(Decimal::from_i128_with_scale(10i128.pow(4 * start_integers as u32), 0))?; + result = result.checked_mul(Self::from_i128_with_scale(10i128.pow(4 * start_integers as u32), 0))?; } // adding fractional part if fractionals_part_count > 0 { let start_fractionals = if weight < 0 { (-weight as u32) - 1 } else { 0 }; for (i, digit) in digits.into_iter().enumerate() { let fract_pow = 4_u32.checked_mul(i as u32 + 1 + start_fractionals)?; - if fract_pow <= MAX_PRECISION_U32 { + if fract_pow <= Self::MAX_SCALE { result = result.checked_add( - Decimal::new(digit as i64, 0) / Decimal::from_i128_with_scale(10i128.pow(fract_pow), 0), + Self::new(digit as i64, 0) / Self::from_i128_with_scale(10i128.pow(fract_pow), 0), )?; - } else if fract_pow == MAX_PRECISION_U32 + 4 { + } else if fract_pow == Self::MAX_SCALE + 4 { // rounding last digit if digit >= 5000 { result = result.checked_add( - Decimal::new(1_i64, 0) / Decimal::from_i128_with_scale(10i128.pow(MAX_PRECISION_U32), 0), + Self::new(1_i64, 0) / Self::from_i128_with_scale(10i128.pow(Self::MAX_SCALE), 0), )?; } } @@ -81,7 +80,7 @@ impl Decimal { result.set_sign_negative(neg); // Rescale to the postgres value, automatically rounding as needed. - result.rescale((scale as u32).min(MAX_PRECISION_U32)); + result.rescale((scale as u32).min(Self::MAX_SCALE)); Some(result) } diff --git a/src/rand.rs b/src/rand.rs index 991c60d..bf7eb5e 100644 --- a/src/rand.rs +++ b/src/rand.rs @@ -17,7 +17,7 @@ impl Distribution for Standard { rng.next_u32(), rng.next_u32(), rng.gen(), - rng.next_u32(), + rng.gen_range(0..=Decimal::MAX_SCALE), ) } } diff --git a/src/str.rs b/src/str.rs index b381b2a..97ce733 100644 --- a/src/str.rs +++ b/src/str.rs @@ -1,5 +1,5 @@ use crate::{ - constants::{BYTES_TO_OVERFLOW_U64, MAX_PRECISION, MAX_STR_BUFFER_SIZE, OVERFLOW_U96, WILL_OVERFLOW_U64}, + constants::{BYTES_TO_OVERFLOW_U64, MAX_SCALE, MAX_STR_BUFFER_SIZE, OVERFLOW_U96, WILL_OVERFLOW_U64}, error::{tail_error, Error}, ops::array::{add_by_internal_flattened, add_one_internal, div_by_u32, is_all_zero, mul_by_u32}, Decimal, @@ -32,7 +32,7 @@ pub(crate) fn to_str_internal( let (prec, additional) = match precision { Some(prec) => { - let max: usize = MAX_PRECISION.into(); + let max: usize = MAX_SCALE.into(); if prec > max { (max, Some(prec - max)) } else { diff --git a/tests/decimal_tests.rs b/tests/decimal_tests.rs index a22e09b..da289b0 100644 --- a/tests/decimal_tests.rs +++ b/tests/decimal_tests.rs @@ -4802,7 +4802,7 @@ mod issues { // 288230376151711744 let a = Decimal::from_parts(0, 67108864, 0, false, 0); // 714606955844629274884780.85120 - let b = Decimal::from_parts(0, 0, 3873892070, false, 3873892070); + let b = Decimal::from_parts(0, 0, 3873892070, false, 5); let c = a.checked_sub(b); assert!(c.is_some());