use crate::constants::{ MAX_I128_REPR, MAX_PRECISION_U32, POWERS_10, SCALE_MASK, SCALE_SHIFT, SIGN_MASK, SIGN_SHIFT, U32_MASK, U8_MASK, UNSIGN_MASK, }; use crate::ops; use crate::Error; use core::{ cmp::{Ordering::Equal, *}, fmt, hash::{Hash, Hasher}, iter::{Product, Sum}, ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign}, str::FromStr, }; // Diesel configuration #[cfg(feature = "diesel2")] use diesel::deserialize::FromSqlRow; #[cfg(feature = "diesel2")] use diesel::expression::AsExpression; #[cfg(any(feature = "diesel1", feature = "diesel2"))] use diesel::sql_types::Numeric; #[allow(unused_imports)] // It's not actually dead code below, but the compiler thinks it is. #[cfg(not(feature = "std"))] use num_traits::float::FloatCore; use num_traits::{FromPrimitive, Num, One, Signed, ToPrimitive, Zero}; #[cfg(feature = "rkyv")] use rkyv::{Archive, Deserialize, Serialize}; /// The smallest value that can be represented by this decimal type. const MIN: Decimal = Decimal { flags: 2_147_483_648, lo: 4_294_967_295, mid: 4_294_967_295, hi: 4_294_967_295, }; /// The largest value that can be represented by this decimal type. const MAX: Decimal = Decimal { flags: 0, lo: 4_294_967_295, mid: 4_294_967_295, hi: 4_294_967_295, }; const ZERO: Decimal = Decimal { flags: 0, lo: 0, mid: 0, hi: 0, }; const ONE: Decimal = Decimal { flags: 0, lo: 1, mid: 0, hi: 0, }; const TWO: Decimal = Decimal { flags: 0, lo: 2, mid: 0, hi: 0, }; const TEN: Decimal = Decimal { flags: 0, lo: 10, mid: 0, hi: 0, }; const ONE_HUNDRED: Decimal = Decimal { flags: 0, lo: 100, mid: 0, hi: 0, }; const ONE_THOUSAND: Decimal = Decimal { flags: 0, lo: 1000, mid: 0, hi: 0, }; const NEGATIVE_ONE: Decimal = Decimal { flags: 2147483648, lo: 1, mid: 0, hi: 0, }; /// `UnpackedDecimal` contains unpacked representation of `Decimal` where each component /// of decimal-format stored in it's own field #[derive(Clone, Copy, Debug, PartialEq)] pub struct UnpackedDecimal { pub negative: bool, pub scale: u32, pub hi: u32, pub mid: u32, pub lo: u32, } /// `Decimal` represents a 128 bit representation of a fixed-precision decimal number. /// The finite set of values of type `Decimal` are of the form m / 10e, /// where m is an integer such that -296 < m < 296, and e is an integer /// between 0 and 28 inclusive. #[derive(Clone, Copy)] #[cfg_attr( all(feature = "diesel1", not(feature = "diesel2")), derive(FromSqlRow, AsExpression), sql_type = "Numeric" )] #[cfg_attr(feature = "diesel2", derive(FromSqlRow, AsExpression), diesel(sql_type = Numeric))] #[cfg_attr(feature = "c-repr", repr(C))] #[cfg_attr( feature = "borsh", derive(borsh::BorshDeserialize, borsh::BorshSerialize, borsh::BorshSchema) )] #[cfg_attr( feature = "rkyv", derive(Archive, Deserialize, Serialize), archive(compare(PartialEq)), archive_attr(derive(Clone, Copy, Debug)) )] #[cfg_attr(feature = "rkyv-safe", archive_attr(derive(bytecheck::CheckBytes)))] pub struct Decimal { // Bits 0-15: unused // Bits 16-23: Contains "e", a value between 0-28 that indicates the scale // Bits 24-30: unused // Bit 31: the sign of the Decimal value, 0 meaning positive and 1 meaning negative. flags: u32, // The lo, mid, hi, and flags fields contain the representation of the // Decimal value as a 96-bit integer. hi: u32, lo: u32, mid: u32, } /// `RoundingStrategy` represents the different rounding strategies that can be used by /// `round_dp_with_strategy`. #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum RoundingStrategy { /// When a number is halfway between two others, it is rounded toward the nearest even number. /// Also known as "Bankers Rounding". /// e.g. /// 6.5 -> 6, 7.5 -> 8 MidpointNearestEven, /// When a number is halfway between two others, it is rounded toward the nearest number that /// is away from zero. e.g. 6.4 -> 6, 6.5 -> 7, -6.5 -> -7 MidpointAwayFromZero, /// When a number is halfway between two others, it is rounded toward the nearest number that /// is toward zero. e.g. 6.4 -> 6, 6.5 -> 6, -6.5 -> -6 MidpointTowardZero, /// The number is always rounded toward zero. e.g. -6.8 -> -6, 6.8 -> 6 ToZero, /// The number is always rounded away from zero. e.g. -6.8 -> -7, 6.8 -> 7 AwayFromZero, /// The number is always rounded towards negative infinity. e.g. 6.8 -> 6, -6.8 -> -7 ToNegativeInfinity, /// The number is always rounded towards positive infinity. e.g. 6.8 -> 7, -6.8 -> -6 ToPositiveInfinity, /// When a number is halfway between two others, it is rounded toward the nearest even number. /// e.g. /// 6.5 -> 6, 7.5 -> 8 #[deprecated(since = "1.11.0", note = "Please use RoundingStrategy::MidpointNearestEven instead")] BankersRounding, /// Rounds up if the value >= 5, otherwise rounds down, e.g. 6.5 -> 7 #[deprecated(since = "1.11.0", note = "Please use RoundingStrategy::MidpointAwayFromZero instead")] RoundHalfUp, /// Rounds down if the value =< 5, otherwise rounds up, e.g. 6.5 -> 6, 6.51 -> 7 1.4999999 -> 1 #[deprecated(since = "1.11.0", note = "Please use RoundingStrategy::MidpointTowardZero instead")] RoundHalfDown, /// Always round down. #[deprecated(since = "1.11.0", note = "Please use RoundingStrategy::ToZero instead")] RoundDown, /// Always round up. #[deprecated(since = "1.11.0", note = "Please use RoundingStrategy::AwayFromZero instead")] RoundUp, } #[allow(dead_code)] impl Decimal { /// The smallest value that can be represented by this decimal type. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::MIN, dec!(-79_228_162_514_264_337_593_543_950_335)); /// ``` pub const MIN: Decimal = MIN; /// The largest value that can be represented by this decimal type. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::MAX, dec!(79_228_162_514_264_337_593_543_950_335)); /// ``` pub const MAX: Decimal = MAX; /// A constant representing 0. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::ZERO, dec!(0)); /// ``` pub const ZERO: Decimal = ZERO; /// A constant representing 1. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::ONE, dec!(1)); /// ``` pub const ONE: Decimal = ONE; /// A constant representing -1. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::NEGATIVE_ONE, dec!(-1)); /// ``` pub const NEGATIVE_ONE: Decimal = NEGATIVE_ONE; /// A constant representing 2. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::TWO, dec!(2)); /// ``` pub const TWO: Decimal = TWO; /// A constant representing 10. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::TEN, dec!(10)); /// ``` pub const TEN: Decimal = TEN; /// A constant representing 100. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::ONE_HUNDRED, dec!(100)); /// ``` pub const ONE_HUNDRED: Decimal = ONE_HUNDRED; /// A constant representing 1000. /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::ONE_THOUSAND, dec!(1000)); /// ``` pub const ONE_THOUSAND: Decimal = ONE_THOUSAND; /// A constant representing π as 3.1415926535897932384626433833 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::PI, dec!(3.1415926535897932384626433833)); /// ``` #[cfg(feature = "maths")] pub const PI: Decimal = Decimal { flags: 1835008, lo: 1102470953, mid: 185874565, hi: 1703060790, }; /// A constant representing π/2 as 1.5707963267948966192313216916 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::HALF_PI, dec!(1.5707963267948966192313216916)); /// ``` #[cfg(feature = "maths")] pub const HALF_PI: Decimal = Decimal { flags: 1835008, lo: 2698719124, mid: 92937282, hi: 851530395, }; /// A constant representing π/4 as 0.7853981633974483096156608458 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::QUARTER_PI, dec!(0.7853981633974483096156608458)); /// ``` #[cfg(feature = "maths")] pub const QUARTER_PI: Decimal = Decimal { flags: 1835008, lo: 1349359562, mid: 2193952289, hi: 425765197, }; /// A constant representing 2π as 6.2831853071795864769252867666 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::TWO_PI, dec!(6.2831853071795864769252867666)); /// ``` #[cfg(feature = "maths")] pub const TWO_PI: Decimal = Decimal { flags: 1835008, lo: 2204941906, mid: 371749130, hi: 3406121580, }; /// A constant representing Euler's number (e) as 2.7182818284590452353602874714 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::E, dec!(2.7182818284590452353602874714)); /// ``` #[cfg(feature = "maths")] pub const E: Decimal = Decimal { flags: 1835008, lo: 2239425882, mid: 3958169141, hi: 1473583531, }; /// A constant representing the inverse of Euler's number (1/e) as 0.3678794411714423215955237702 /// /// # Examples /// /// Basic usage: /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// assert_eq!(Decimal::E_INVERSE, dec!(0.3678794411714423215955237702)); /// ``` #[cfg(feature = "maths")] pub const E_INVERSE: Decimal = Decimal { flags: 1835008, lo: 2384059206, mid: 2857938002, hi: 199427844, }; /// Returns a `Decimal` with a 64 bit `m` representation and corresponding `e` scale. /// /// # Arguments /// /// * `num` - An i64 that represents the `m` portion of the decimal number /// * `scale` - A u32 representing the `e` portion of the decimal number. /// /// # Panics /// /// This function panics if `scale` is > 28. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let pi = Decimal::new(3141, 3); /// assert_eq!(pi.to_string(), "3.141"); /// ``` #[must_use] pub fn new(num: i64, scale: u32) -> Decimal { match Self::try_new(num, scale) { Err(e) => panic!("{}", e), Ok(d) => d, } } /// Checked version of `Decimal::new`. Will return `Err` instead of panicking at run-time. /// /// # Example /// /// ```rust /// # use rust_decimal::Decimal; /// # /// let max = Decimal::try_new(i64::MAX, u32::MAX); /// assert!(max.is_err()); /// ``` pub const fn try_new(num: i64, scale: u32) -> crate::Result { if scale > MAX_PRECISION_U32 { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } let flags: u32 = scale << SCALE_SHIFT; if num < 0 { let pos_num = num.wrapping_neg() as u64; return Ok(Decimal { flags: flags | SIGN_MASK, hi: 0, lo: (pos_num & U32_MASK) as u32, mid: ((pos_num >> 32) & U32_MASK) as u32, }); } Ok(Decimal { flags, hi: 0, lo: (num as u64 & U32_MASK) as u32, mid: ((num as u64 >> 32) & U32_MASK) as u32, }) } /// Creates a `Decimal` using a 128 bit signed `m` representation and corresponding `e` scale. /// /// # Arguments /// /// * `num` - An i128 that represents the `m` portion of the decimal number /// * `scale` - A u32 representing the `e` portion of the decimal number. /// /// # Panics /// /// This function panics if `scale` is > 28 or if `num` exceeds the maximum supported 96 bits. /// /// # Example /// /// ```rust /// # use rust_decimal::Decimal; /// # /// let pi = Decimal::from_i128_with_scale(3141i128, 3); /// assert_eq!(pi.to_string(), "3.141"); /// ``` #[must_use] pub fn from_i128_with_scale(num: i128, scale: u32) -> Decimal { match Self::try_from_i128_with_scale(num, scale) { Ok(d) => d, Err(e) => panic!("{}", e), } } /// Checked version of `Decimal::from_i128_with_scale`. Will return `Err` instead /// of panicking at run-time. /// /// # Example /// /// ```rust /// # use rust_decimal::Decimal; /// # /// let max = Decimal::try_from_i128_with_scale(i128::MAX, u32::MAX); /// assert!(max.is_err()); /// ``` pub const fn try_from_i128_with_scale(num: i128, scale: u32) -> crate::Result { if scale > MAX_PRECISION_U32 { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } let mut neg = false; let mut wrapped = num; if num > MAX_I128_REPR { return Err(Error::ExceedsMaximumPossibleValue); } else if num < -MAX_I128_REPR { return Err(Error::LessThanMinimumPossibleValue); } else if num < 0 { neg = true; wrapped = -num; } let flags: u32 = flags(neg, scale); Ok(Decimal { flags, lo: (wrapped as u64 & U32_MASK) as u32, mid: ((wrapped as u64 >> 32) & U32_MASK) as u32, hi: ((wrapped as u128 >> 64) as u64 & U32_MASK) as u32, }) } /// Returns a `Decimal` using the instances constituent parts. /// /// # Arguments /// /// * `lo` - The low 32 bits of a 96-bit integer. /// * `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. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let pi = Decimal::from_parts(1102470952, 185874565, 1703060790, false, 28); /// assert_eq!(pi.to_string(), "3.1415926535897932384626433832"); /// ``` #[must_use] pub const fn from_parts(lo: u32, mid: u32, hi: u32, negative: bool, scale: u32) -> Decimal { Decimal { lo, mid, hi, flags: flags( if lo == 0 && mid == 0 && hi == 0 { false } else { negative }, scale % (MAX_PRECISION_U32 + 1), ), } } #[must_use] pub(crate) const fn from_parts_raw(lo: u32, mid: u32, hi: u32, flags: u32) -> Decimal { if lo == 0 && mid == 0 && hi == 0 { Decimal { lo, mid, hi, flags: flags & SCALE_MASK, } } else { Decimal { flags, hi, lo, mid } } } /// Returns a `Result` which if successful contains the `Decimal` constitution of /// the scientific notation provided by `value`. /// /// # Arguments /// /// * `value` - The scientific notation of the `Decimal`. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// # fn main() -> Result<(), rust_decimal::Error> { /// let value = Decimal::from_scientific("9.7e-7")?; /// assert_eq!(value.to_string(), "0.00000097"); /// # Ok(()) /// # } /// ``` pub fn from_scientific(value: &str) -> Result { const ERROR_MESSAGE: &str = "Failed to parse"; let mut split = value.splitn(2, |c| c == 'e' || c == 'E'); let base = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?; let exp = split.next().ok_or_else(|| Error::from(ERROR_MESSAGE))?; let mut ret = Decimal::from_str(base)?; let current_scale = ret.scale(); if let Some(stripped) = exp.strip_prefix('-') { let exp: u32 = stripped.parse().map_err(|_| Error::from(ERROR_MESSAGE))?; ret.set_scale(current_scale + exp)?; } else { let exp: u32 = exp.parse().map_err(|_| Error::from(ERROR_MESSAGE))?; if exp <= current_scale { ret.set_scale(current_scale - exp)?; } else if exp > 0 { use crate::constants::BIG_POWERS_10; // This is a case whereby the mantissa needs to be larger to be correctly // represented within the decimal type. A good example is 1.2E10. At this point, // 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 { return Err(Error::ScaleExceedsMaximumPrecision(exp)); } let mut exp = exp as usize; // Max two iterations. If exp is 1 then it needs to index position 0 of the array. while exp > 0 { let pow; if exp >= BIG_POWERS_10.len() { pow = BIG_POWERS_10[BIG_POWERS_10.len() - 1]; exp -= BIG_POWERS_10.len(); } else { pow = BIG_POWERS_10[exp - 1]; exp = 0; } let pow = Decimal { flags: 0, lo: pow as u32, mid: (pow >> 32) as u32, hi: 0, }; match ret.checked_mul(pow) { Some(r) => ret = r, None => return Err(Error::ExceedsMaximumPossibleValue), }; } ret.normalize_assign(); } } Ok(ret) } /// Converts a string slice in a given base to a decimal. /// /// The string is expected to be an optional + sign followed by digits. /// Digits are a subset of these characters, depending on radix, and will return an error if outside /// the expected range: /// /// * 0-9 /// * a-z /// * A-Z /// /// # Examples /// /// Basic usage: /// /// ``` /// # use rust_decimal::prelude::*; /// # /// # fn main() -> Result<(), rust_decimal::Error> { /// assert_eq!(Decimal::from_str_radix("A", 16)?.to_string(), "10"); /// # Ok(()) /// # } /// ``` pub fn from_str_radix(str: &str, radix: u32) -> Result { if radix == 10 { crate::str::parse_str_radix_10(str) } else { crate::str::parse_str_radix_n(str, radix) } } /// Parses a string slice into a decimal. If the value underflows and cannot be represented with the /// given scale then this will return an error. /// /// # Examples /// /// Basic usage: /// /// ``` /// # use rust_decimal::prelude::*; /// # use rust_decimal::Error; /// # /// # fn main() -> Result<(), rust_decimal::Error> { /// assert_eq!(Decimal::from_str_exact("0.001")?.to_string(), "0.001"); /// assert_eq!(Decimal::from_str_exact("0.00000_00000_00000_00000_00000_001")?.to_string(), "0.0000000000000000000000000001"); /// assert_eq!(Decimal::from_str_exact("0.00000_00000_00000_00000_00000_0001"), Err(Error::Underflow)); /// # Ok(()) /// # } /// ``` pub fn from_str_exact(str: &str) -> Result { crate::str::parse_str_radix_10_exact(str) } /// Returns the scale of the decimal number, otherwise known as `e`. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let num = Decimal::new(1234, 3); /// assert_eq!(num.scale(), 3u32); /// ``` #[inline] #[must_use] pub const fn scale(&self) -> u32 { ((self.flags & SCALE_MASK) >> SCALE_SHIFT) as u32 } /// Returns the mantissa of the decimal number. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// use rust_decimal_macros::dec; /// /// let num = dec!(-1.2345678); /// assert_eq!(num.mantissa(), -12345678i128); /// assert_eq!(num.scale(), 7); /// ``` #[must_use] pub const fn mantissa(&self) -> i128 { let raw = (self.lo as i128) | ((self.mid as i128) << 32) | ((self.hi as i128) << 64); if self.is_sign_negative() { -raw } else { raw } } /// Returns true if this Decimal number is equivalent to zero. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// # /// let num = Decimal::ZERO; /// assert!(num.is_zero()); /// ``` #[must_use] pub const fn is_zero(&self) -> bool { self.lo == 0 && self.mid == 0 && self.hi == 0 } /// An optimized method for changing the sign of a decimal number. /// /// # Arguments /// /// * `positive`: true if the resulting decimal should be positive. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let mut one = Decimal::ONE; /// one.set_sign(false); /// assert_eq!(one.to_string(), "-1"); /// ``` #[deprecated(since = "1.4.0", note = "please use `set_sign_positive` instead")] pub fn set_sign(&mut self, positive: bool) { self.set_sign_positive(positive); } /// An optimized method for changing the sign of a decimal number. /// /// # Arguments /// /// * `positive`: true if the resulting decimal should be positive. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let mut one = Decimal::ONE; /// one.set_sign_positive(false); /// assert_eq!(one.to_string(), "-1"); /// ``` #[inline(always)] pub fn set_sign_positive(&mut self, positive: bool) { if positive { self.flags &= UNSIGN_MASK; } else { self.flags |= SIGN_MASK; } } /// An optimized method for changing the sign of a decimal number. /// /// # Arguments /// /// * `negative`: true if the resulting decimal should be negative. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let mut one = Decimal::ONE; /// one.set_sign_negative(true); /// assert_eq!(one.to_string(), "-1"); /// ``` #[inline(always)] pub fn set_sign_negative(&mut self, negative: bool) { self.set_sign_positive(!negative); } /// An optimized method for changing the scale of a decimal number. /// /// # Arguments /// /// * `scale`: the new scale of the number /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// # fn main() -> Result<(), rust_decimal::Error> { /// let mut one = Decimal::ONE; /// one.set_scale(5)?; /// assert_eq!(one.to_string(), "0.00001"); /// # Ok(()) /// # } /// ``` pub fn set_scale(&mut self, scale: u32) -> Result<(), Error> { if scale > MAX_PRECISION_U32 { return Err(Error::ScaleExceedsMaximumPrecision(scale)); } self.flags = (scale << SCALE_SHIFT) | (self.flags & SIGN_MASK); Ok(()) } /// Modifies the `Decimal` towards the desired scale, attempting to do so without changing the /// underlying number itself. /// /// Setting the scale to something less then the current `Decimal`s scale will /// 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 /// be represented with the given mantissa. /// /// # Arguments /// * `scale`: The desired scale to use for the new `Decimal` number. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// use rust_decimal_macros::dec; /// /// // Rescaling to a higher scale preserves the value /// let mut number = dec!(1.123); /// assert_eq!(number.scale(), 3); /// number.rescale(6); /// assert_eq!(number.to_string(), "1.123000"); /// assert_eq!(number.scale(), 6); /// /// // Rescaling to a lower scale forces the number to be rounded /// let mut number = dec!(1.45); /// assert_eq!(number.scale(), 2); /// number.rescale(1); /// assert_eq!(number.to_string(), "1.5"); /// assert_eq!(number.scale(), 1); /// /// // This function never fails. Consequently, if a scale is provided that is unable to be /// // represented using the given mantissa, then the maximum possible scale is used. /// let mut number = dec!(11.76470588235294); /// assert_eq!(number.scale(), 14); /// number.rescale(28); /// // A scale of 28 cannot be represented given this mantissa, however it was able to represent /// // a number with a scale of 27 /// assert_eq!(number.to_string(), "11.764705882352940000000000000"); /// assert_eq!(number.scale(), 27); /// ``` pub fn rescale(&mut self, scale: u32) { let mut array = [self.lo, self.mid, self.hi]; let mut value_scale = self.scale(); ops::array::rescale_internal(&mut array, &mut value_scale, scale); self.lo = array[0]; self.mid = array[1]; self.hi = array[2]; self.flags = flags(self.is_sign_negative(), value_scale); } /// Returns a serialized version of the decimal number. /// The resulting byte array will have the following representation: /// /// * Bytes 1-4: flags /// * Bytes 5-8: lo portion of `m` /// * Bytes 9-12: mid portion of `m` /// * Bytes 13-16: high portion of `m` #[must_use] pub const fn serialize(&self) -> [u8; 16] { [ (self.flags & U8_MASK) as u8, ((self.flags >> 8) & U8_MASK) as u8, ((self.flags >> 16) & U8_MASK) as u8, ((self.flags >> 24) & U8_MASK) as u8, (self.lo & U8_MASK) as u8, ((self.lo >> 8) & U8_MASK) as u8, ((self.lo >> 16) & U8_MASK) as u8, ((self.lo >> 24) & U8_MASK) as u8, (self.mid & U8_MASK) as u8, ((self.mid >> 8) & U8_MASK) as u8, ((self.mid >> 16) & U8_MASK) as u8, ((self.mid >> 24) & U8_MASK) as u8, (self.hi & U8_MASK) as u8, ((self.hi >> 8) & U8_MASK) as u8, ((self.hi >> 16) & U8_MASK) as u8, ((self.hi >> 24) & U8_MASK) as u8, ] } /// Deserializes the given bytes into a decimal number. /// The deserialized byte representation must be 16 bytes and adhere to the following convention: /// /// * Bytes 1-4: flags /// * Bytes 5-8: lo portion of `m` /// * Bytes 9-12: mid portion of `m` /// * Bytes 13-16: high portion of `m` #[must_use] pub fn deserialize(bytes: [u8; 16]) -> Decimal { // We can bound flags by a bitwise mask to correspond to: // Bits 0-15: unused // Bits 16-23: Contains "e", a value between 0-28 that indicates the scale // Bits 24-30: unused // Bit 31: the sign of the Decimal value, 0 meaning positive and 1 meaning negative. let mut raw = Decimal { flags: ((bytes[0] as u32) | (bytes[1] as u32) << 8 | (bytes[2] as u32) << 16 | (bytes[3] as u32) << 24) & 0x801F_0000, lo: (bytes[4] as u32) | (bytes[5] as u32) << 8 | (bytes[6] as u32) << 16 | (bytes[7] as u32) << 24, mid: (bytes[8] as u32) | (bytes[9] as u32) << 8 | (bytes[10] as u32) << 16 | (bytes[11] as u32) << 24, 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 { let mut bits = raw.mantissa_array3(); let remainder = match raw.scale() { 29 => crate::ops::array::div_by_1x(&mut bits, 1), 30 => crate::ops::array::div_by_1x(&mut bits, 2), 31 => crate::ops::array::div_by_1x(&mut bits, 3), _ => 0, }; if remainder >= 5 { ops::array::add_one_internal(&mut bits); } raw.lo = bits[0]; raw.mid = bits[1]; raw.hi = bits[2]; raw.flags = flags(raw.is_sign_negative(), MAX_PRECISION_U32); } raw } /// Returns `true` if the decimal is negative. #[deprecated(since = "0.6.3", note = "please use `is_sign_negative` instead")] #[must_use] pub fn is_negative(&self) -> bool { self.is_sign_negative() } /// Returns `true` if the decimal is positive. #[deprecated(since = "0.6.3", note = "please use `is_sign_positive` instead")] #[must_use] pub fn is_positive(&self) -> bool { self.is_sign_positive() } /// Returns `true` if the sign bit of the decimal is negative. /// /// # Example /// ``` /// # use rust_decimal::prelude::*; /// # /// assert_eq!(true, Decimal::new(-1, 0).is_sign_negative()); /// assert_eq!(false, Decimal::new(1, 0).is_sign_negative()); /// ``` #[inline(always)] #[must_use] pub const fn is_sign_negative(&self) -> bool { self.flags & SIGN_MASK > 0 } /// Returns `true` if the sign bit of the decimal is positive. /// /// # Example /// ``` /// # use rust_decimal::prelude::*; /// # /// assert_eq!(false, Decimal::new(-1, 0).is_sign_positive()); /// assert_eq!(true, Decimal::new(1, 0).is_sign_positive()); /// ``` #[inline(always)] #[must_use] pub const fn is_sign_positive(&self) -> bool { self.flags & SIGN_MASK == 0 } /// Returns the minimum possible number that `Decimal` can represent. #[deprecated(since = "1.12.0", note = "Use the associated constant Decimal::MIN")] #[must_use] pub const fn min_value() -> Decimal { MIN } /// Returns the maximum possible number that `Decimal` can represent. #[deprecated(since = "1.12.0", note = "Use the associated constant Decimal::MAX")] #[must_use] pub const fn max_value() -> Decimal { MAX } /// Returns a new `Decimal` integral with no fractional portion. /// This is a true truncation whereby no rounding is performed. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let pi = Decimal::new(3141, 3); /// let trunc = Decimal::new(3, 0); /// // note that it returns a decimal /// assert_eq!(pi.trunc(), trunc); /// ``` #[must_use] pub fn trunc(&self) -> Decimal { let mut scale = self.scale(); if scale == 0 { // Nothing to do return *self; } let mut working = [self.lo, self.mid, self.hi]; while scale > 0 { // We're removing precision, so we don't care about overflow if scale < 10 { ops::array::div_by_u32(&mut working, POWERS_10[scale as usize]); break; } else { ops::array::div_by_u32(&mut working, POWERS_10[9]); // Only 9 as this array starts with 1 scale -= 9; } } Decimal { lo: working[0], mid: working[1], hi: working[2], flags: flags(self.is_sign_negative(), 0), } } /// Returns a new `Decimal` representing the fractional portion of the number. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let pi = Decimal::new(3141, 3); /// let fract = Decimal::new(141, 3); /// // note that it returns a decimal /// assert_eq!(pi.fract(), fract); /// ``` #[must_use] pub fn fract(&self) -> Decimal { // This is essentially the original number minus the integral. // Could possibly be optimized in the future *self - self.trunc() } /// Computes the absolute value of `self`. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let num = Decimal::new(-3141, 3); /// assert_eq!(num.abs().to_string(), "3.141"); /// ``` #[must_use] pub fn abs(&self) -> Decimal { let mut me = *self; me.set_sign_positive(true); me } /// Returns the largest integer less than or equal to a number. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let num = Decimal::new(3641, 3); /// assert_eq!(num.floor().to_string(), "3"); /// ``` #[must_use] pub fn floor(&self) -> Decimal { let scale = self.scale(); if scale == 0 { // Nothing to do return *self; } // Opportunity for optimization here let floored = self.trunc(); if self.is_sign_negative() && !self.fract().is_zero() { floored - ONE } else { floored } } /// Returns the smallest integer greater than or equal to a number. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// let num = Decimal::new(3141, 3); /// assert_eq!(num.ceil().to_string(), "4"); /// let num = Decimal::new(3, 0); /// assert_eq!(num.ceil().to_string(), "3"); /// ``` #[must_use] pub fn ceil(&self) -> Decimal { let scale = self.scale(); if scale == 0 { // Nothing to do return *self; } // Opportunity for optimization here if self.is_sign_positive() && !self.fract().is_zero() { self.trunc() + ONE } else { self.trunc() } } /// Returns the maximum of the two numbers. /// /// ``` /// # use rust_decimal::Decimal; /// # /// let x = Decimal::new(1, 0); /// let y = Decimal::new(2, 0); /// assert_eq!(y, x.max(y)); /// ``` #[must_use] pub fn max(self, other: Decimal) -> Decimal { if self < other { other } else { self } } /// Returns the minimum of the two numbers. /// /// ``` /// # use rust_decimal::Decimal; /// # /// let x = Decimal::new(1, 0); /// let y = Decimal::new(2, 0); /// assert_eq!(x, x.min(y)); /// ``` #[must_use] pub fn min(self, other: Decimal) -> Decimal { if self > other { other } else { self } } /// Strips any trailing zero's from a `Decimal` and converts -0 to 0. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// # fn main() -> Result<(), rust_decimal::Error> { /// let number = Decimal::from_str("3.100")?; /// assert_eq!(number.normalize().to_string(), "3.1"); /// # Ok(()) /// # } /// ``` #[must_use] pub fn normalize(&self) -> Decimal { let mut result = *self; result.normalize_assign(); result } /// An in place version of `normalize`. Strips any trailing zero's from a `Decimal` and converts -0 to 0. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// # fn main() -> Result<(), rust_decimal::Error> { /// let mut number = Decimal::from_str("3.100")?; /// assert_eq!(number.to_string(), "3.100"); /// number.normalize_assign(); /// assert_eq!(number.to_string(), "3.1"); /// # Ok(()) /// # } /// ``` pub fn normalize_assign(&mut self) { if self.is_zero() { self.flags = 0; return; } let mut scale = self.scale(); if scale == 0 { return; } let mut result = self.mantissa_array3(); let mut working = self.mantissa_array3(); while scale > 0 { if ops::array::div_by_u32(&mut working, 10) > 0 { break; } scale -= 1; result.copy_from_slice(&working); } self.lo = result[0]; self.mid = result[1]; self.hi = result[2]; self.flags = flags(self.is_sign_negative(), scale); } /// Returns a new `Decimal` number with no fractional portion (i.e. an integer). /// Rounding currently follows "Bankers Rounding" rules. e.g. 6.5 -> 6, 7.5 -> 8 /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # /// // Demonstrating bankers rounding... /// let number_down = Decimal::new(65, 1); /// let number_up = Decimal::new(75, 1); /// assert_eq!(number_down.round().to_string(), "6"); /// assert_eq!(number_up.round().to_string(), "8"); /// ``` #[must_use] pub fn round(&self) -> Decimal { self.round_dp(0) } /// Returns a new `Decimal` number with the specified number of decimal points for fractional /// portion. /// Rounding is performed using the provided [`RoundingStrategy`] /// /// # Arguments /// * `dp`: the number of decimal points to round to. /// * `strategy`: the [`RoundingStrategy`] to use. /// /// # Example /// /// ``` /// # use rust_decimal::{Decimal, RoundingStrategy}; /// # use rust_decimal_macros::dec; /// # /// let tax = dec!(3.4395); /// assert_eq!(tax.round_dp_with_strategy(2, RoundingStrategy::MidpointAwayFromZero).to_string(), "3.44"); /// ``` #[must_use] pub fn round_dp_with_strategy(&self, dp: u32, strategy: RoundingStrategy) -> Decimal { // Short circuit for zero if self.is_zero() { return Decimal { lo: 0, mid: 0, hi: 0, flags: flags(self.is_sign_negative(), dp), }; } let old_scale = self.scale(); // return early if decimal has a smaller number of fractional places than dp // e.g. 2.51 rounded to 3 decimal places is 2.51 if old_scale <= dp { return *self; } let mut value = [self.lo, self.mid, self.hi]; let mut value_scale = self.scale(); let negative = self.is_sign_negative(); value_scale -= dp; // Rescale to zero so it's easier to work with while value_scale > 0 { if value_scale < 10 { ops::array::div_by_u32(&mut value, POWERS_10[value_scale as usize]); value_scale = 0; } else { ops::array::div_by_u32(&mut value, POWERS_10[9]); value_scale -= 9; } } // Do some midpoint rounding checks // We're actually doing two things here. // 1. Figuring out midpoint rounding when we're right on the boundary. e.g. 2.50000 // 2. Figuring out whether to add one or not e.g. 2.51 // For this, we need to figure out the fractional portion that is additional to // the rounded number. e.g. for 0.12345 rounding to 2dp we'd want 345. // We're doing the equivalent of losing precision (e.g. to get 0.12) // then increasing the precision back up to 0.12000 let mut offset = [self.lo, self.mid, self.hi]; let mut diff = old_scale - dp; while diff > 0 { if diff < 10 { ops::array::div_by_u32(&mut offset, POWERS_10[diff as usize]); break; } else { ops::array::div_by_u32(&mut offset, POWERS_10[9]); // Only 9 as this array starts with 1 diff -= 9; } } let mut diff = old_scale - dp; while diff > 0 { if diff < 10 { ops::array::mul_by_u32(&mut offset, POWERS_10[diff as usize]); break; } else { ops::array::mul_by_u32(&mut offset, POWERS_10[9]); // Only 9 as this array starts with 1 diff -= 9; } } let mut decimal_portion = [self.lo, self.mid, self.hi]; ops::array::sub_by_internal(&mut decimal_portion, &offset); // If the decimal_portion is zero then we round based on the other data let mut cap = [5, 0, 0]; for _ in 0..(old_scale - dp - 1) { ops::array::mul_by_u32(&mut cap, 10); } let order = ops::array::cmp_internal(&decimal_portion, &cap); #[allow(deprecated)] match strategy { RoundingStrategy::BankersRounding | RoundingStrategy::MidpointNearestEven => { match order { Ordering::Equal => { if (value[0] & 1) == 1 { ops::array::add_one_internal(&mut value); } } Ordering::Greater => { // Doesn't matter about the decimal portion ops::array::add_one_internal(&mut value); } _ => {} } } RoundingStrategy::RoundHalfDown | RoundingStrategy::MidpointTowardZero => { if let Ordering::Greater = order { ops::array::add_one_internal(&mut value); } } RoundingStrategy::RoundHalfUp | RoundingStrategy::MidpointAwayFromZero => { // when Ordering::Equal, decimal_portion is 0.5 exactly // when Ordering::Greater, decimal_portion is > 0.5 match order { Ordering::Equal => { ops::array::add_one_internal(&mut value); } Ordering::Greater => { // Doesn't matter about the decimal portion ops::array::add_one_internal(&mut value); } _ => {} } } RoundingStrategy::RoundUp | RoundingStrategy::AwayFromZero => { if !ops::array::is_all_zero(&decimal_portion) { ops::array::add_one_internal(&mut value); } } RoundingStrategy::ToPositiveInfinity => { if !negative && !ops::array::is_all_zero(&decimal_portion) { ops::array::add_one_internal(&mut value); } } RoundingStrategy::ToNegativeInfinity => { if negative && !ops::array::is_all_zero(&decimal_portion) { ops::array::add_one_internal(&mut value); } } RoundingStrategy::RoundDown | RoundingStrategy::ToZero => (), } Decimal::from_parts(value[0], value[1], value[2], negative, dp) } /// Returns a new `Decimal` number with the specified number of decimal points for fractional portion. /// Rounding currently follows "Bankers Rounding" rules. e.g. 6.5 -> 6, 7.5 -> 8 /// /// # Arguments /// * `dp`: the number of decimal points to round to. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// # use rust_decimal_macros::dec; /// # /// let pi = dec!(3.1415926535897932384626433832); /// assert_eq!(pi.round_dp(2).to_string(), "3.14"); /// ``` #[must_use] pub fn round_dp(&self, dp: u32) -> Decimal { self.round_dp_with_strategy(dp, RoundingStrategy::MidpointNearestEven) } /// Returns `Some(Decimal)` number rounded to the specified number of significant digits. If /// the resulting number is unable to be represented by the `Decimal` number then `None` will /// be returned. /// When the number of significant figures of the `Decimal` being rounded is greater than the requested /// number of significant digits then rounding will be performed using `MidpointNearestEven` strategy. /// /// # Arguments /// * `digits`: the number of significant digits to round to. /// /// # Remarks /// A significant figure is determined using the following rules: /// 1. Non-zero digits are always significant. /// 2. Zeros between non-zero digits are always significant. /// 3. Leading zeros are never significant. /// 4. Trailing zeros are only significant if the number contains a decimal point. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// use rust_decimal_macros::dec; /// /// let value = dec!(305.459); /// assert_eq!(value.round_sf(0), Some(dec!(0))); /// assert_eq!(value.round_sf(1), Some(dec!(300))); /// assert_eq!(value.round_sf(2), Some(dec!(310))); /// assert_eq!(value.round_sf(3), Some(dec!(305))); /// assert_eq!(value.round_sf(4), Some(dec!(305.5))); /// assert_eq!(value.round_sf(5), Some(dec!(305.46))); /// assert_eq!(value.round_sf(6), Some(dec!(305.459))); /// assert_eq!(value.round_sf(7), Some(dec!(305.4590))); /// assert_eq!(Decimal::MAX.round_sf(1), None); /// /// let value = dec!(0.012301); /// assert_eq!(value.round_sf(3), Some(dec!(0.0123))); /// ``` #[must_use] pub fn round_sf(&self, digits: u32) -> Option { self.round_sf_with_strategy(digits, RoundingStrategy::MidpointNearestEven) } /// Returns `Some(Decimal)` number rounded to the specified number of significant digits. If /// the resulting number is unable to be represented by the `Decimal` number then `None` will /// be returned. /// When the number of significant figures of the `Decimal` being rounded is greater than the requested /// number of significant digits then rounding will be performed using the provided [RoundingStrategy]. /// /// # Arguments /// * `digits`: the number of significant digits to round to. /// * `strategy`: if required, the rounding strategy to use. /// /// # Remarks /// A significant figure is determined using the following rules: /// 1. Non-zero digits are always significant. /// 2. Zeros between non-zero digits are always significant. /// 3. Leading zeros are never significant. /// 4. Trailing zeros are only significant if the number contains a decimal point. /// /// # Example /// /// ``` /// # use rust_decimal::{Decimal, RoundingStrategy}; /// use rust_decimal_macros::dec; /// /// let value = dec!(305.459); /// assert_eq!(value.round_sf_with_strategy(0, RoundingStrategy::ToZero), Some(dec!(0))); /// assert_eq!(value.round_sf_with_strategy(1, RoundingStrategy::ToZero), Some(dec!(300))); /// assert_eq!(value.round_sf_with_strategy(2, RoundingStrategy::ToZero), Some(dec!(300))); /// assert_eq!(value.round_sf_with_strategy(3, RoundingStrategy::ToZero), Some(dec!(305))); /// assert_eq!(value.round_sf_with_strategy(4, RoundingStrategy::ToZero), Some(dec!(305.4))); /// assert_eq!(value.round_sf_with_strategy(5, RoundingStrategy::ToZero), Some(dec!(305.45))); /// assert_eq!(value.round_sf_with_strategy(6, RoundingStrategy::ToZero), Some(dec!(305.459))); /// assert_eq!(value.round_sf_with_strategy(7, RoundingStrategy::ToZero), Some(dec!(305.4590))); /// assert_eq!(Decimal::MAX.round_sf_with_strategy(1, RoundingStrategy::ToZero), Some(dec!(70000000000000000000000000000))); /// /// let value = dec!(0.012301); /// assert_eq!(value.round_sf_with_strategy(3, RoundingStrategy::AwayFromZero), Some(dec!(0.0124))); /// ``` #[must_use] pub fn round_sf_with_strategy(&self, digits: u32, strategy: RoundingStrategy) -> Option { if self.is_zero() || digits == 0 { return Some(Decimal::ZERO); } // We start by grabbing the mantissa and figuring out how many significant figures it is // made up of. We do this by just dividing by 10 and checking remainders - effectively // we're performing a naive log10. let mut working = self.mantissa_array3(); let mut mantissa_sf = 0; while !ops::array::is_all_zero(&working) { let _remainder = ops::array::div_by_u32(&mut working, 10u32); mantissa_sf += 1; if working[2] == 0 && working[1] == 0 && working[0] == 1 { mantissa_sf += 1; break; } } let scale = self.scale(); match digits.cmp(&mantissa_sf) { Ordering::Greater => { // If we're requesting a higher number of significant figures, we rescale let mut array = [self.lo, self.mid, self.hi]; let mut value_scale = scale; ops::array::rescale_internal(&mut array, &mut value_scale, scale + digits - mantissa_sf); Some(Decimal { lo: array[0], mid: array[1], hi: array[2], flags: flags(self.is_sign_negative(), value_scale), }) } Ordering::Less => { // We're requesting a lower number of significant digits. let diff = mantissa_sf - digits; // If the diff is greater than the scale we're focused on the integral. Otherwise, we can // just round. if diff > scale { use crate::constants::BIG_POWERS_10; // We need to adjust the integral portion. This also should be rounded, consequently // we reduce the number down, round it, and then scale back up. // E.g. If we have 305.459 scaling to a sf of 2 - we first reduce the number // down to 30.5459, round it to 31 and then scale it back up to 310. // Likewise, if we have 12301 scaling to a sf of 3 - we first reduce the number // down to 123.01, round it to 123 and then scale it back up to 12300. let mut num = *self; let mut exp = (diff - scale) as usize; while exp > 0 { let pow; if exp >= BIG_POWERS_10.len() { pow = Decimal::from(BIG_POWERS_10[BIG_POWERS_10.len() - 1]); exp -= BIG_POWERS_10.len(); } else { pow = Decimal::from(BIG_POWERS_10[exp - 1]); exp = 0; } num = num.checked_div(pow)?; } let mut num = num.round_dp_with_strategy(0, strategy).trunc(); let mut exp = (mantissa_sf - digits - scale) as usize; while exp > 0 { let pow; if exp >= BIG_POWERS_10.len() { pow = Decimal::from(BIG_POWERS_10[BIG_POWERS_10.len() - 1]); exp -= BIG_POWERS_10.len(); } else { pow = Decimal::from(BIG_POWERS_10[exp - 1]); exp = 0; } num = num.checked_mul(pow)?; } Some(num) } else { Some(self.round_dp_with_strategy(scale - diff, strategy)) } } Ordering::Equal => { // Case where significant figures = requested significant digits. Some(*self) } } } /// Convert `Decimal` to an internal representation of the underlying struct. This is useful /// for debugging the internal state of the object. /// /// # Important Disclaimer /// This is primarily intended for library maintainers. The internal representation of a /// `Decimal` is considered "unstable" for public use. /// /// # Example /// /// ``` /// # use rust_decimal::Decimal; /// use rust_decimal_macros::dec; /// /// let pi = dec!(3.1415926535897932384626433832); /// assert_eq!(format!("{:?}", pi), "3.1415926535897932384626433832"); /// assert_eq!(format!("{:?}", pi.unpack()), "UnpackedDecimal { \ /// negative: false, scale: 28, hi: 1703060790, mid: 185874565, lo: 1102470952 \ /// }"); /// ``` #[must_use] pub const fn unpack(&self) -> UnpackedDecimal { UnpackedDecimal { negative: self.is_sign_negative(), scale: self.scale(), hi: self.hi, lo: self.lo, mid: self.mid, } } #[inline(always)] pub(crate) const fn lo(&self) -> u32 { self.lo } #[inline(always)] pub(crate) const fn mid(&self) -> u32 { self.mid } #[inline(always)] pub(crate) const fn hi(&self) -> u32 { self.hi } #[inline(always)] pub(crate) const fn flags(&self) -> u32 { self.flags } #[inline(always)] pub(crate) const fn mantissa_array3(&self) -> [u32; 3] { [self.lo, self.mid, self.hi] } #[inline(always)] pub(crate) const fn mantissa_array4(&self) -> [u32; 4] { [self.lo, self.mid, self.hi, 0] } /// Parses a 32-bit float into a Decimal number whilst retaining any non-guaranteed precision. /// /// Typically when a float is parsed in Rust Decimal, any excess bits (after ~7.22 decimal points for /// f32 as per IEEE-754) are removed due to any digits following this are considered an approximation /// at best. This function bypasses this additional step and retains these excess bits. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// # /// // Usually floats are parsed leveraging float guarantees. i.e. 0.1_f32 => 0.1 /// assert_eq!("0.1", Decimal::from_f32(0.1_f32).unwrap().to_string()); /// /// // Sometimes, we may want to represent the approximation exactly. /// assert_eq!("0.100000001490116119384765625", Decimal::from_f32_retain(0.1_f32).unwrap().to_string()); /// ``` pub fn from_f32_retain(n: f32) -> Option { from_f32(n, false) } /// Parses a 64-bit float into a Decimal number whilst retaining any non-guaranteed precision. /// /// Typically when a float is parsed in Rust Decimal, any excess bits (after ~15.95 decimal points for /// f64 as per IEEE-754) are removed due to any digits following this are considered an approximation /// at best. This function bypasses this additional step and retains these excess bits. /// /// # Example /// /// ``` /// # use rust_decimal::prelude::*; /// # /// // Usually floats are parsed leveraging float guarantees. i.e. 0.1_f64 => 0.1 /// assert_eq!("0.1", Decimal::from_f64(0.1_f64).unwrap().to_string()); /// /// // Sometimes, we may want to represent the approximation exactly. /// assert_eq!("0.1000000000000000055511151231", Decimal::from_f64_retain(0.1_f64).unwrap().to_string()); /// ``` pub fn from_f64_retain(n: f64) -> Option { from_f64(n, false) } } impl Default for Decimal { /// Returns the default value for a `Decimal` (equivalent to `Decimal::ZERO`). [Read more] /// /// [Read more]: core::default::Default#tymethod.default #[inline] fn default() -> Self { ZERO } } pub(crate) enum CalculationResult { Ok(Decimal), Overflow, DivByZero, } #[inline] const fn flags(neg: bool, scale: u32) -> u32 { (scale << SCALE_SHIFT) | ((neg as u32) << SIGN_SHIFT) } macro_rules! integer_docs { ( true ) => { " by truncating and returning the integer component" }; ( false ) => { "" }; } // #[doc] attributes are formatted poorly with rustfmt so skip for now. // See https://github.com/rust-lang/rustfmt/issues/5062 for more information. #[rustfmt::skip] macro_rules! impl_try_from_decimal { ($TInto:ty, $conversion_fn:path, $additional_docs:expr) => { #[doc = concat!( "Try to convert a `Decimal` to `", stringify!($TInto), "`", $additional_docs, ".\n\nCan fail if the `Decimal` is out of range for `", stringify!($TInto), "`.", )] impl TryFrom for $TInto { type Error = crate::Error; #[inline] fn try_from(t: Decimal) -> Result { $conversion_fn(&t).ok_or_else(|| Error::ConversionTo(stringify!($TInto).into())) } } }; } impl_try_from_decimal!(f32, Decimal::to_f32, integer_docs!(false)); impl_try_from_decimal!(f64, Decimal::to_f64, integer_docs!(false)); impl_try_from_decimal!(isize, Decimal::to_isize, integer_docs!(true)); impl_try_from_decimal!(i8, Decimal::to_i8, integer_docs!(true)); impl_try_from_decimal!(i16, Decimal::to_i16, integer_docs!(true)); impl_try_from_decimal!(i32, Decimal::to_i32, integer_docs!(true)); impl_try_from_decimal!(i64, Decimal::to_i64, integer_docs!(true)); impl_try_from_decimal!(i128, Decimal::to_i128, integer_docs!(true)); impl_try_from_decimal!(usize, Decimal::to_usize, integer_docs!(true)); impl_try_from_decimal!(u8, Decimal::to_u8, integer_docs!(true)); impl_try_from_decimal!(u16, Decimal::to_u16, integer_docs!(true)); impl_try_from_decimal!(u32, Decimal::to_u32, integer_docs!(true)); impl_try_from_decimal!(u64, Decimal::to_u64, integer_docs!(true)); impl_try_from_decimal!(u128, Decimal::to_u128, integer_docs!(true)); // #[doc] attributes are formatted poorly with rustfmt so skip for now. // See https://github.com/rust-lang/rustfmt/issues/5062 for more information. #[rustfmt::skip] macro_rules! impl_try_from_primitive { ($TFrom:ty, $conversion_fn:path $(, $err:expr)?) => { #[doc = concat!( "Try to convert a `", stringify!($TFrom), "` into a `Decimal`.\n\nCan fail if the value is out of range for `Decimal`." )] impl TryFrom<$TFrom> for Decimal { type Error = crate::Error; #[inline] fn try_from(t: $TFrom) -> Result { $conversion_fn(t) $( .ok_or_else(|| $err) )? } } }; } impl_try_from_primitive!(f32, Self::from_f32, Error::ConversionTo("Decimal".into())); impl_try_from_primitive!(f64, Self::from_f64, Error::ConversionTo("Decimal".into())); impl_try_from_primitive!(&str, core::str::FromStr::from_str); macro_rules! impl_from { ($T:ty, $from_ty:path) => { /// /// Conversion to `Decimal`. /// impl core::convert::From<$T> for Decimal { #[inline] fn from(t: $T) -> Self { $from_ty(t).unwrap() } } }; } impl_from!(isize, FromPrimitive::from_isize); impl_from!(i8, FromPrimitive::from_i8); impl_from!(i16, FromPrimitive::from_i16); impl_from!(i32, FromPrimitive::from_i32); impl_from!(i64, FromPrimitive::from_i64); impl_from!(usize, FromPrimitive::from_usize); impl_from!(u8, FromPrimitive::from_u8); impl_from!(u16, FromPrimitive::from_u16); impl_from!(u32, FromPrimitive::from_u32); impl_from!(u64, FromPrimitive::from_u64); impl_from!(i128, FromPrimitive::from_i128); impl_from!(u128, FromPrimitive::from_u128); impl Zero for Decimal { fn zero() -> Decimal { ZERO } fn is_zero(&self) -> bool { self.is_zero() } } impl One for Decimal { fn one() -> Decimal { ONE } } impl Signed for Decimal { fn abs(&self) -> Self { self.abs() } fn abs_sub(&self, other: &Self) -> Self { if self <= other { ZERO } else { self.abs() } } fn signum(&self) -> Self { if self.is_zero() { ZERO } else { let mut value = ONE; if self.is_sign_negative() { value.set_sign_negative(true); } value } } fn is_positive(&self) -> bool { self.is_sign_positive() } fn is_negative(&self) -> bool { self.is_sign_negative() } } impl Num for Decimal { type FromStrRadixErr = Error; fn from_str_radix(str: &str, radix: u32) -> Result { Decimal::from_str_radix(str, radix) } } impl FromStr for Decimal { type Err = Error; fn from_str(value: &str) -> Result { crate::str::parse_str_radix_10(value) } } impl FromPrimitive for Decimal { fn from_i32(n: i32) -> Option { let flags: u32; let value_copy: i64; if n >= 0 { flags = 0; value_copy = n as i64; } else { flags = SIGN_MASK; value_copy = -(n as i64); } Some(Decimal { flags, lo: value_copy as u32, mid: 0, hi: 0, }) } fn from_i64(n: i64) -> Option { let flags: u32; let value_copy: i128; if n >= 0 { flags = 0; value_copy = n as i128; } else { flags = SIGN_MASK; value_copy = -(n as i128); } Some(Decimal { flags, lo: value_copy as u32, mid: (value_copy >> 32) as u32, hi: 0, }) } fn from_i128(n: i128) -> Option { let flags; let unsigned; if n >= 0 { unsigned = n as u128; flags = 0; } else { unsigned = -n as u128; flags = SIGN_MASK; }; // Check if we overflow if unsigned >> 96 != 0 { return None; } Some(Decimal { flags, lo: unsigned as u32, mid: (unsigned >> 32) as u32, hi: (unsigned >> 64) as u32, }) } fn from_u32(n: u32) -> Option { Some(Decimal { flags: 0, lo: n, mid: 0, hi: 0, }) } fn from_u64(n: u64) -> Option { Some(Decimal { flags: 0, lo: n as u32, mid: (n >> 32) as u32, hi: 0, }) } fn from_u128(n: u128) -> Option { // Check if we overflow if n >> 96 != 0 { return None; } Some(Decimal { flags: 0, lo: n as u32, mid: (n >> 32) as u32, hi: (n >> 64) as u32, }) } fn from_f32(n: f32) -> Option { // By default, we remove excess bits. This allows 0.1_f64 == dec!(0.1). from_f32(n, true) } fn from_f64(n: f64) -> Option { // By default, we remove excess bits. This allows 0.1_f64 == dec!(0.1). from_f64(n, true) } } #[inline] fn from_f64(n: f64, remove_excess_bits: bool) -> Option { // Handle the case if it is NaN, Infinity or -Infinity if !n.is_finite() { return None; } // It's a shame we can't use a union for this due to it being broken up by bits // i.e. 1/11/52 (sign, exponent, mantissa) // See https://en.wikipedia.org/wiki/IEEE_754-1985 // n = (sign*-1) * 2^exp * mantissa // Decimal of course stores this differently... 10^-exp * significand let raw = n.to_bits(); let positive = (raw >> 63) == 0; let biased_exponent = ((raw >> 52) & 0x7FF) as i32; let mantissa = raw & 0x000F_FFFF_FFFF_FFFF; // Handle the special zero case if biased_exponent == 0 && mantissa == 0 { let mut zero = ZERO; if !positive { zero.set_sign_negative(true); } return Some(zero); } // Get the bits and exponent2 let mut exponent2 = biased_exponent - 1023; let mut bits = [ (mantissa & 0xFFFF_FFFF) as u32, ((mantissa >> 32) & 0xFFFF_FFFF) as u32, 0u32, ]; if biased_exponent == 0 { // Denormalized number - correct the exponent exponent2 += 1; } else { // Add extra hidden bit to mantissa bits[1] |= 0x0010_0000; } // The act of copying a mantissa as integer bits is equivalent to shifting // left the mantissa 52 bits. The exponent is reduced to compensate. exponent2 -= 52; // Convert to decimal base2_to_decimal(&mut bits, exponent2, positive, true, remove_excess_bits) } #[inline] fn from_f32(n: f32, remove_excess_bits: bool) -> Option { // Handle the case if it is NaN, Infinity or -Infinity if !n.is_finite() { return None; } // It's a shame we can't use a union for this due to it being broken up by bits // i.e. 1/8/23 (sign, exponent, mantissa) // See https://en.wikipedia.org/wiki/IEEE_754-1985 // n = (sign*-1) * 2^exp * mantissa // Decimal of course stores this differently... 10^-exp * significand let raw = n.to_bits(); let positive = (raw >> 31) == 0; let biased_exponent = ((raw >> 23) & 0xFF) as i32; let mantissa = raw & 0x007F_FFFF; // Handle the special zero case if biased_exponent == 0 && mantissa == 0 { let mut zero = ZERO; if !positive { zero.set_sign_negative(true); } return Some(zero); } // Get the bits and exponent2 let mut exponent2 = biased_exponent - 127; let mut bits = [mantissa, 0u32, 0u32]; if biased_exponent == 0 { // Denormalized number - correct the exponent exponent2 += 1; } else { // Add extra hidden bit to mantissa bits[0] |= 0x0080_0000; } // The act of copying a mantissa as integer bits is equivalent to shifting // left the mantissa 23 bits. The exponent is reduced to compensate. exponent2 -= 23; // Convert to decimal base2_to_decimal(&mut bits, exponent2, positive, false, remove_excess_bits) } fn base2_to_decimal( bits: &mut [u32; 3], exponent2: i32, positive: bool, is64: bool, remove_excess_bits: bool, ) -> Option { // 2^exponent2 = (10^exponent2)/(5^exponent2) // = (5^-exponent2)*(10^exponent2) let mut exponent5 = -exponent2; let mut exponent10 = exponent2; // Ultimately, we want this for the scale while exponent5 > 0 { // Check to see if the mantissa is divisible by 2 if bits[0] & 0x1 == 0 { exponent10 += 1; exponent5 -= 1; // We can divide by 2 without losing precision let hi_carry = bits[2] & 0x1 == 1; bits[2] >>= 1; let mid_carry = bits[1] & 0x1 == 1; bits[1] = (bits[1] >> 1) | if hi_carry { SIGN_MASK } else { 0 }; bits[0] = (bits[0] >> 1) | if mid_carry { SIGN_MASK } else { 0 }; } else { // The mantissa is NOT divisible by 2. Therefore the mantissa should // be multiplied by 5, unless the multiplication overflows. exponent5 -= 1; let mut temp = [bits[0], bits[1], bits[2]]; if ops::array::mul_by_u32(&mut temp, 5) == 0 { // Multiplication succeeded without overflow, so copy result back bits[0] = temp[0]; bits[1] = temp[1]; bits[2] = temp[2]; } else { // Multiplication by 5 overflows. The mantissa should be divided // by 2, and therefore will lose significant digits. exponent10 += 1; // Shift right let hi_carry = bits[2] & 0x1 == 1; bits[2] >>= 1; let mid_carry = bits[1] & 0x1 == 1; bits[1] = (bits[1] >> 1) | if hi_carry { SIGN_MASK } else { 0 }; bits[0] = (bits[0] >> 1) | if mid_carry { SIGN_MASK } else { 0 }; } } } // In order to divide the value by 5, it is best to multiply by 2/10. // Therefore, exponent10 is decremented, and the mantissa should be multiplied by 2 while exponent5 < 0 { if bits[2] & SIGN_MASK == 0 { // No far left bit, the mantissa can withstand a shift-left without overflowing exponent10 -= 1; exponent5 += 1; ops::array::shl1_internal(bits, 0); } else { // The mantissa would overflow if shifted. Therefore it should be // directly divided by 5. This will lose significant digits, unless // by chance the mantissa happens to be divisible by 5. exponent5 += 1; ops::array::div_by_u32(bits, 5); } } // 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 // down appropriately. while exponent10 > 0 { // In order to bring exponent10 down to 0, the mantissa should be // multiplied by 10 to compensate. If the exponent10 is too big, this // will cause the mantissa to overflow. if ops::array::mul_by_u32(bits, 10) == 0 { exponent10 -= 1; } else { // Overflowed - return? return None; } } // In order to bring exponent up to -MAX_PRECISION, 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) { let rem10 = ops::array::div_by_u32(bits, 10); exponent10 += 1; if ops::array::is_all_zero(bits) { // Underflow, unable to keep dividing exponent10 = 0; } else if rem10 >= 5 { ops::array::add_one_internal(bits); } } if remove_excess_bits { // This step is required in order to remove excess bits of precision from the // end of the bit representation, down to the precision guaranteed by the // floating point number (see IEEE-754). if is64 { // Guaranteed to approx 15/16 dp while exponent10 < 0 && (bits[2] != 0 || (bits[1] & 0xFFF0_0000) != 0) { let rem10 = ops::array::div_by_u32(bits, 10); exponent10 += 1; if rem10 >= 5 { ops::array::add_one_internal(bits); } } } else { // Guaranteed to about 7/8 dp while exponent10 < 0 && ((bits[0] & 0xFF00_0000) != 0 || bits[1] != 0 || bits[2] != 0) { let rem10 = ops::array::div_by_u32(bits, 10); exponent10 += 1; if rem10 >= 5 { ops::array::add_one_internal(bits); } } } // Remove multiples of 10 from the representation while exponent10 < 0 { let mut temp = [bits[0], bits[1], bits[2]]; let remainder = ops::array::div_by_u32(&mut temp, 10); if remainder == 0 { exponent10 += 1; bits[0] = temp[0]; bits[1] = temp[1]; bits[2] = temp[2]; } else { break; } } } Some(Decimal { lo: bits[0], mid: bits[1], hi: bits[2], flags: flags(!positive, -exponent10 as u32), }) } impl ToPrimitive for Decimal { fn to_i64(&self) -> Option { let d = self.trunc(); // If it is in the hi bit then it is a clear overflow. if d.hi != 0 { // Overflow return None; } let negative = self.is_sign_negative(); // A bit more convoluted in terms of checking when it comes to the hi bit due to twos-complement if d.mid & 0x8000_0000 > 0 { if negative && d.mid == 0x8000_0000 && d.lo == 0 { // We do this because below we try to convert the i64 to a positive first - of which // doesn't fit into an i64. return Some(i64::MIN); } return None; } let raw: i64 = (i64::from(d.mid) << 32) | i64::from(d.lo); if negative { Some(raw.neg()) } else { Some(raw) } } fn to_i128(&self) -> Option { let d = self.trunc(); let raw: i128 = ((i128::from(d.hi) << 64) | i128::from(d.mid) << 32) | i128::from(d.lo); if self.is_sign_negative() { Some(-raw) } else { Some(raw) } } fn to_u64(&self) -> Option { if self.is_sign_negative() { return None; } let d = self.trunc(); if d.hi != 0 { // Overflow return None; } Some((u64::from(d.mid) << 32) | u64::from(d.lo)) } fn to_u128(&self) -> Option { if self.is_sign_negative() { return None; } let d = self.trunc(); Some((u128::from(d.hi) << 64) | (u128::from(d.mid) << 32) | u128::from(d.lo)) } fn to_f64(&self) -> Option { if self.scale() == 0 { // If scale is zero, we are storing a 96-bit integer value, that would // always fit into i128, which in turn is always representable as f64, // albeit with loss of precision for values outside of -2^53..2^53 range. let integer = self.to_i128(); integer.map(|i| i as f64) } else { let sign: f64 = if self.is_sign_negative() { -1.0 } else { 1.0 }; let mut mantissa: u128 = self.lo.into(); mantissa |= (self.mid as u128) << 32; mantissa |= (self.hi as u128) << 64; // scale is at most 28, so this fits comfortably into a u128. let scale = self.scale(); let precision: u128 = 10_u128.pow(scale); let integral_part = mantissa / precision; let frac_part = mantissa % precision; let frac_f64 = (frac_part as f64) / (precision as f64); let value = sign * ((integral_part as f64) + frac_f64); let round_to = 10f64.powi(self.scale() as i32); Some((value * round_to).round() / round_to) } } } impl fmt::Display for Decimal { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { let (rep, additional) = crate::str::to_str_internal(self, false, f.precision()); if let Some(additional) = additional { let value = [rep.as_str(), "0".repeat(additional).as_str()].concat(); f.pad_integral(self.is_sign_positive(), "", value.as_str()) } else { f.pad_integral(self.is_sign_positive(), "", rep.as_str()) } } } impl fmt::Debug for Decimal { fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { fmt::Display::fmt(self, f) } } impl fmt::LowerExp for Decimal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { crate::str::fmt_scientific_notation(self, "e", f) } } impl fmt::UpperExp for Decimal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { crate::str::fmt_scientific_notation(self, "E", f) } } impl Neg for Decimal { type Output = Decimal; fn neg(self) -> Decimal { let mut copy = self; copy.set_sign_negative(self.is_sign_positive()); copy } } impl<'a> Neg for &'a Decimal { type Output = Decimal; fn neg(self) -> Decimal { Decimal { flags: flags(!self.is_sign_negative(), self.scale()), hi: self.hi, lo: self.lo, mid: self.mid, } } } impl AddAssign for Decimal { fn add_assign(&mut self, other: Decimal) { let result = self.add(other); self.lo = result.lo; self.mid = result.mid; self.hi = result.hi; self.flags = result.flags; } } impl<'a> AddAssign<&'a Decimal> for Decimal { fn add_assign(&mut self, other: &'a Decimal) { Decimal::add_assign(self, *other) } } impl<'a> AddAssign for &'a mut Decimal { fn add_assign(&mut self, other: Decimal) { Decimal::add_assign(*self, other) } } impl<'a> AddAssign<&'a Decimal> for &'a mut Decimal { fn add_assign(&mut self, other: &'a Decimal) { Decimal::add_assign(*self, *other) } } impl SubAssign for Decimal { fn sub_assign(&mut self, other: Decimal) { let result = self.sub(other); self.lo = result.lo; self.mid = result.mid; self.hi = result.hi; self.flags = result.flags; } } impl<'a> SubAssign<&'a Decimal> for Decimal { fn sub_assign(&mut self, other: &'a Decimal) { Decimal::sub_assign(self, *other) } } impl<'a> SubAssign for &'a mut Decimal { fn sub_assign(&mut self, other: Decimal) { Decimal::sub_assign(*self, other) } } impl<'a> SubAssign<&'a Decimal> for &'a mut Decimal { fn sub_assign(&mut self, other: &'a Decimal) { Decimal::sub_assign(*self, *other) } } impl MulAssign for Decimal { fn mul_assign(&mut self, other: Decimal) { let result = self.mul(other); self.lo = result.lo; self.mid = result.mid; self.hi = result.hi; self.flags = result.flags; } } impl<'a> MulAssign<&'a Decimal> for Decimal { fn mul_assign(&mut self, other: &'a Decimal) { Decimal::mul_assign(self, *other) } } impl<'a> MulAssign for &'a mut Decimal { fn mul_assign(&mut self, other: Decimal) { Decimal::mul_assign(*self, other) } } impl<'a> MulAssign<&'a Decimal> for &'a mut Decimal { fn mul_assign(&mut self, other: &'a Decimal) { Decimal::mul_assign(*self, *other) } } impl DivAssign for Decimal { fn div_assign(&mut self, other: Decimal) { let result = self.div(other); self.lo = result.lo; self.mid = result.mid; self.hi = result.hi; self.flags = result.flags; } } impl<'a> DivAssign<&'a Decimal> for Decimal { fn div_assign(&mut self, other: &'a Decimal) { Decimal::div_assign(self, *other) } } impl<'a> DivAssign for &'a mut Decimal { fn div_assign(&mut self, other: Decimal) { Decimal::div_assign(*self, other) } } impl<'a> DivAssign<&'a Decimal> for &'a mut Decimal { fn div_assign(&mut self, other: &'a Decimal) { Decimal::div_assign(*self, *other) } } impl RemAssign for Decimal { fn rem_assign(&mut self, other: Decimal) { let result = self.rem(other); self.lo = result.lo; self.mid = result.mid; self.hi = result.hi; self.flags = result.flags; } } impl<'a> RemAssign<&'a Decimal> for Decimal { fn rem_assign(&mut self, other: &'a Decimal) { Decimal::rem_assign(self, *other) } } impl<'a> RemAssign for &'a mut Decimal { fn rem_assign(&mut self, other: Decimal) { Decimal::rem_assign(*self, other) } } impl<'a> RemAssign<&'a Decimal> for &'a mut Decimal { fn rem_assign(&mut self, other: &'a Decimal) { Decimal::rem_assign(*self, *other) } } impl PartialEq for Decimal { #[inline] fn eq(&self, other: &Decimal) -> bool { self.cmp(other) == Equal } } impl Eq for Decimal {} impl Hash for Decimal { fn hash(&self, state: &mut H) { let n = self.normalize(); n.lo.hash(state); n.mid.hash(state); n.hi.hash(state); n.flags.hash(state); } } impl PartialOrd for Decimal { #[inline] fn partial_cmp(&self, other: &Decimal) -> Option { Some(self.cmp(other)) } } impl Ord for Decimal { fn cmp(&self, other: &Decimal) -> Ordering { ops::cmp_impl(self, other) } } impl Product for Decimal { /// Panics if out-of-bounds fn product>(iter: I) -> Self { let mut product = ONE; for i in iter { product *= i; } product } } impl<'a> Product<&'a Decimal> for Decimal { /// Panics if out-of-bounds fn product>(iter: I) -> Self { let mut product = ONE; for i in iter { product *= i; } product } } impl Sum for Decimal { fn sum>(iter: I) -> Self { let mut sum = ZERO; for i in iter { sum += i; } sum } } impl<'a> Sum<&'a Decimal> for Decimal { fn sum>(iter: I) -> Self { let mut sum = ZERO; for i in iter { sum += i; } sum } }