secret_cosmwasm_std/math/
decimal.rs

1use forward_ref::{forward_ref_binop, forward_ref_op_assign};
2use schemars::JsonSchema;
3use serde::{de, ser, Deserialize, Deserializer, Serialize};
4use std::cmp::Ordering;
5use std::fmt::{self, Write};
6use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Sub, SubAssign};
7use std::str::FromStr;
8use thiserror::Error;
9
10use crate::errors::{
11    CheckedFromRatioError, CheckedMultiplyRatioError, DivideByZeroError, OverflowError,
12    OverflowOperation, RoundUpOverflowError, StdError,
13};
14
15use super::Fraction;
16use super::Isqrt;
17use super::{Uint128, Uint256};
18
19/// A fixed-point decimal value with 18 fractional digits, i.e. Decimal(1_000_000_000_000_000_000) == 1.0
20///
21/// The greatest possible value that can be represented is 340282366920938463463.374607431768211455 (which is (2^128 - 1) / 10^18)
22#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
23pub struct Decimal(#[schemars(with = "String")] Uint128);
24
25#[derive(Error, Debug, PartialEq, Eq)]
26#[error("Decimal range exceeded")]
27pub struct DecimalRangeExceeded;
28
29impl Decimal {
30    const DECIMAL_FRACTIONAL: Uint128 = Uint128::new(1_000_000_000_000_000_000u128); // 1*10**18
31    const DECIMAL_FRACTIONAL_SQUARED: Uint128 =
32        Uint128::new(1_000_000_000_000_000_000_000_000_000_000_000_000u128); // (1*10**18)**2 = 1*10**36
33
34    /// The number of decimal places. Since decimal types are fixed-point rather than
35    /// floating-point, this is a constant.
36    pub const DECIMAL_PLACES: u32 = 18; // This needs to be an even number.
37    /// The largest value that can be represented by this decimal type.
38    pub const MAX: Self = Self(Uint128::MAX);
39    /// The smallest value that can be represented by this decimal type.
40    pub const MIN: Self = Self(Uint128::MIN);
41
42    /// Creates a Decimal(value)
43    /// This is equivalent to `Decimal::from_atomics(value, 18)` but usable in a const context.
44    pub const fn new(value: Uint128) -> Self {
45        Self(value)
46    }
47
48    /// Creates a Decimal(Uint128(value))
49    /// This is equivalent to `Decimal::from_atomics(value, 18)` but usable in a const context.
50    pub const fn raw(value: u128) -> Self {
51        Self(Uint128::new(value))
52    }
53
54    /// Create a 1.0 Decimal
55    #[inline]
56    pub const fn one() -> Self {
57        Self(Self::DECIMAL_FRACTIONAL)
58    }
59
60    /// Create a 0.0 Decimal
61    #[inline]
62    pub const fn zero() -> Self {
63        Self(Uint128::zero())
64    }
65
66    /// Convert x% into Decimal
67    pub fn percent(x: u64) -> Self {
68        Self(((x as u128) * 10_000_000_000_000_000).into())
69    }
70
71    /// Convert permille (x/1000) into Decimal
72    pub fn permille(x: u64) -> Self {
73        Self(((x as u128) * 1_000_000_000_000_000).into())
74    }
75
76    /// Creates a decimal from a number of atomic units and the number
77    /// of decimal places. The inputs will be converted internally to form
78    /// a decimal with 18 decimal places. So the input 123 and 2 will create
79    /// the decimal 1.23.
80    ///
81    /// Using 18 decimal places is slightly more efficient than other values
82    /// as no internal conversion is necessary.
83    ///
84    /// ## Examples
85    ///
86    /// ```
87    /// # use secret_cosmwasm_std::{Decimal, Uint128};
88    /// let a = Decimal::from_atomics(Uint128::new(1234), 3).unwrap();
89    /// assert_eq!(a.to_string(), "1.234");
90    ///
91    /// let a = Decimal::from_atomics(1234u128, 0).unwrap();
92    /// assert_eq!(a.to_string(), "1234");
93    ///
94    /// let a = Decimal::from_atomics(1u64, 18).unwrap();
95    /// assert_eq!(a.to_string(), "0.000000000000000001");
96    /// ```
97    pub fn from_atomics(
98        atomics: impl Into<Uint128>,
99        decimal_places: u32,
100    ) -> Result<Self, DecimalRangeExceeded> {
101        let atomics = atomics.into();
102        const TEN: Uint128 = Uint128::new(10);
103        Ok(match decimal_places.cmp(&(Self::DECIMAL_PLACES)) {
104            Ordering::Less => {
105                let digits = (Self::DECIMAL_PLACES) - decimal_places; // No overflow because decimal_places < DECIMAL_PLACES
106                let factor = TEN.checked_pow(digits).unwrap(); // Safe because digits <= 17
107                Self(
108                    atomics
109                        .checked_mul(factor)
110                        .map_err(|_| DecimalRangeExceeded)?,
111                )
112            }
113            Ordering::Equal => Self(atomics),
114            Ordering::Greater => {
115                let digits = decimal_places - (Self::DECIMAL_PLACES); // No overflow because decimal_places > DECIMAL_PLACES
116                if let Ok(factor) = TEN.checked_pow(digits) {
117                    Self(atomics.checked_div(factor).unwrap()) // Safe because factor cannot be zero
118                } else {
119                    // In this case `factor` exceeds the Uint128 range.
120                    // Any Uint128 `x` divided by `factor` with `factor > Uint128::MAX` is 0.
121                    // Try e.g. Python3: `(2**128-1) // 2**128`
122                    Self(Uint128::zero())
123                }
124            }
125        })
126    }
127
128    /// Returns the ratio (numerator / denominator) as a Decimal
129    pub fn from_ratio(numerator: impl Into<Uint128>, denominator: impl Into<Uint128>) -> Self {
130        match Decimal::checked_from_ratio(numerator, denominator) {
131            Ok(value) => value,
132            Err(CheckedFromRatioError::DivideByZero) => {
133                panic!("Denominator must not be zero")
134            }
135            Err(CheckedFromRatioError::Overflow) => panic!("Multiplication overflow"),
136        }
137    }
138
139    /// Returns the ratio (numerator / denominator) as a Decimal
140    pub fn checked_from_ratio(
141        numerator: impl Into<Uint128>,
142        denominator: impl Into<Uint128>,
143    ) -> Result<Self, CheckedFromRatioError> {
144        let numerator: Uint128 = numerator.into();
145        let denominator: Uint128 = denominator.into();
146        match numerator.checked_multiply_ratio(Self::DECIMAL_FRACTIONAL, denominator) {
147            Ok(ratio) => {
148                // numerator * DECIMAL_FRACTIONAL / denominator
149                Ok(Decimal(ratio))
150            }
151            Err(CheckedMultiplyRatioError::Overflow) => Err(CheckedFromRatioError::Overflow),
152            Err(CheckedMultiplyRatioError::DivideByZero) => {
153                Err(CheckedFromRatioError::DivideByZero)
154            }
155        }
156    }
157
158    pub const fn is_zero(&self) -> bool {
159        self.0.is_zero()
160    }
161
162    /// A decimal is an integer of atomic units plus a number that specifies the
163    /// position of the decimal dot. So any decimal can be expressed as two numbers.
164    ///
165    /// ## Examples
166    ///
167    /// ```
168    /// # use secret_cosmwasm_std::{Decimal, Uint128};
169    /// # use std::str::FromStr;
170    /// // Value with whole and fractional part
171    /// let a = Decimal::from_str("1.234").unwrap();
172    /// assert_eq!(a.decimal_places(), 18);
173    /// assert_eq!(a.atomics(), Uint128::new(1234000000000000000));
174    ///
175    /// // Smallest possible value
176    /// let b = Decimal::from_str("0.000000000000000001").unwrap();
177    /// assert_eq!(b.decimal_places(), 18);
178    /// assert_eq!(b.atomics(), Uint128::new(1));
179    /// ```
180    #[inline]
181    pub const fn atomics(&self) -> Uint128 {
182        self.0
183    }
184
185    /// The number of decimal places. This is a constant value for now
186    /// but this could potentially change as the type evolves.
187    ///
188    /// See also [`Decimal::atomics()`].
189    #[inline]
190    pub const fn decimal_places(&self) -> u32 {
191        Self::DECIMAL_PLACES
192    }
193
194    /// Rounds value down after decimal places.
195    pub fn floor(&self) -> Self {
196        Self((self.0 / Self::DECIMAL_FRACTIONAL) * Self::DECIMAL_FRACTIONAL)
197    }
198
199    /// Rounds value up after decimal places. Panics on overflow.
200    pub fn ceil(&self) -> Self {
201        match self.checked_ceil() {
202            Ok(value) => value,
203            Err(_) => panic!("attempt to ceil with overflow"),
204        }
205    }
206
207    /// Rounds value up after decimal places. Returns OverflowError on overflow.
208    pub fn checked_ceil(&self) -> Result<Self, RoundUpOverflowError> {
209        let floor = self.floor();
210        if floor == self {
211            Ok(floor)
212        } else {
213            floor
214                .checked_add(Decimal::one())
215                .map_err(|_| RoundUpOverflowError)
216        }
217    }
218
219    pub fn checked_add(self, other: Self) -> Result<Self, OverflowError> {
220        self.0
221            .checked_add(other.0)
222            .map(Self)
223            .map_err(|_| OverflowError::new(OverflowOperation::Add, self, other))
224    }
225
226    pub fn checked_sub(self, other: Self) -> Result<Self, OverflowError> {
227        self.0
228            .checked_sub(other.0)
229            .map(Self)
230            .map_err(|_| OverflowError::new(OverflowOperation::Sub, self, other))
231    }
232
233    /// Multiplies one `Decimal` by another, returning an `OverflowError` if an overflow occurred.
234    pub fn checked_mul(self, other: Self) -> Result<Self, OverflowError> {
235        let result_as_uint256 = self.numerator().full_mul(other.numerator())
236            / Uint256::from_uint128(Self::DECIMAL_FRACTIONAL); // from_uint128 is a const method and should be "free"
237        result_as_uint256
238            .try_into()
239            .map(Self)
240            .map_err(|_| OverflowError {
241                operation: crate::OverflowOperation::Mul,
242                operand1: self.to_string(),
243                operand2: other.to_string(),
244            })
245    }
246
247    /// Raises a value to the power of `exp`, panics if an overflow occurred.
248    pub fn pow(self, exp: u32) -> Self {
249        match self.checked_pow(exp) {
250            Ok(value) => value,
251            Err(_) => panic!("Multiplication overflow"),
252        }
253    }
254
255    /// Raises a value to the power of `exp`, returning an `OverflowError` if an overflow occurred.
256    pub fn checked_pow(self, exp: u32) -> Result<Self, OverflowError> {
257        // This uses the exponentiation by squaring algorithm:
258        // https://en.wikipedia.org/wiki/Exponentiation_by_squaring#Basic_method
259
260        fn inner(mut x: Decimal, mut n: u32) -> Result<Decimal, OverflowError> {
261            if n == 0 {
262                return Ok(Decimal::one());
263            }
264
265            let mut y = Decimal::one();
266
267            while n > 1 {
268                if n % 2 == 0 {
269                    x = x.checked_mul(x)?;
270                    n /= 2;
271                } else {
272                    y = x.checked_mul(y)?;
273                    x = x.checked_mul(x)?;
274                    n = (n - 1) / 2;
275                }
276            }
277
278            Ok(x * y)
279        }
280
281        inner(self, exp).map_err(|_| OverflowError {
282            operation: crate::OverflowOperation::Pow,
283            operand1: self.to_string(),
284            operand2: exp.to_string(),
285        })
286    }
287
288    pub fn checked_div(self, other: Self) -> Result<Self, CheckedFromRatioError> {
289        Decimal::checked_from_ratio(self.numerator(), other.numerator())
290    }
291
292    pub fn checked_rem(self, other: Self) -> Result<Self, DivideByZeroError> {
293        self.0
294            .checked_rem(other.0)
295            .map(Self)
296            .map_err(|_| DivideByZeroError::new(self))
297    }
298
299    /// Returns the approximate square root as a Decimal.
300    ///
301    /// This should not overflow or panic.
302    pub fn sqrt(&self) -> Self {
303        // Algorithm described in https://hackmd.io/@webmaster128/SJThlukj_
304        // We start with the highest precision possible and lower it until
305        // there's no overflow.
306        //
307        // TODO: This could be made more efficient once log10 is in:
308        // https://github.com/rust-lang/rust/issues/70887
309        // The max precision is something like `9 - log10(self.0) / 2`.
310        (0..=Self::DECIMAL_PLACES / 2)
311            .rev()
312            .find_map(|i| self.sqrt_with_precision(i))
313            // The last step (i = 0) is guaranteed to succeed because `isqrt(u128::MAX) * 10^9` does not overflow
314            .unwrap()
315    }
316
317    /// Lower precision means more aggressive rounding, but less risk of overflow.
318    /// Precision *must* be a number between 0 and 9 (inclusive).
319    ///
320    /// Returns `None` if the internal multiplication overflows.
321    fn sqrt_with_precision(&self, precision: u32) -> Option<Self> {
322        let inner_mul = 100u128.pow(precision);
323        self.0.checked_mul(inner_mul.into()).ok().map(|inner| {
324            let outer_mul = 10u128.pow(Self::DECIMAL_PLACES / 2 - precision);
325            Decimal(inner.isqrt().checked_mul(Uint128::from(outer_mul)).unwrap())
326        })
327    }
328
329    pub const fn abs_diff(self, other: Self) -> Self {
330        Self(self.0.abs_diff(other.0))
331    }
332
333    pub fn saturating_add(self, other: Self) -> Self {
334        match self.checked_add(other) {
335            Ok(value) => value,
336            Err(_) => Self::MAX,
337        }
338    }
339
340    pub fn saturating_sub(self, other: Self) -> Self {
341        match self.checked_sub(other) {
342            Ok(value) => value,
343            Err(_) => Self::zero(),
344        }
345    }
346
347    pub fn saturating_mul(self, other: Self) -> Self {
348        match self.checked_mul(other) {
349            Ok(value) => value,
350            Err(_) => Self::MAX,
351        }
352    }
353
354    pub fn saturating_pow(self, exp: u32) -> Self {
355        match self.checked_pow(exp) {
356            Ok(value) => value,
357            Err(_) => Self::MAX,
358        }
359    }
360}
361
362impl Fraction<Uint128> for Decimal {
363    #[inline]
364    fn numerator(&self) -> Uint128 {
365        self.0
366    }
367
368    #[inline]
369    fn denominator(&self) -> Uint128 {
370        Self::DECIMAL_FRACTIONAL
371    }
372
373    /// Returns the multiplicative inverse `1/d` for decimal `d`.
374    ///
375    /// If `d` is zero, none is returned.
376    fn inv(&self) -> Option<Self> {
377        if self.is_zero() {
378            None
379        } else {
380            // Let self be p/q with p = self.0 and q = DECIMAL_FRACTIONAL.
381            // Now we calculate the inverse a/b = q/p such that b = DECIMAL_FRACTIONAL. Then
382            // `a = DECIMAL_FRACTIONAL*DECIMAL_FRACTIONAL / self.0`.
383            Some(Decimal(Self::DECIMAL_FRACTIONAL_SQUARED / self.0))
384        }
385    }
386}
387
388impl FromStr for Decimal {
389    type Err = StdError;
390
391    /// Converts the decimal string to a Decimal
392    /// Possible inputs: "1.23", "1", "000012", "1.123000000"
393    /// Disallowed: "", ".23"
394    ///
395    /// This never performs any kind of rounding.
396    /// More than DECIMAL_PLACES fractional digits, even zeros, result in an error.
397    fn from_str(input: &str) -> Result<Self, Self::Err> {
398        let mut parts_iter = input.split('.');
399
400        let whole_part = parts_iter.next().unwrap(); // split always returns at least one element
401        let whole = whole_part
402            .parse::<Uint128>()
403            .map_err(|_| StdError::generic_err("Error parsing whole"))?;
404        let mut atomics = whole
405            .checked_mul(Self::DECIMAL_FRACTIONAL)
406            .map_err(|_| StdError::generic_err("Value too big"))?;
407
408        if let Some(fractional_part) = parts_iter.next() {
409            let fractional = fractional_part
410                .parse::<Uint128>()
411                .map_err(|_| StdError::generic_err("Error parsing fractional"))?;
412            let exp = (Self::DECIMAL_PLACES.checked_sub(fractional_part.len() as u32)).ok_or_else(
413                || {
414                    StdError::generic_err(format!(
415                        "Cannot parse more than {} fractional digits",
416                        Self::DECIMAL_PLACES
417                    ))
418                },
419            )?;
420            debug_assert!(exp <= Self::DECIMAL_PLACES);
421            let fractional_factor = Uint128::from(10u128.pow(exp));
422            atomics = atomics
423                .checked_add(
424                    // The inner multiplication can't overflow because
425                    // fractional < 10^DECIMAL_PLACES && fractional_factor <= 10^DECIMAL_PLACES
426                    fractional.checked_mul(fractional_factor).unwrap(),
427                )
428                .map_err(|_| StdError::generic_err("Value too big"))?;
429        }
430
431        if parts_iter.next().is_some() {
432            return Err(StdError::generic_err("Unexpected number of dots"));
433        }
434
435        Ok(Decimal(atomics))
436    }
437}
438
439impl fmt::Display for Decimal {
440    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
441        let whole = (self.0) / Self::DECIMAL_FRACTIONAL;
442        let fractional = (self.0).checked_rem(Self::DECIMAL_FRACTIONAL).unwrap();
443
444        if fractional.is_zero() {
445            write!(f, "{}", whole)
446        } else {
447            let fractional_string = format!(
448                "{:0>padding$}",
449                fractional,
450                padding = Self::DECIMAL_PLACES as usize
451            );
452            f.write_str(&whole.to_string())?;
453            f.write_char('.')?;
454            f.write_str(fractional_string.trim_end_matches('0'))?;
455            Ok(())
456        }
457    }
458}
459
460impl Add for Decimal {
461    type Output = Self;
462
463    fn add(self, other: Self) -> Self {
464        Decimal(self.0 + other.0)
465    }
466}
467forward_ref_binop!(impl Add, add for Decimal, Decimal);
468
469impl AddAssign for Decimal {
470    fn add_assign(&mut self, rhs: Decimal) {
471        *self = *self + rhs;
472    }
473}
474forward_ref_op_assign!(impl AddAssign, add_assign for Decimal, Decimal);
475
476impl Sub for Decimal {
477    type Output = Self;
478
479    fn sub(self, other: Self) -> Self {
480        Decimal(self.0 - other.0)
481    }
482}
483forward_ref_binop!(impl Sub, sub for Decimal, Decimal);
484
485impl SubAssign for Decimal {
486    fn sub_assign(&mut self, rhs: Decimal) {
487        *self = *self - rhs;
488    }
489}
490forward_ref_op_assign!(impl SubAssign, sub_assign for Decimal, Decimal);
491
492impl Mul for Decimal {
493    type Output = Self;
494
495    #[allow(clippy::suspicious_arithmetic_impl)]
496    fn mul(self, other: Self) -> Self {
497        // Decimals are fractions. We can multiply two decimals a and b
498        // via
499        //       (a.numerator() * b.numerator()) / (a.denominator() * b.denominator())
500        //     = (a.numerator() * b.numerator()) / a.denominator() / b.denominator()
501
502        let result_as_uint256 = self.numerator().full_mul(other.numerator())
503            / Uint256::from_uint128(Self::DECIMAL_FRACTIONAL); // from_uint128 is a const method and should be "free"
504        match result_as_uint256.try_into() {
505            Ok(result) => Self(result),
506            Err(_) => panic!("attempt to multiply with overflow"),
507        }
508    }
509}
510forward_ref_binop!(impl Mul, mul for Decimal, Decimal);
511
512impl MulAssign for Decimal {
513    fn mul_assign(&mut self, rhs: Decimal) {
514        *self = *self * rhs;
515    }
516}
517forward_ref_op_assign!(impl MulAssign, mul_assign for Decimal, Decimal);
518
519/// Both d*u and u*d with d: Decimal and u: Uint128 returns an Uint128. There is no
520/// specific reason for this decision other than the initial use cases we have. If you
521/// need a Decimal result for the same calculation, use Decimal(d*u) or Decimal(u*d).
522impl Mul<Decimal> for Uint128 {
523    type Output = Self;
524
525    #[allow(clippy::suspicious_arithmetic_impl)]
526    fn mul(self, rhs: Decimal) -> Self::Output {
527        // 0*a and b*0 is always 0
528        if self.is_zero() || rhs.is_zero() {
529            return Uint128::zero();
530        }
531        self.multiply_ratio(rhs.0, Decimal::DECIMAL_FRACTIONAL)
532    }
533}
534
535impl Mul<Uint128> for Decimal {
536    type Output = Uint128;
537
538    fn mul(self, rhs: Uint128) -> Self::Output {
539        rhs * self
540    }
541}
542
543impl Div for Decimal {
544    type Output = Self;
545
546    fn div(self, other: Self) -> Self {
547        match Decimal::checked_from_ratio(self.numerator(), other.numerator()) {
548            Ok(ratio) => ratio,
549            Err(CheckedFromRatioError::DivideByZero) => {
550                panic!("Division failed - denominator must not be zero")
551            }
552            Err(CheckedFromRatioError::Overflow) => {
553                panic!("Division failed - multiplication overflow")
554            }
555        }
556    }
557}
558forward_ref_binop!(impl Div, div for Decimal, Decimal);
559
560impl DivAssign for Decimal {
561    fn div_assign(&mut self, rhs: Decimal) {
562        *self = *self / rhs;
563    }
564}
565forward_ref_op_assign!(impl DivAssign, div_assign for Decimal, Decimal);
566
567impl Div<Uint128> for Decimal {
568    type Output = Self;
569
570    fn div(self, rhs: Uint128) -> Self::Output {
571        Decimal(self.0 / rhs)
572    }
573}
574
575impl DivAssign<Uint128> for Decimal {
576    fn div_assign(&mut self, rhs: Uint128) {
577        self.0 /= rhs;
578    }
579}
580
581impl Rem for Decimal {
582    type Output = Self;
583
584    /// # Panics
585    ///
586    /// This operation will panic if `rhs` is zero
587    #[inline]
588    fn rem(self, rhs: Self) -> Self {
589        Self(self.0.rem(rhs.0))
590    }
591}
592forward_ref_binop!(impl Rem, rem for Decimal, Decimal);
593
594impl RemAssign<Decimal> for Decimal {
595    fn rem_assign(&mut self, rhs: Decimal) {
596        *self = *self % rhs;
597    }
598}
599forward_ref_op_assign!(impl RemAssign, rem_assign for Decimal, Decimal);
600
601impl<A> std::iter::Sum<A> for Decimal
602where
603    Self: Add<A, Output = Self>,
604{
605    fn sum<I: Iterator<Item = A>>(iter: I) -> Self {
606        iter.fold(Self::zero(), Add::add)
607    }
608}
609
610/// Serializes as a decimal string
611impl Serialize for Decimal {
612    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
613    where
614        S: ser::Serializer,
615    {
616        serializer.serialize_str(&self.to_string())
617    }
618}
619
620/// Deserializes as a base64 string
621impl<'de> Deserialize<'de> for Decimal {
622    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
623    where
624        D: Deserializer<'de>,
625    {
626        deserializer.deserialize_str(DecimalVisitor)
627    }
628}
629
630struct DecimalVisitor;
631
632impl<'de> de::Visitor<'de> for DecimalVisitor {
633    type Value = Decimal;
634
635    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
636        formatter.write_str("string-encoded decimal")
637    }
638
639    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
640    where
641        E: de::Error,
642    {
643        match Decimal::from_str(v) {
644            Ok(d) => Ok(d),
645            Err(e) => Err(E::custom(format!("Error parsing decimal '{}': {}", v, e))),
646        }
647    }
648}
649
650impl PartialEq<&Decimal> for Decimal {
651    fn eq(&self, rhs: &&Decimal) -> bool {
652        self == *rhs
653    }
654}
655
656impl PartialEq<Decimal> for &Decimal {
657    fn eq(&self, rhs: &Decimal) -> bool {
658        *self == rhs
659    }
660}
661
662#[cfg(test)]
663mod tests {
664    use super::*;
665    use crate::{from_slice, to_vec};
666
667    fn dec(input: &str) -> Decimal {
668        Decimal::from_str(input).unwrap()
669    }
670
671    #[test]
672    fn decimal_new() {
673        let expected = Uint128::from(300u128);
674        assert_eq!(Decimal::new(expected).0, expected);
675    }
676
677    #[test]
678    fn decimal_raw() {
679        let value = 300u128;
680        assert_eq!(Decimal::raw(value).0.u128(), value);
681    }
682
683    #[test]
684    fn decimal_one() {
685        let value = Decimal::one();
686        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL);
687    }
688
689    #[test]
690    fn decimal_zero() {
691        let value = Decimal::zero();
692        assert!(value.0.is_zero());
693    }
694
695    #[test]
696    fn decimal_percent() {
697        let value = Decimal::percent(50);
698        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
699    }
700
701    #[test]
702    fn decimal_permille() {
703        let value = Decimal::permille(125);
704        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(8u8));
705    }
706
707    #[test]
708    fn decimal_from_atomics_works() {
709        let one = Decimal::one();
710        let two = one + one;
711
712        assert_eq!(Decimal::from_atomics(1u128, 0).unwrap(), one);
713        assert_eq!(Decimal::from_atomics(10u128, 1).unwrap(), one);
714        assert_eq!(Decimal::from_atomics(100u128, 2).unwrap(), one);
715        assert_eq!(Decimal::from_atomics(1000u128, 3).unwrap(), one);
716        assert_eq!(
717            Decimal::from_atomics(1000000000000000000u128, 18).unwrap(),
718            one
719        );
720        assert_eq!(
721            Decimal::from_atomics(10000000000000000000u128, 19).unwrap(),
722            one
723        );
724        assert_eq!(
725            Decimal::from_atomics(100000000000000000000u128, 20).unwrap(),
726            one
727        );
728
729        assert_eq!(Decimal::from_atomics(2u128, 0).unwrap(), two);
730        assert_eq!(Decimal::from_atomics(20u128, 1).unwrap(), two);
731        assert_eq!(Decimal::from_atomics(200u128, 2).unwrap(), two);
732        assert_eq!(Decimal::from_atomics(2000u128, 3).unwrap(), two);
733        assert_eq!(
734            Decimal::from_atomics(2000000000000000000u128, 18).unwrap(),
735            two
736        );
737        assert_eq!(
738            Decimal::from_atomics(20000000000000000000u128, 19).unwrap(),
739            two
740        );
741        assert_eq!(
742            Decimal::from_atomics(200000000000000000000u128, 20).unwrap(),
743            two
744        );
745
746        // Cuts decimal digits (20 provided but only 18 can be stored)
747        assert_eq!(
748            Decimal::from_atomics(4321u128, 20).unwrap(),
749            Decimal::from_str("0.000000000000000043").unwrap()
750        );
751        assert_eq!(
752            Decimal::from_atomics(6789u128, 20).unwrap(),
753            Decimal::from_str("0.000000000000000067").unwrap()
754        );
755        assert_eq!(
756            Decimal::from_atomics(u128::MAX, 38).unwrap(),
757            Decimal::from_str("3.402823669209384634").unwrap()
758        );
759        assert_eq!(
760            Decimal::from_atomics(u128::MAX, 39).unwrap(),
761            Decimal::from_str("0.340282366920938463").unwrap()
762        );
763        assert_eq!(
764            Decimal::from_atomics(u128::MAX, 45).unwrap(),
765            Decimal::from_str("0.000000340282366920").unwrap()
766        );
767        assert_eq!(
768            Decimal::from_atomics(u128::MAX, 51).unwrap(),
769            Decimal::from_str("0.000000000000340282").unwrap()
770        );
771        assert_eq!(
772            Decimal::from_atomics(u128::MAX, 56).unwrap(),
773            Decimal::from_str("0.000000000000000003").unwrap()
774        );
775        assert_eq!(
776            Decimal::from_atomics(u128::MAX, 57).unwrap(),
777            Decimal::from_str("0.000000000000000000").unwrap()
778        );
779        assert_eq!(
780            Decimal::from_atomics(u128::MAX, u32::MAX).unwrap(),
781            Decimal::from_str("0.000000000000000000").unwrap()
782        );
783
784        // Can be used with max value
785        let max = Decimal::MAX;
786        assert_eq!(
787            Decimal::from_atomics(max.atomics(), max.decimal_places()).unwrap(),
788            max
789        );
790
791        // Overflow is only possible with digits < 18
792        let result = Decimal::from_atomics(u128::MAX, 17);
793        assert_eq!(result.unwrap_err(), DecimalRangeExceeded);
794    }
795
796    #[test]
797    fn decimal_from_ratio_works() {
798        // 1.0
799        assert_eq!(Decimal::from_ratio(1u128, 1u128), Decimal::one());
800        assert_eq!(Decimal::from_ratio(53u128, 53u128), Decimal::one());
801        assert_eq!(Decimal::from_ratio(125u128, 125u128), Decimal::one());
802
803        // 1.5
804        assert_eq!(Decimal::from_ratio(3u128, 2u128), Decimal::percent(150));
805        assert_eq!(Decimal::from_ratio(150u128, 100u128), Decimal::percent(150));
806        assert_eq!(Decimal::from_ratio(333u128, 222u128), Decimal::percent(150));
807
808        // 0.125
809        assert_eq!(Decimal::from_ratio(1u64, 8u64), Decimal::permille(125));
810        assert_eq!(Decimal::from_ratio(125u64, 1000u64), Decimal::permille(125));
811
812        // 1/3 (result floored)
813        assert_eq!(
814            Decimal::from_ratio(1u64, 3u64),
815            Decimal(Uint128::from(333_333_333_333_333_333u128))
816        );
817
818        // 2/3 (result floored)
819        assert_eq!(
820            Decimal::from_ratio(2u64, 3u64),
821            Decimal(Uint128::from(666_666_666_666_666_666u128))
822        );
823
824        // large inputs
825        assert_eq!(Decimal::from_ratio(0u128, u128::MAX), Decimal::zero());
826        assert_eq!(Decimal::from_ratio(u128::MAX, u128::MAX), Decimal::one());
827        // 340282366920938463463 is the largest integer <= Decimal::MAX
828        assert_eq!(
829            Decimal::from_ratio(340282366920938463463u128, 1u128),
830            Decimal::from_str("340282366920938463463").unwrap()
831        );
832    }
833
834    #[test]
835    #[should_panic(expected = "Denominator must not be zero")]
836    fn decimal_from_ratio_panics_for_zero_denominator() {
837        Decimal::from_ratio(1u128, 0u128);
838    }
839
840    #[test]
841    #[should_panic(expected = "Multiplication overflow")]
842    fn decimal_from_ratio_panics_for_mul_overflow() {
843        Decimal::from_ratio(u128::MAX, 1u128);
844    }
845
846    #[test]
847    fn decimal_checked_from_ratio_does_not_panic() {
848        assert_eq!(
849            Decimal::checked_from_ratio(1u128, 0u128),
850            Err(CheckedFromRatioError::DivideByZero)
851        );
852
853        assert_eq!(
854            Decimal::checked_from_ratio(u128::MAX, 1u128),
855            Err(CheckedFromRatioError::Overflow)
856        );
857    }
858
859    #[test]
860    fn decimal_implements_fraction() {
861        let fraction = Decimal::from_str("1234.567").unwrap();
862        assert_eq!(
863            fraction.numerator(),
864            Uint128::from(1_234_567_000_000_000_000_000u128)
865        );
866        assert_eq!(
867            fraction.denominator(),
868            Uint128::from(1_000_000_000_000_000_000u128)
869        );
870    }
871
872    #[test]
873    fn decimal_from_str_works() {
874        // Integers
875        assert_eq!(Decimal::from_str("0").unwrap(), Decimal::percent(0));
876        assert_eq!(Decimal::from_str("1").unwrap(), Decimal::percent(100));
877        assert_eq!(Decimal::from_str("5").unwrap(), Decimal::percent(500));
878        assert_eq!(Decimal::from_str("42").unwrap(), Decimal::percent(4200));
879        assert_eq!(Decimal::from_str("000").unwrap(), Decimal::percent(0));
880        assert_eq!(Decimal::from_str("001").unwrap(), Decimal::percent(100));
881        assert_eq!(Decimal::from_str("005").unwrap(), Decimal::percent(500));
882        assert_eq!(Decimal::from_str("0042").unwrap(), Decimal::percent(4200));
883
884        // Decimals
885        assert_eq!(Decimal::from_str("1.0").unwrap(), Decimal::percent(100));
886        assert_eq!(Decimal::from_str("1.5").unwrap(), Decimal::percent(150));
887        assert_eq!(Decimal::from_str("0.5").unwrap(), Decimal::percent(50));
888        assert_eq!(Decimal::from_str("0.123").unwrap(), Decimal::permille(123));
889
890        assert_eq!(Decimal::from_str("40.00").unwrap(), Decimal::percent(4000));
891        assert_eq!(Decimal::from_str("04.00").unwrap(), Decimal::percent(400));
892        assert_eq!(Decimal::from_str("00.40").unwrap(), Decimal::percent(40));
893        assert_eq!(Decimal::from_str("00.04").unwrap(), Decimal::percent(4));
894
895        // Can handle DECIMAL_PLACES fractional digits
896        assert_eq!(
897            Decimal::from_str("7.123456789012345678").unwrap(),
898            Decimal(Uint128::from(7123456789012345678u128))
899        );
900        assert_eq!(
901            Decimal::from_str("7.999999999999999999").unwrap(),
902            Decimal(Uint128::from(7999999999999999999u128))
903        );
904
905        // Works for documented max value
906        assert_eq!(
907            Decimal::from_str("340282366920938463463.374607431768211455").unwrap(),
908            Decimal::MAX
909        );
910    }
911
912    #[test]
913    fn decimal_from_str_errors_for_broken_whole_part() {
914        match Decimal::from_str("").unwrap_err() {
915            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
916            e => panic!("Unexpected error: {:?}", e),
917        }
918
919        match Decimal::from_str(" ").unwrap_err() {
920            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
921            e => panic!("Unexpected error: {:?}", e),
922        }
923
924        match Decimal::from_str("-1").unwrap_err() {
925            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing whole"),
926            e => panic!("Unexpected error: {:?}", e),
927        }
928    }
929
930    #[test]
931    fn decimal_from_str_errors_for_broken_fractinal_part() {
932        match Decimal::from_str("1.").unwrap_err() {
933            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
934            e => panic!("Unexpected error: {:?}", e),
935        }
936
937        match Decimal::from_str("1. ").unwrap_err() {
938            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
939            e => panic!("Unexpected error: {:?}", e),
940        }
941
942        match Decimal::from_str("1.e").unwrap_err() {
943            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
944            e => panic!("Unexpected error: {:?}", e),
945        }
946
947        match Decimal::from_str("1.2e3").unwrap_err() {
948            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Error parsing fractional"),
949            e => panic!("Unexpected error: {:?}", e),
950        }
951    }
952
953    #[test]
954    fn decimal_from_str_errors_for_more_than_18_fractional_digits() {
955        match Decimal::from_str("7.1234567890123456789").unwrap_err() {
956            StdError::GenericErr { msg, .. } => {
957                assert_eq!(msg, "Cannot parse more than 18 fractional digits",)
958            }
959            e => panic!("Unexpected error: {:?}", e),
960        }
961
962        // No special rules for trailing zeros. This could be changed but adds gas cost for the happy path.
963        match Decimal::from_str("7.1230000000000000000").unwrap_err() {
964            StdError::GenericErr { msg, .. } => {
965                assert_eq!(msg, "Cannot parse more than 18 fractional digits")
966            }
967            e => panic!("Unexpected error: {:?}", e),
968        }
969    }
970
971    #[test]
972    fn decimal_from_str_errors_for_invalid_number_of_dots() {
973        match Decimal::from_str("1.2.3").unwrap_err() {
974            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
975            e => panic!("Unexpected error: {:?}", e),
976        }
977
978        match Decimal::from_str("1.2.3.4").unwrap_err() {
979            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Unexpected number of dots"),
980            e => panic!("Unexpected error: {:?}", e),
981        }
982    }
983
984    #[test]
985    fn decimal_from_str_errors_for_more_than_max_value() {
986        // Integer
987        match Decimal::from_str("340282366920938463464").unwrap_err() {
988            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
989            e => panic!("Unexpected error: {:?}", e),
990        }
991
992        // Decimal
993        match Decimal::from_str("340282366920938463464.0").unwrap_err() {
994            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
995            e => panic!("Unexpected error: {:?}", e),
996        }
997        match Decimal::from_str("340282366920938463463.374607431768211456").unwrap_err() {
998            StdError::GenericErr { msg, .. } => assert_eq!(msg, "Value too big"),
999            e => panic!("Unexpected error: {:?}", e),
1000        }
1001    }
1002
1003    #[test]
1004    fn decimal_atomics_works() {
1005        let zero = Decimal::zero();
1006        let one = Decimal::one();
1007        let half = Decimal::percent(50);
1008        let two = Decimal::percent(200);
1009        let max = Decimal::MAX;
1010
1011        assert_eq!(zero.atomics(), Uint128::new(0));
1012        assert_eq!(one.atomics(), Uint128::new(1000000000000000000));
1013        assert_eq!(half.atomics(), Uint128::new(500000000000000000));
1014        assert_eq!(two.atomics(), Uint128::new(2000000000000000000));
1015        assert_eq!(max.atomics(), Uint128::MAX);
1016    }
1017
1018    #[test]
1019    fn decimal_decimal_places_works() {
1020        let zero = Decimal::zero();
1021        let one = Decimal::one();
1022        let half = Decimal::percent(50);
1023        let two = Decimal::percent(200);
1024        let max = Decimal::MAX;
1025
1026        assert_eq!(zero.decimal_places(), 18);
1027        assert_eq!(one.decimal_places(), 18);
1028        assert_eq!(half.decimal_places(), 18);
1029        assert_eq!(two.decimal_places(), 18);
1030        assert_eq!(max.decimal_places(), 18);
1031    }
1032
1033    #[test]
1034    fn decimal_is_zero_works() {
1035        assert!(Decimal::zero().is_zero());
1036        assert!(Decimal::percent(0).is_zero());
1037        assert!(Decimal::permille(0).is_zero());
1038
1039        assert!(!Decimal::one().is_zero());
1040        assert!(!Decimal::percent(123).is_zero());
1041        assert!(!Decimal::permille(1234).is_zero());
1042    }
1043
1044    #[test]
1045    fn decimal_inv_works() {
1046        // d = 0
1047        assert_eq!(Decimal::zero().inv(), None);
1048
1049        // d == 1
1050        assert_eq!(Decimal::one().inv(), Some(Decimal::one()));
1051
1052        // d > 1 exact
1053        assert_eq!(
1054            Decimal::from_str("2").unwrap().inv(),
1055            Some(Decimal::from_str("0.5").unwrap())
1056        );
1057        assert_eq!(
1058            Decimal::from_str("20").unwrap().inv(),
1059            Some(Decimal::from_str("0.05").unwrap())
1060        );
1061        assert_eq!(
1062            Decimal::from_str("200").unwrap().inv(),
1063            Some(Decimal::from_str("0.005").unwrap())
1064        );
1065        assert_eq!(
1066            Decimal::from_str("2000").unwrap().inv(),
1067            Some(Decimal::from_str("0.0005").unwrap())
1068        );
1069
1070        // d > 1 rounded
1071        assert_eq!(
1072            Decimal::from_str("3").unwrap().inv(),
1073            Some(Decimal::from_str("0.333333333333333333").unwrap())
1074        );
1075        assert_eq!(
1076            Decimal::from_str("6").unwrap().inv(),
1077            Some(Decimal::from_str("0.166666666666666666").unwrap())
1078        );
1079
1080        // d < 1 exact
1081        assert_eq!(
1082            Decimal::from_str("0.5").unwrap().inv(),
1083            Some(Decimal::from_str("2").unwrap())
1084        );
1085        assert_eq!(
1086            Decimal::from_str("0.05").unwrap().inv(),
1087            Some(Decimal::from_str("20").unwrap())
1088        );
1089        assert_eq!(
1090            Decimal::from_str("0.005").unwrap().inv(),
1091            Some(Decimal::from_str("200").unwrap())
1092        );
1093        assert_eq!(
1094            Decimal::from_str("0.0005").unwrap().inv(),
1095            Some(Decimal::from_str("2000").unwrap())
1096        );
1097    }
1098
1099    #[test]
1100    #[allow(clippy::op_ref)]
1101    fn decimal_add_works() {
1102        let value = Decimal::one() + Decimal::percent(50); // 1.5
1103        assert_eq!(
1104            value.0,
1105            Decimal::DECIMAL_FRACTIONAL * Uint128::from(3u8) / Uint128::from(2u8)
1106        );
1107
1108        assert_eq!(
1109            Decimal::percent(5) + Decimal::percent(4),
1110            Decimal::percent(9)
1111        );
1112        assert_eq!(Decimal::percent(5) + Decimal::zero(), Decimal::percent(5));
1113        assert_eq!(Decimal::zero() + Decimal::zero(), Decimal::zero());
1114
1115        // works for refs
1116        let a = Decimal::percent(15);
1117        let b = Decimal::percent(25);
1118        let expected = Decimal::percent(40);
1119        assert_eq!(a + b, expected);
1120        assert_eq!(&a + b, expected);
1121        assert_eq!(a + &b, expected);
1122        assert_eq!(&a + &b, expected);
1123    }
1124
1125    #[test]
1126    #[should_panic(expected = "attempt to add with overflow")]
1127    fn decimal_add_overflow_panics() {
1128        let _value = Decimal::MAX + Decimal::percent(50);
1129    }
1130
1131    #[test]
1132    fn decimal_add_assign_works() {
1133        let mut a = Decimal::percent(30);
1134        a += Decimal::percent(20);
1135        assert_eq!(a, Decimal::percent(50));
1136
1137        // works for refs
1138        let mut a = Decimal::percent(15);
1139        let b = Decimal::percent(3);
1140        let expected = Decimal::percent(18);
1141        a += &b;
1142        assert_eq!(a, expected);
1143    }
1144
1145    #[test]
1146    #[allow(clippy::op_ref)]
1147    fn decimal_sub_works() {
1148        let value = Decimal::one() - Decimal::percent(50); // 0.5
1149        assert_eq!(value.0, Decimal::DECIMAL_FRACTIONAL / Uint128::from(2u8));
1150
1151        assert_eq!(
1152            Decimal::percent(9) - Decimal::percent(4),
1153            Decimal::percent(5)
1154        );
1155        assert_eq!(Decimal::percent(16) - Decimal::zero(), Decimal::percent(16));
1156        assert_eq!(Decimal::percent(16) - Decimal::percent(16), Decimal::zero());
1157        assert_eq!(Decimal::zero() - Decimal::zero(), Decimal::zero());
1158
1159        // works for refs
1160        let a = Decimal::percent(13);
1161        let b = Decimal::percent(6);
1162        let expected = Decimal::percent(7);
1163        assert_eq!(a - b, expected);
1164        assert_eq!(&a - b, expected);
1165        assert_eq!(a - &b, expected);
1166        assert_eq!(&a - &b, expected);
1167    }
1168
1169    #[test]
1170    #[should_panic(expected = "attempt to subtract with overflow")]
1171    fn decimal_sub_overflow_panics() {
1172        let _value = Decimal::zero() - Decimal::percent(50);
1173    }
1174
1175    #[test]
1176    fn decimal_sub_assign_works() {
1177        let mut a = Decimal::percent(20);
1178        a -= Decimal::percent(2);
1179        assert_eq!(a, Decimal::percent(18));
1180
1181        // works for refs
1182        let mut a = Decimal::percent(33);
1183        let b = Decimal::percent(13);
1184        let expected = Decimal::percent(20);
1185        a -= &b;
1186        assert_eq!(a, expected);
1187    }
1188
1189    #[test]
1190    #[allow(clippy::op_ref)]
1191    fn decimal_implements_mul() {
1192        let one = Decimal::one();
1193        let two = one + one;
1194        let half = Decimal::percent(50);
1195
1196        // 1*x and x*1
1197        assert_eq!(one * Decimal::percent(0), Decimal::percent(0));
1198        assert_eq!(one * Decimal::percent(1), Decimal::percent(1));
1199        assert_eq!(one * Decimal::percent(10), Decimal::percent(10));
1200        assert_eq!(one * Decimal::percent(100), Decimal::percent(100));
1201        assert_eq!(one * Decimal::percent(1000), Decimal::percent(1000));
1202        assert_eq!(one * Decimal::MAX, Decimal::MAX);
1203        assert_eq!(Decimal::percent(0) * one, Decimal::percent(0));
1204        assert_eq!(Decimal::percent(1) * one, Decimal::percent(1));
1205        assert_eq!(Decimal::percent(10) * one, Decimal::percent(10));
1206        assert_eq!(Decimal::percent(100) * one, Decimal::percent(100));
1207        assert_eq!(Decimal::percent(1000) * one, Decimal::percent(1000));
1208        assert_eq!(Decimal::MAX * one, Decimal::MAX);
1209
1210        // double
1211        assert_eq!(two * Decimal::percent(0), Decimal::percent(0));
1212        assert_eq!(two * Decimal::percent(1), Decimal::percent(2));
1213        assert_eq!(two * Decimal::percent(10), Decimal::percent(20));
1214        assert_eq!(two * Decimal::percent(100), Decimal::percent(200));
1215        assert_eq!(two * Decimal::percent(1000), Decimal::percent(2000));
1216        assert_eq!(Decimal::percent(0) * two, Decimal::percent(0));
1217        assert_eq!(Decimal::percent(1) * two, Decimal::percent(2));
1218        assert_eq!(Decimal::percent(10) * two, Decimal::percent(20));
1219        assert_eq!(Decimal::percent(100) * two, Decimal::percent(200));
1220        assert_eq!(Decimal::percent(1000) * two, Decimal::percent(2000));
1221
1222        // half
1223        assert_eq!(half * Decimal::percent(0), Decimal::percent(0));
1224        assert_eq!(half * Decimal::percent(1), Decimal::permille(5));
1225        assert_eq!(half * Decimal::percent(10), Decimal::percent(5));
1226        assert_eq!(half * Decimal::percent(100), Decimal::percent(50));
1227        assert_eq!(half * Decimal::percent(1000), Decimal::percent(500));
1228        assert_eq!(Decimal::percent(0) * half, Decimal::percent(0));
1229        assert_eq!(Decimal::percent(1) * half, Decimal::permille(5));
1230        assert_eq!(Decimal::percent(10) * half, Decimal::percent(5));
1231        assert_eq!(Decimal::percent(100) * half, Decimal::percent(50));
1232        assert_eq!(Decimal::percent(1000) * half, Decimal::percent(500));
1233
1234        // Move left
1235        let a = dec("123.127726548762582");
1236        assert_eq!(a * dec("1"), dec("123.127726548762582"));
1237        assert_eq!(a * dec("10"), dec("1231.27726548762582"));
1238        assert_eq!(a * dec("100"), dec("12312.7726548762582"));
1239        assert_eq!(a * dec("1000"), dec("123127.726548762582"));
1240        assert_eq!(a * dec("1000000"), dec("123127726.548762582"));
1241        assert_eq!(a * dec("1000000000"), dec("123127726548.762582"));
1242        assert_eq!(a * dec("1000000000000"), dec("123127726548762.582"));
1243        assert_eq!(a * dec("1000000000000000"), dec("123127726548762582"));
1244        assert_eq!(a * dec("1000000000000000000"), dec("123127726548762582000"));
1245        assert_eq!(dec("1") * a, dec("123.127726548762582"));
1246        assert_eq!(dec("10") * a, dec("1231.27726548762582"));
1247        assert_eq!(dec("100") * a, dec("12312.7726548762582"));
1248        assert_eq!(dec("1000") * a, dec("123127.726548762582"));
1249        assert_eq!(dec("1000000") * a, dec("123127726.548762582"));
1250        assert_eq!(dec("1000000000") * a, dec("123127726548.762582"));
1251        assert_eq!(dec("1000000000000") * a, dec("123127726548762.582"));
1252        assert_eq!(dec("1000000000000000") * a, dec("123127726548762582"));
1253        assert_eq!(dec("1000000000000000000") * a, dec("123127726548762582000"));
1254
1255        // Move right
1256        let max = Decimal::MAX;
1257        assert_eq!(
1258            max * dec("1.0"),
1259            dec("340282366920938463463.374607431768211455")
1260        );
1261        assert_eq!(
1262            max * dec("0.1"),
1263            dec("34028236692093846346.337460743176821145")
1264        );
1265        assert_eq!(
1266            max * dec("0.01"),
1267            dec("3402823669209384634.633746074317682114")
1268        );
1269        assert_eq!(
1270            max * dec("0.001"),
1271            dec("340282366920938463.463374607431768211")
1272        );
1273        assert_eq!(
1274            max * dec("0.000001"),
1275            dec("340282366920938.463463374607431768")
1276        );
1277        assert_eq!(
1278            max * dec("0.000000001"),
1279            dec("340282366920.938463463374607431")
1280        );
1281        assert_eq!(
1282            max * dec("0.000000000001"),
1283            dec("340282366.920938463463374607")
1284        );
1285        assert_eq!(
1286            max * dec("0.000000000000001"),
1287            dec("340282.366920938463463374")
1288        );
1289        assert_eq!(
1290            max * dec("0.000000000000000001"),
1291            dec("340.282366920938463463")
1292        );
1293
1294        // works for refs
1295        let a = Decimal::percent(20);
1296        let b = Decimal::percent(30);
1297        let expected = Decimal::percent(6);
1298        assert_eq!(a * b, expected);
1299        assert_eq!(&a * b, expected);
1300        assert_eq!(a * &b, expected);
1301        assert_eq!(&a * &b, expected);
1302    }
1303
1304    #[test]
1305    fn decimal_mul_assign_works() {
1306        let mut a = Decimal::percent(15);
1307        a *= Decimal::percent(60);
1308        assert_eq!(a, Decimal::percent(9));
1309
1310        // works for refs
1311        let mut a = Decimal::percent(50);
1312        let b = Decimal::percent(20);
1313        a *= &b;
1314        assert_eq!(a, Decimal::percent(10));
1315    }
1316
1317    #[test]
1318    #[should_panic(expected = "attempt to multiply with overflow")]
1319    fn decimal_mul_overflow_panics() {
1320        let _value = Decimal::MAX * Decimal::percent(101);
1321    }
1322
1323    #[test]
1324    fn decimal_checked_mul() {
1325        let test_data = [
1326            (Decimal::zero(), Decimal::zero()),
1327            (Decimal::zero(), Decimal::one()),
1328            (Decimal::one(), Decimal::zero()),
1329            (Decimal::percent(10), Decimal::zero()),
1330            (Decimal::percent(10), Decimal::percent(5)),
1331            (Decimal::MAX, Decimal::one()),
1332            (Decimal::MAX / Uint128::new(2), Decimal::percent(200)),
1333            (Decimal::permille(6), Decimal::permille(13)),
1334        ];
1335
1336        // The regular std::ops::Mul is our source of truth for these tests.
1337        for (x, y) in test_data.into_iter() {
1338            assert_eq!(x * y, x.checked_mul(y).unwrap());
1339        }
1340    }
1341
1342    #[test]
1343    fn decimal_checked_mul_overflow() {
1344        assert_eq!(
1345            Decimal::MAX.checked_mul(Decimal::percent(200)),
1346            Err(OverflowError {
1347                operation: crate::OverflowOperation::Mul,
1348                operand1: Decimal::MAX.to_string(),
1349                operand2: Decimal::percent(200).to_string(),
1350            })
1351        );
1352    }
1353
1354    #[test]
1355    // in this test the Decimal is on the right
1356    fn uint128_decimal_multiply() {
1357        // a*b
1358        let left = Uint128::new(300);
1359        let right = Decimal::one() + Decimal::percent(50); // 1.5
1360        assert_eq!(left * right, Uint128::new(450));
1361
1362        // a*0
1363        let left = Uint128::new(300);
1364        let right = Decimal::zero();
1365        assert_eq!(left * right, Uint128::new(0));
1366
1367        // 0*a
1368        let left = Uint128::new(0);
1369        let right = Decimal::one() + Decimal::percent(50); // 1.5
1370        assert_eq!(left * right, Uint128::new(0));
1371    }
1372
1373    #[test]
1374    // in this test the Decimal is on the left
1375    fn decimal_uint128_multiply() {
1376        // a*b
1377        let left = Decimal::one() + Decimal::percent(50); // 1.5
1378        let right = Uint128::new(300);
1379        assert_eq!(left * right, Uint128::new(450));
1380
1381        // 0*a
1382        let left = Decimal::zero();
1383        let right = Uint128::new(300);
1384        assert_eq!(left * right, Uint128::new(0));
1385
1386        // a*0
1387        let left = Decimal::one() + Decimal::percent(50); // 1.5
1388        let right = Uint128::new(0);
1389        assert_eq!(left * right, Uint128::new(0));
1390    }
1391
1392    #[test]
1393    #[allow(clippy::op_ref)]
1394    fn decimal_implements_div() {
1395        let one = Decimal::one();
1396        let two = one + one;
1397        let half = Decimal::percent(50);
1398
1399        // 1/x and x/1
1400        assert_eq!(one / Decimal::percent(1), Decimal::percent(10_000));
1401        assert_eq!(one / Decimal::percent(10), Decimal::percent(1_000));
1402        assert_eq!(one / Decimal::percent(100), Decimal::percent(100));
1403        assert_eq!(one / Decimal::percent(1000), Decimal::percent(10));
1404        assert_eq!(Decimal::percent(0) / one, Decimal::percent(0));
1405        assert_eq!(Decimal::percent(1) / one, Decimal::percent(1));
1406        assert_eq!(Decimal::percent(10) / one, Decimal::percent(10));
1407        assert_eq!(Decimal::percent(100) / one, Decimal::percent(100));
1408        assert_eq!(Decimal::percent(1000) / one, Decimal::percent(1000));
1409
1410        // double
1411        assert_eq!(two / Decimal::percent(1), Decimal::percent(20_000));
1412        assert_eq!(two / Decimal::percent(10), Decimal::percent(2_000));
1413        assert_eq!(two / Decimal::percent(100), Decimal::percent(200));
1414        assert_eq!(two / Decimal::percent(1000), Decimal::percent(20));
1415        assert_eq!(Decimal::percent(0) / two, Decimal::percent(0));
1416        assert_eq!(Decimal::percent(1) / two, dec("0.005"));
1417        assert_eq!(Decimal::percent(10) / two, Decimal::percent(5));
1418        assert_eq!(Decimal::percent(100) / two, Decimal::percent(50));
1419        assert_eq!(Decimal::percent(1000) / two, Decimal::percent(500));
1420
1421        // half
1422        assert_eq!(half / Decimal::percent(1), Decimal::percent(5_000));
1423        assert_eq!(half / Decimal::percent(10), Decimal::percent(500));
1424        assert_eq!(half / Decimal::percent(100), Decimal::percent(50));
1425        assert_eq!(half / Decimal::percent(1000), Decimal::percent(5));
1426        assert_eq!(Decimal::percent(0) / half, Decimal::percent(0));
1427        assert_eq!(Decimal::percent(1) / half, Decimal::percent(2));
1428        assert_eq!(Decimal::percent(10) / half, Decimal::percent(20));
1429        assert_eq!(Decimal::percent(100) / half, Decimal::percent(200));
1430        assert_eq!(Decimal::percent(1000) / half, Decimal::percent(2000));
1431
1432        // Move right
1433        let a = dec("123127726548762582");
1434        assert_eq!(a / dec("1"), dec("123127726548762582"));
1435        assert_eq!(a / dec("10"), dec("12312772654876258.2"));
1436        assert_eq!(a / dec("100"), dec("1231277265487625.82"));
1437        assert_eq!(a / dec("1000"), dec("123127726548762.582"));
1438        assert_eq!(a / dec("1000000"), dec("123127726548.762582"));
1439        assert_eq!(a / dec("1000000000"), dec("123127726.548762582"));
1440        assert_eq!(a / dec("1000000000000"), dec("123127.726548762582"));
1441        assert_eq!(a / dec("1000000000000000"), dec("123.127726548762582"));
1442        assert_eq!(a / dec("1000000000000000000"), dec("0.123127726548762582"));
1443        assert_eq!(dec("1") / a, dec("0.000000000000000008"));
1444        assert_eq!(dec("10") / a, dec("0.000000000000000081"));
1445        assert_eq!(dec("100") / a, dec("0.000000000000000812"));
1446        assert_eq!(dec("1000") / a, dec("0.000000000000008121"));
1447        assert_eq!(dec("1000000") / a, dec("0.000000000008121647"));
1448        assert_eq!(dec("1000000000") / a, dec("0.000000008121647560"));
1449        assert_eq!(dec("1000000000000") / a, dec("0.000008121647560868"));
1450        assert_eq!(dec("1000000000000000") / a, dec("0.008121647560868164"));
1451        assert_eq!(dec("1000000000000000000") / a, dec("8.121647560868164773"));
1452
1453        // Move left
1454        let a = dec("0.123127726548762582");
1455        assert_eq!(a / dec("1.0"), dec("0.123127726548762582"));
1456        assert_eq!(a / dec("0.1"), dec("1.23127726548762582"));
1457        assert_eq!(a / dec("0.01"), dec("12.3127726548762582"));
1458        assert_eq!(a / dec("0.001"), dec("123.127726548762582"));
1459        assert_eq!(a / dec("0.000001"), dec("123127.726548762582"));
1460        assert_eq!(a / dec("0.000000001"), dec("123127726.548762582"));
1461        assert_eq!(a / dec("0.000000000001"), dec("123127726548.762582"));
1462        assert_eq!(a / dec("0.000000000000001"), dec("123127726548762.582"));
1463        assert_eq!(a / dec("0.000000000000000001"), dec("123127726548762582"));
1464
1465        assert_eq!(
1466            Decimal::percent(15) / Decimal::percent(60),
1467            Decimal::percent(25)
1468        );
1469
1470        // works for refs
1471        let a = Decimal::percent(100);
1472        let b = Decimal::percent(20);
1473        let expected = Decimal::percent(500);
1474        assert_eq!(a / b, expected);
1475        assert_eq!(&a / b, expected);
1476        assert_eq!(a / &b, expected);
1477        assert_eq!(&a / &b, expected);
1478    }
1479
1480    #[test]
1481    fn decimal_div_assign_works() {
1482        let mut a = Decimal::percent(15);
1483        a /= Decimal::percent(20);
1484        assert_eq!(a, Decimal::percent(75));
1485
1486        // works for refs
1487        let mut a = Decimal::percent(50);
1488        let b = Decimal::percent(20);
1489        a /= &b;
1490        assert_eq!(a, Decimal::percent(250));
1491    }
1492
1493    #[test]
1494    #[should_panic(expected = "Division failed - multiplication overflow")]
1495    fn decimal_div_overflow_panics() {
1496        let _value = Decimal::MAX / Decimal::percent(10);
1497    }
1498
1499    #[test]
1500    #[should_panic(expected = "Division failed - denominator must not be zero")]
1501    fn decimal_div_by_zero_panics() {
1502        let _value = Decimal::one() / Decimal::zero();
1503    }
1504
1505    #[test]
1506    fn decimal_uint128_division() {
1507        // a/b
1508        let left = Decimal::percent(150); // 1.5
1509        let right = Uint128::new(3);
1510        assert_eq!(left / right, Decimal::percent(50));
1511
1512        // 0/a
1513        let left = Decimal::zero();
1514        let right = Uint128::new(300);
1515        assert_eq!(left / right, Decimal::zero());
1516    }
1517
1518    #[test]
1519    #[should_panic(expected = "attempt to divide by zero")]
1520    fn decimal_uint128_divide_by_zero() {
1521        let left = Decimal::percent(150); // 1.5
1522        let right = Uint128::new(0);
1523        let _result = left / right;
1524    }
1525
1526    #[test]
1527    fn decimal_uint128_div_assign() {
1528        // a/b
1529        let mut dec = Decimal::percent(150); // 1.5
1530        dec /= Uint128::new(3);
1531        assert_eq!(dec, Decimal::percent(50));
1532
1533        // 0/a
1534        let mut dec = Decimal::zero();
1535        dec /= Uint128::new(300);
1536        assert_eq!(dec, Decimal::zero());
1537    }
1538
1539    #[test]
1540    #[should_panic(expected = "attempt to divide by zero")]
1541    fn decimal_uint128_div_assign_by_zero() {
1542        // a/0
1543        let mut dec = Decimal::percent(50);
1544        dec /= Uint128::new(0);
1545    }
1546
1547    #[test]
1548    fn decimal_uint128_sqrt() {
1549        assert_eq!(Decimal::percent(900).sqrt(), Decimal::percent(300));
1550
1551        assert!(Decimal::percent(316) < Decimal::percent(1000).sqrt());
1552        assert!(Decimal::percent(1000).sqrt() < Decimal::percent(317));
1553    }
1554
1555    /// sqrt(2) is an irrational number, i.e. all 18 decimal places should be used.
1556    #[test]
1557    fn decimal_uint128_sqrt_is_precise() {
1558        assert_eq!(
1559            Decimal::from_str("2").unwrap().sqrt(),
1560            Decimal::from_str("1.414213562373095048").unwrap() // https://www.wolframalpha.com/input/?i=sqrt%282%29
1561        );
1562    }
1563
1564    #[test]
1565    fn decimal_uint128_sqrt_does_not_overflow() {
1566        assert_eq!(
1567            Decimal::from_str("400").unwrap().sqrt(),
1568            Decimal::from_str("20").unwrap()
1569        );
1570    }
1571
1572    #[test]
1573    fn decimal_uint128_sqrt_intermediate_precision_used() {
1574        assert_eq!(
1575            Decimal::from_str("400001").unwrap().sqrt(),
1576            // The last two digits (27) are truncated below due to the algorithm
1577            // we use. Larger numbers will cause less precision.
1578            // https://www.wolframalpha.com/input/?i=sqrt%28400001%29
1579            Decimal::from_str("632.456322602596803200").unwrap()
1580        );
1581    }
1582
1583    #[test]
1584    fn decimal_checked_pow() {
1585        for exp in 0..10 {
1586            assert_eq!(Decimal::one().checked_pow(exp).unwrap(), Decimal::one());
1587        }
1588
1589        // This case is mathematically undefined but we ensure consistency with Rust stdandard types
1590        // https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=20df6716048e77087acd40194b233494
1591        assert_eq!(Decimal::zero().checked_pow(0).unwrap(), Decimal::one());
1592
1593        for exp in 1..10 {
1594            assert_eq!(Decimal::zero().checked_pow(exp).unwrap(), Decimal::zero());
1595        }
1596
1597        for num in &[
1598            Decimal::percent(50),
1599            Decimal::percent(99),
1600            Decimal::percent(200),
1601        ] {
1602            assert_eq!(num.checked_pow(0).unwrap(), Decimal::one())
1603        }
1604
1605        assert_eq!(
1606            Decimal::percent(20).checked_pow(2).unwrap(),
1607            Decimal::percent(4)
1608        );
1609
1610        assert_eq!(
1611            Decimal::percent(20).checked_pow(3).unwrap(),
1612            Decimal::permille(8)
1613        );
1614
1615        assert_eq!(
1616            Decimal::percent(200).checked_pow(4).unwrap(),
1617            Decimal::percent(1600)
1618        );
1619
1620        assert_eq!(
1621            Decimal::percent(200).checked_pow(4).unwrap(),
1622            Decimal::percent(1600)
1623        );
1624
1625        assert_eq!(
1626            Decimal::percent(700).checked_pow(5).unwrap(),
1627            Decimal::percent(1680700)
1628        );
1629
1630        assert_eq!(
1631            Decimal::percent(700).checked_pow(8).unwrap(),
1632            Decimal::percent(576480100)
1633        );
1634
1635        assert_eq!(
1636            Decimal::percent(700).checked_pow(10).unwrap(),
1637            Decimal::percent(28247524900)
1638        );
1639
1640        assert_eq!(
1641            Decimal::percent(120).checked_pow(123).unwrap(),
1642            Decimal(5486473221892422150877397607u128.into())
1643        );
1644
1645        assert_eq!(
1646            Decimal::percent(10).checked_pow(2).unwrap(),
1647            Decimal(10000000000000000u128.into())
1648        );
1649
1650        assert_eq!(
1651            Decimal::percent(10).checked_pow(18).unwrap(),
1652            Decimal(1u128.into())
1653        );
1654    }
1655
1656    #[test]
1657    fn decimal_checked_pow_overflow() {
1658        assert_eq!(
1659            Decimal::MAX.checked_pow(2),
1660            Err(OverflowError {
1661                operation: crate::OverflowOperation::Pow,
1662                operand1: Decimal::MAX.to_string(),
1663                operand2: "2".to_string(),
1664            })
1665        );
1666    }
1667
1668    #[test]
1669    fn decimal_to_string() {
1670        // Integers
1671        assert_eq!(Decimal::zero().to_string(), "0");
1672        assert_eq!(Decimal::one().to_string(), "1");
1673        assert_eq!(Decimal::percent(500).to_string(), "5");
1674
1675        // Decimals
1676        assert_eq!(Decimal::percent(125).to_string(), "1.25");
1677        assert_eq!(Decimal::percent(42638).to_string(), "426.38");
1678        assert_eq!(Decimal::percent(3).to_string(), "0.03");
1679        assert_eq!(Decimal::permille(987).to_string(), "0.987");
1680
1681        assert_eq!(
1682            Decimal(Uint128::from(1u128)).to_string(),
1683            "0.000000000000000001"
1684        );
1685        assert_eq!(
1686            Decimal(Uint128::from(10u128)).to_string(),
1687            "0.00000000000000001"
1688        );
1689        assert_eq!(
1690            Decimal(Uint128::from(100u128)).to_string(),
1691            "0.0000000000000001"
1692        );
1693        assert_eq!(
1694            Decimal(Uint128::from(1000u128)).to_string(),
1695            "0.000000000000001"
1696        );
1697        assert_eq!(
1698            Decimal(Uint128::from(10000u128)).to_string(),
1699            "0.00000000000001"
1700        );
1701        assert_eq!(
1702            Decimal(Uint128::from(100000u128)).to_string(),
1703            "0.0000000000001"
1704        );
1705        assert_eq!(
1706            Decimal(Uint128::from(1000000u128)).to_string(),
1707            "0.000000000001"
1708        );
1709        assert_eq!(
1710            Decimal(Uint128::from(10000000u128)).to_string(),
1711            "0.00000000001"
1712        );
1713        assert_eq!(
1714            Decimal(Uint128::from(100000000u128)).to_string(),
1715            "0.0000000001"
1716        );
1717        assert_eq!(
1718            Decimal(Uint128::from(1000000000u128)).to_string(),
1719            "0.000000001"
1720        );
1721        assert_eq!(
1722            Decimal(Uint128::from(10000000000u128)).to_string(),
1723            "0.00000001"
1724        );
1725        assert_eq!(
1726            Decimal(Uint128::from(100000000000u128)).to_string(),
1727            "0.0000001"
1728        );
1729        assert_eq!(
1730            Decimal(Uint128::from(10000000000000u128)).to_string(),
1731            "0.00001"
1732        );
1733        assert_eq!(
1734            Decimal(Uint128::from(100000000000000u128)).to_string(),
1735            "0.0001"
1736        );
1737        assert_eq!(
1738            Decimal(Uint128::from(1000000000000000u128)).to_string(),
1739            "0.001"
1740        );
1741        assert_eq!(
1742            Decimal(Uint128::from(10000000000000000u128)).to_string(),
1743            "0.01"
1744        );
1745        assert_eq!(
1746            Decimal(Uint128::from(100000000000000000u128)).to_string(),
1747            "0.1"
1748        );
1749    }
1750
1751    #[test]
1752    fn decimal_iter_sum() {
1753        let items = vec![
1754            Decimal::zero(),
1755            Decimal(Uint128::from(2u128)),
1756            Decimal(Uint128::from(2u128)),
1757        ];
1758        assert_eq!(items.iter().sum::<Decimal>(), Decimal(Uint128::from(4u128)));
1759        assert_eq!(
1760            items.into_iter().sum::<Decimal>(),
1761            Decimal(Uint128::from(4u128))
1762        );
1763
1764        let empty: Vec<Decimal> = vec![];
1765        assert_eq!(Decimal::zero(), empty.iter().sum::<Decimal>());
1766    }
1767
1768    #[test]
1769    fn decimal_serialize() {
1770        assert_eq!(to_vec(&Decimal::zero()).unwrap(), br#""0""#);
1771        assert_eq!(to_vec(&Decimal::one()).unwrap(), br#""1""#);
1772        assert_eq!(to_vec(&Decimal::percent(8)).unwrap(), br#""0.08""#);
1773        assert_eq!(to_vec(&Decimal::percent(87)).unwrap(), br#""0.87""#);
1774        assert_eq!(to_vec(&Decimal::percent(876)).unwrap(), br#""8.76""#);
1775        assert_eq!(to_vec(&Decimal::percent(8765)).unwrap(), br#""87.65""#);
1776    }
1777
1778    #[test]
1779    fn decimal_deserialize() {
1780        assert_eq!(from_slice::<Decimal>(br#""0""#).unwrap(), Decimal::zero());
1781        assert_eq!(from_slice::<Decimal>(br#""1""#).unwrap(), Decimal::one());
1782        assert_eq!(from_slice::<Decimal>(br#""000""#).unwrap(), Decimal::zero());
1783        assert_eq!(from_slice::<Decimal>(br#""001""#).unwrap(), Decimal::one());
1784
1785        assert_eq!(
1786            from_slice::<Decimal>(br#""0.08""#).unwrap(),
1787            Decimal::percent(8)
1788        );
1789        assert_eq!(
1790            from_slice::<Decimal>(br#""0.87""#).unwrap(),
1791            Decimal::percent(87)
1792        );
1793        assert_eq!(
1794            from_slice::<Decimal>(br#""8.76""#).unwrap(),
1795            Decimal::percent(876)
1796        );
1797        assert_eq!(
1798            from_slice::<Decimal>(br#""87.65""#).unwrap(),
1799            Decimal::percent(8765)
1800        );
1801    }
1802
1803    #[test]
1804    fn decimal_abs_diff_works() {
1805        let a = Decimal::percent(285);
1806        let b = Decimal::percent(200);
1807        let expected = Decimal::percent(85);
1808        assert_eq!(a.abs_diff(b), expected);
1809        assert_eq!(b.abs_diff(a), expected);
1810    }
1811
1812    #[test]
1813    #[allow(clippy::op_ref)]
1814    fn decimal_rem_works() {
1815        // 4.02 % 1.11 = 0.69
1816        assert_eq!(
1817            Decimal::percent(402) % Decimal::percent(111),
1818            Decimal::percent(69)
1819        );
1820
1821        // 15.25 % 4 = 3.25
1822        assert_eq!(
1823            Decimal::percent(1525) % Decimal::percent(400),
1824            Decimal::percent(325)
1825        );
1826
1827        let a = Decimal::percent(318);
1828        let b = Decimal::percent(317);
1829        let expected = Decimal::percent(1);
1830        assert_eq!(a % b, expected);
1831        assert_eq!(a % &b, expected);
1832        assert_eq!(&a % b, expected);
1833        assert_eq!(&a % &b, expected);
1834    }
1835
1836    #[test]
1837    fn decimal_rem_assign_works() {
1838        let mut a = Decimal::percent(17673);
1839        a %= Decimal::percent(2362);
1840        assert_eq!(a, Decimal::percent(1139)); // 176.73 % 23.62 = 11.39
1841
1842        let mut a = Decimal::percent(4262);
1843        let b = Decimal::percent(1270);
1844        a %= &b;
1845        assert_eq!(a, Decimal::percent(452)); // 42.62 % 12.7 = 4.52
1846    }
1847
1848    #[test]
1849    #[should_panic(expected = "divisor of zero")]
1850    fn decimal_rem_panics_for_zero() {
1851        let _ = Decimal::percent(777) % Decimal::zero();
1852    }
1853
1854    #[test]
1855    fn decimal_checked_methods() {
1856        // checked add
1857        assert_eq!(
1858            Decimal::percent(402)
1859                .checked_add(Decimal::percent(111))
1860                .unwrap(),
1861            Decimal::percent(513)
1862        );
1863        assert!(matches!(
1864            Decimal::MAX.checked_add(Decimal::percent(1)),
1865            Err(OverflowError { .. })
1866        ));
1867
1868        // checked sub
1869        assert_eq!(
1870            Decimal::percent(1111)
1871                .checked_sub(Decimal::percent(111))
1872                .unwrap(),
1873            Decimal::percent(1000)
1874        );
1875        assert!(matches!(
1876            Decimal::zero().checked_sub(Decimal::percent(1)),
1877            Err(OverflowError { .. })
1878        ));
1879
1880        // checked div
1881        assert_eq!(
1882            Decimal::percent(30)
1883                .checked_div(Decimal::percent(200))
1884                .unwrap(),
1885            Decimal::percent(15)
1886        );
1887        assert_eq!(
1888            Decimal::percent(88)
1889                .checked_div(Decimal::percent(20))
1890                .unwrap(),
1891            Decimal::percent(440)
1892        );
1893        assert!(matches!(
1894            Decimal::MAX.checked_div(Decimal::zero()),
1895            Err(CheckedFromRatioError::DivideByZero {})
1896        ));
1897        assert!(matches!(
1898            Decimal::MAX.checked_div(Decimal::percent(1)),
1899            Err(CheckedFromRatioError::Overflow {})
1900        ));
1901
1902        // checked rem
1903        assert_eq!(
1904            Decimal::percent(402)
1905                .checked_rem(Decimal::percent(111))
1906                .unwrap(),
1907            Decimal::percent(69)
1908        );
1909        assert_eq!(
1910            Decimal::percent(1525)
1911                .checked_rem(Decimal::percent(400))
1912                .unwrap(),
1913            Decimal::percent(325)
1914        );
1915        assert!(matches!(
1916            Decimal::MAX.checked_rem(Decimal::zero()),
1917            Err(DivideByZeroError { .. })
1918        ));
1919    }
1920
1921    #[test]
1922    fn decimal_pow_works() {
1923        assert_eq!(Decimal::percent(200).pow(2), Decimal::percent(400));
1924        assert_eq!(Decimal::percent(200).pow(10), Decimal::percent(102400));
1925    }
1926
1927    #[test]
1928    #[should_panic]
1929    fn decimal_pow_overflow_panics() {
1930        Decimal::MAX.pow(2u32);
1931    }
1932
1933    #[test]
1934    fn decimal_saturating_works() {
1935        assert_eq!(
1936            Decimal::percent(200).saturating_add(Decimal::percent(200)),
1937            Decimal::percent(400)
1938        );
1939        assert_eq!(
1940            Decimal::MAX.saturating_add(Decimal::percent(200)),
1941            Decimal::MAX
1942        );
1943        assert_eq!(
1944            Decimal::percent(200).saturating_sub(Decimal::percent(100)),
1945            Decimal::percent(100)
1946        );
1947        assert_eq!(
1948            Decimal::zero().saturating_sub(Decimal::percent(200)),
1949            Decimal::zero()
1950        );
1951        assert_eq!(
1952            Decimal::percent(200).saturating_mul(Decimal::percent(50)),
1953            Decimal::percent(100)
1954        );
1955        assert_eq!(
1956            Decimal::MAX.saturating_mul(Decimal::percent(200)),
1957            Decimal::MAX
1958        );
1959        assert_eq!(
1960            Decimal::percent(400).saturating_pow(2u32),
1961            Decimal::percent(1600)
1962        );
1963        assert_eq!(Decimal::MAX.saturating_pow(2u32), Decimal::MAX);
1964    }
1965
1966    #[test]
1967    fn decimal_rounding() {
1968        assert_eq!(Decimal::one().floor(), Decimal::one());
1969        assert_eq!(Decimal::percent(150).floor(), Decimal::one());
1970        assert_eq!(Decimal::percent(199).floor(), Decimal::one());
1971        assert_eq!(Decimal::percent(200).floor(), Decimal::percent(200));
1972        assert_eq!(Decimal::percent(99).floor(), Decimal::zero());
1973
1974        assert_eq!(Decimal::one().ceil(), Decimal::one());
1975        assert_eq!(Decimal::percent(150).ceil(), Decimal::percent(200));
1976        assert_eq!(Decimal::percent(199).ceil(), Decimal::percent(200));
1977        assert_eq!(Decimal::percent(99).ceil(), Decimal::one());
1978        assert_eq!(Decimal(Uint128::from(1u128)).ceil(), Decimal::one());
1979    }
1980
1981    #[test]
1982    #[should_panic(expected = "attempt to ceil with overflow")]
1983    fn decimal_ceil_panics() {
1984        let _ = Decimal::MAX.ceil();
1985    }
1986
1987    #[test]
1988    fn decimal_checked_ceil() {
1989        assert_eq!(
1990            Decimal::percent(199).checked_ceil(),
1991            Ok(Decimal::percent(200))
1992        );
1993        assert!(matches!(
1994            Decimal::MAX.checked_ceil(),
1995            Err(RoundUpOverflowError { .. })
1996        ));
1997    }
1998
1999    #[test]
2000    fn decimal_partial_eq() {
2001        let test_cases = [
2002            ("1", "1", true),
2003            ("0.5", "0.5", true),
2004            ("0.5", "0.51", false),
2005            ("0", "0.00000", true),
2006        ]
2007        .into_iter()
2008        .map(|(lhs, rhs, expected)| (dec(lhs), dec(rhs), expected));
2009
2010        #[allow(clippy::op_ref)]
2011        for (lhs, rhs, expected) in test_cases {
2012            assert_eq!(lhs == rhs, expected);
2013            assert_eq!(&lhs == rhs, expected);
2014            assert_eq!(lhs == &rhs, expected);
2015            assert_eq!(&lhs == &rhs, expected);
2016        }
2017    }
2018}