radix_common/math/
decimal.rs

1use crate::internal_prelude::*;
2#[cfg(feature = "fuzzing")]
3use arbitrary::Arbitrary;
4use core::cmp::Ordering;
5use core::ops::*;
6use num_bigint::BigInt;
7use num_traits::{Pow, Zero};
8#[cfg(feature = "fuzzing")]
9use serde::{Deserialize, Serialize};
10
11use crate::data::manifest::ManifestCustomValueKind;
12use crate::data::scrypto::*;
13use crate::math::bnum_integer::*;
14use crate::math::rounding_mode::*;
15use crate::math::traits::*;
16use crate::math::PreciseDecimal;
17use crate::well_known_scrypto_custom_type;
18use crate::*;
19
20use super::CheckedTruncate;
21
22/// `Decimal` represents a 192 bit representation of a fixed-scale decimal number.
23///
24/// The finite set of values are of the form `m / 10^18`, where `m` is
25/// an integer such that `-2^(192 - 1) <= m < 2^(192 - 1)`.
26///
27/// ```text
28/// Fractional part: ~60 bits/18 digits
29/// Integer part   : 132 bits /40 digits
30/// Max            :  3138550867693340381917894711603833208051.177722232017256447
31/// Min            : -3138550867693340381917894711603833208051.177722232017256448
32/// ```
33///
34/// Unless otherwise specified, all operations will panic if there is underflow/overflow.
35///
36/// To create a Decimal with a certain number of `10^(-18)` subunits, use
37/// [`Decimal::from_attos`] or equivalently [`Decimal::from_subunits`].
38#[cfg_attr(feature = "fuzzing", derive(Arbitrary, Serialize, Deserialize))]
39#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
40pub struct Decimal(InnerDecimal);
41
42pub type InnerDecimal = I192;
43
44impl Default for Decimal {
45    fn default() -> Self {
46        Self::zero()
47    }
48}
49
50// TODO come up with some smarter formatting depending on Decimal::Scale
51macro_rules! fmt_remainder {
52    () => {
53        "{:018}"
54    };
55}
56
57impl Decimal {
58    /// The min value of `Decimal`.
59    pub const MIN: Self = Self(I192::MIN);
60
61    /// The max value of `Decimal`.
62    pub const MAX: Self = Self(I192::MAX);
63
64    /// The bit length of number storing `Decimal`.
65    pub const BITS: usize = I192::BITS as usize;
66
67    /// The fixed scale used by `Decimal`.
68    pub const SCALE: u32 = 18;
69
70    pub const ZERO: Self = Self(I192::ZERO);
71
72    pub const ONE_ATTO: Self = Self(I192::ONE);
73    pub const ONE_SUBUNIT: Self = Self::ONE_ATTO;
74    pub const ONE_HUNDREDTH: Self = Self(I192::from_digits([10_u64.pow(Decimal::SCALE - 2), 0, 0]));
75    pub const ONE_TENTH: Self = Self(I192::from_digits([10_u64.pow(Decimal::SCALE - 1), 0, 0]));
76    pub const ONE: Self = Self(I192::from_digits([10_u64.pow(Decimal::SCALE), 0, 0]));
77    pub const TEN: Self = Self(I192::from_digits([10_u64.pow(Decimal::SCALE + 1), 0, 0]));
78    pub const ONE_HUNDRED: Self = Self(I192::from_digits([7766279631452241920, 0x5, 0]));
79
80    /// Constructs a [`Decimal`] from its underlying `10^(-18)` subunits.
81    pub const fn from_attos(attos: I192) -> Self {
82        Self(attos)
83    }
84
85    /// Constructs a [`Decimal`] from its underlying `10^(-18)` subunits.
86    ///
87    /// This is an alias of [`from_attos`][Self::from_attos], for consistency with [`PreciseDecimal::from_precise_subunits`].
88    pub const fn from_subunits(subunits: I192) -> Self {
89        Self(subunits)
90    }
91
92    /// Returns the underlying `10^(-18)` subunits of the [`Decimal`].
93    pub const fn attos(self) -> I192 {
94        self.0
95    }
96
97    /// Returns the underlying `10^(-18)` subunits of the [`Decimal`].
98    ///
99    /// This is an alias of [`attos`][Self::attos], for consistency with [`PreciseDecimal::precise_subunits`].
100    pub const fn subunits(self) -> I192 {
101        self.0
102    }
103
104    /// Returns a [`Decimal`] with value 0.
105    pub const fn zero() -> Self {
106        Self::ZERO
107    }
108
109    /// Returns a [`Decimal`] with value 1.
110    pub const fn one() -> Self {
111        Self::ONE
112    }
113
114    /// Whether this value is zero.
115    pub fn is_zero(&self) -> bool {
116        self.0 == I192::ZERO
117    }
118
119    /// Whether this value is positive.
120    pub fn is_positive(&self) -> bool {
121        self.0 > I192::ZERO
122    }
123
124    /// Whether this value is negative.
125    pub fn is_negative(&self) -> bool {
126        self.0 < I192::ZERO
127    }
128
129    /// Returns the absolute value.
130    pub fn checked_abs(&self) -> Option<Self> {
131        if *self != Self::MIN {
132            Some(Self(self.0.abs()))
133        } else {
134            None
135        }
136    }
137
138    /// Returns the largest integer that is equal to or less than this number.
139    pub fn checked_floor(&self) -> Option<Self> {
140        self.checked_round(0, RoundingMode::ToNegativeInfinity)
141    }
142
143    /// Returns the smallest integer that is equal to or greater than this number.
144    pub fn checked_ceiling(&self) -> Option<Self> {
145        self.checked_round(0, RoundingMode::ToPositiveInfinity)
146    }
147
148    /// Rounds this number to the specified decimal places.
149    ///
150    /// # Panics
151    /// - Panic if the number of decimal places is not within [0..SCALE]
152    pub fn checked_round<T: Into<i32>>(
153        &self,
154        decimal_places: T,
155        mode: RoundingMode,
156    ) -> Option<Self> {
157        let decimal_places = decimal_places.into();
158        assert!(decimal_places <= Self::SCALE as i32);
159        assert!(decimal_places >= 0);
160
161        let n = Self::SCALE - decimal_places as u32;
162        let divisor: I192 = I192::TEN.pow(n);
163        let positive_remainder = {
164            // % is the "C" style remainder operator, rather than the mathematical modulo operator,
165            // So we fix that here https://internals.rust-lang.org/t/mathematical-modulo-operator/5952
166            let remainder = self.0 % divisor;
167            match remainder.cmp(&I192::ZERO) {
168                Ordering::Less => divisor + remainder,
169                Ordering::Equal => return Some(*self),
170                Ordering::Greater => remainder,
171            }
172        };
173
174        let resolved_strategy =
175            ResolvedRoundingStrategy::from_mode(mode, self.is_positive(), || {
176                let midpoint = divisor >> 1; // Half the divisor
177                positive_remainder.cmp(&midpoint)
178            });
179
180        let rounded_subunits = match resolved_strategy {
181            ResolvedRoundingStrategy::RoundUp => {
182                let to_add = divisor
183                    .checked_sub(positive_remainder)
184                    .expect("Always safe");
185                self.0.checked_add(to_add)?
186            }
187            ResolvedRoundingStrategy::RoundDown => self.0.checked_sub(positive_remainder)?,
188            ResolvedRoundingStrategy::RoundToEven => {
189                let double_divisor = divisor << 1; // Double the divisor
190                if self.is_positive() {
191                    // If positive, we try rounding down first (to avoid accidental overflow)
192                    let rounded_down = self.0.checked_sub(positive_remainder)?;
193                    if rounded_down % double_divisor == I192::ZERO {
194                        rounded_down
195                    } else {
196                        rounded_down.checked_add(divisor)?
197                    }
198                } else {
199                    // If negative, we try rounding up first (to avoid accidental overflow)
200                    let to_add = divisor
201                        .checked_sub(positive_remainder)
202                        .expect("Always safe");
203                    let rounded_up = self.0.checked_add(to_add)?;
204                    if rounded_up % double_divisor == I192::ZERO {
205                        rounded_up
206                    } else {
207                        rounded_up.checked_sub(divisor)?
208                    }
209                }
210            }
211        };
212
213        Some(Self(rounded_subunits))
214    }
215
216    /// Calculates power using exponentiation by squaring".
217    pub fn checked_powi(&self, exp: i64) -> Option<Self> {
218        let one_256 = I256::from(Self::ONE.0);
219        let base_256 = I256::from(self.0);
220        let div = |x: i64, y: i64| x.checked_div(y);
221        let sub = |x: i64, y: i64| x.checked_sub(y);
222        let mul = |x: i64, y: i64| x.checked_mul(y);
223
224        if exp < 0 {
225            let dec_192 = I192::try_from((one_256 * one_256).checked_div(base_256)?).ok()?;
226            let exp = mul(exp, -1)?;
227            return Self(dec_192).checked_powi(exp);
228        }
229        if exp == 0 {
230            return Some(Self::ONE);
231        }
232        if exp == 1 {
233            return Some(*self);
234        }
235        if exp % 2 == 0 {
236            let dec_192 = I192::try_from(base_256.checked_mul(base_256)? / one_256).ok()?;
237            let exp = div(exp, 2)?;
238            Self(dec_192).checked_powi(exp)
239        } else {
240            let dec_192 = I192::try_from(base_256.checked_mul(base_256)? / one_256).ok()?;
241            let sub_dec = Self(dec_192);
242            let exp = div(sub(exp, 1)?, 2)?;
243            let b = sub_dec.checked_powi(exp)?;
244            self.checked_mul(b)
245        }
246    }
247
248    /// Square root of a Decimal
249    pub fn checked_sqrt(&self) -> Option<Self> {
250        if self.is_negative() {
251            return None;
252        }
253        if self.is_zero() {
254            return Some(Self::ZERO);
255        }
256
257        // The I192 i associated to a Decimal d is : i = d*10^18.
258        // Therefore, taking sqrt yields sqrt(i) = sqrt(d)*10^9 => We lost precision
259        // To get the right precision, we compute : sqrt(i*10^18) = sqrt(d)*10^18
260        let self_256 = I256::from(self.0);
261        let correct_nb = self_256 * I256::from(Self::ONE.0);
262        let sqrt = I192::try_from(correct_nb.sqrt()).ok()?;
263        Some(Self(sqrt))
264    }
265
266    /// Cubic root of a Decimal
267    pub fn checked_cbrt(&self) -> Option<Self> {
268        if self.is_zero() {
269            return Some(Self::ZERO);
270        }
271
272        // By reasoning in the same way as before, we realise that we need to multiply by 10^36
273        let self_320 = I320::from(self.0);
274        let correct_nb = self_320 * I320::from(Self::ONE.0).pow(2);
275        let cbrt = I192::try_from(correct_nb.cbrt()).ok()?;
276        Some(Self(cbrt))
277    }
278
279    /// Nth root of a Decimal
280    pub fn checked_nth_root(&self, n: u32) -> Option<Self> {
281        if (self.is_negative() && n % 2 == 0) || n == 0 {
282            None
283        } else if n == 1 {
284            Some(*self)
285        } else {
286            if self.is_zero() {
287                return Some(Self::ZERO);
288            }
289
290            // By induction, we need to multiply by the (n-1)th power of 10^18.
291            // To not overflow, we use BigInts
292            let self_bigint = BigInt::from(self.0);
293            let correct_nb = self_bigint * BigInt::from(Self::ONE.0).pow(n - 1);
294            let nth_root = I192::try_from(correct_nb.nth_root(n)).unwrap();
295            Some(Decimal(nth_root))
296        }
297    }
298}
299
300macro_rules! from_primitive_type {
301    ($($type:ident),*) => {
302        $(
303            impl From<$type> for Decimal {
304                fn from(val: $type) -> Self {
305                    Self(I192::from(val) * Self::ONE.0)
306                }
307            }
308        )*
309    };
310}
311macro_rules! to_primitive_type {
312    ($($type:ident),*) => {
313        $(
314            impl TryFrom<Decimal> for $type {
315                type Error = ParseDecimalError;
316
317                fn try_from(val: Decimal) -> Result<Self, Self::Error> {
318                    let rounded = val.checked_round(0, RoundingMode::ToZero).ok_or(ParseDecimalError::Overflow)?;
319                    let fraction = val.checked_sub(rounded).ok_or(Self::Error::Overflow)?;
320                    if !fraction.is_zero() {
321                        Err(Self::Error::InvalidDigit)
322                    }
323                    else {
324                        let i_192 = rounded.0 / I192::TEN.pow(Decimal::SCALE);
325                        $type::try_from(i_192)
326                            .map_err(|_| Self::Error::Overflow)
327                    }
328                }
329            }
330
331            impl TryFrom<&Decimal> for $type {
332                type Error = ParseDecimalError;
333
334                fn try_from(val: &Decimal) -> Result<Self, Self::Error> {
335                    $type::try_from(*val)
336                }
337            }
338        )*
339    }
340}
341
342from_primitive_type!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
343to_primitive_type!(i8, i16, i32, i64, i128, isize, u8, u16, u32, u64, u128, usize);
344
345resolvable_with_try_into_impls!(Decimal);
346
347// from_str() should be enough, but we want to have try_from() to simplify dec! macro
348impl TryFrom<&str> for Decimal {
349    type Error = ParseDecimalError;
350
351    fn try_from(val: &str) -> Result<Self, Self::Error> {
352        Self::from_str(val)
353    }
354}
355
356impl TryFrom<String> for Decimal {
357    type Error = ParseDecimalError;
358
359    fn try_from(val: String) -> Result<Self, Self::Error> {
360        Self::from_str(&val)
361    }
362}
363
364impl From<bool> for Decimal {
365    fn from(val: bool) -> Self {
366        if val {
367            Self::ONE
368        } else {
369            Self::ZERO
370        }
371    }
372}
373
374impl CheckedNeg<Decimal> for Decimal {
375    type Output = Self;
376
377    #[inline]
378    fn checked_neg(self) -> Option<Self::Output> {
379        let c = self.0.checked_neg();
380        c.map(Self)
381    }
382}
383
384impl CheckedAdd<Decimal> for Decimal {
385    type Output = Self;
386
387    #[inline]
388    fn checked_add(self, other: Self) -> Option<Self::Output> {
389        let a = self.0;
390        let b = other.0;
391        let c = a.checked_add(b);
392        c.map(Self)
393    }
394}
395
396impl SaturatingAdd<Decimal> for Decimal {
397    type Output = Self;
398
399    #[inline]
400    fn saturating_add(self, other: Self) -> Self::Output {
401        Self(self.0.saturating_add(other.0))
402    }
403}
404
405impl CheckedSub<Decimal> for Decimal {
406    type Output = Self;
407
408    #[inline]
409    fn checked_sub(self, other: Self) -> Option<Self::Output> {
410        let a = self.0;
411        let b = other.0;
412        let c = a.checked_sub(b);
413        c.map(Self)
414    }
415}
416
417impl CheckedMul<Decimal> for Decimal {
418    type Output = Self;
419
420    #[inline]
421    fn checked_mul(self, other: Self) -> Option<Self> {
422        // Use I256 (BInt<4>) to not overflow.
423        let a = I256::from(self.0);
424        let b = I256::from(other.0);
425        let mut c = a.checked_mul(b)?;
426        c = c.checked_div(I256::from(Self::ONE.0))?;
427
428        let c_192 = I192::try_from(c).ok();
429        c_192.map(Self)
430    }
431}
432
433impl CheckedDiv<Decimal> for Decimal {
434    type Output = Self;
435
436    #[inline]
437    fn checked_div(self, other: Self) -> Option<Self> {
438        // Use I256 (BInt<4>) to not overflow.
439        let a = I256::from(self.0);
440        let b = I256::from(other.0);
441        let mut c = a.checked_mul(I256::from(Self::ONE.0))?;
442        c = c.checked_div(b)?;
443
444        let c_192 = I192::try_from(c).ok();
445        c_192.map(Self)
446    }
447}
448
449impl Neg for Decimal {
450    type Output = Self;
451
452    #[inline]
453    fn neg(self) -> Self::Output {
454        self.checked_neg().expect("Overflow")
455    }
456}
457
458impl Add<Decimal> for Decimal {
459    type Output = Self;
460
461    #[inline]
462    fn add(self, other: Self) -> Self::Output {
463        self.checked_add(other).expect("Overflow")
464    }
465}
466
467impl Sub<Decimal> for Decimal {
468    type Output = Self;
469
470    #[inline]
471    fn sub(self, other: Self) -> Self::Output {
472        self.checked_sub(other).expect("Overflow")
473    }
474}
475
476impl Mul<Decimal> for Decimal {
477    type Output = Self;
478
479    #[inline]
480    fn mul(self, other: Self) -> Self::Output {
481        self.checked_mul(other).expect("Overflow")
482    }
483}
484
485impl Div<Decimal> for Decimal {
486    type Output = Self;
487
488    #[inline]
489    fn div(self, other: Self) -> Self::Output {
490        self.checked_div(other)
491            .expect("Overflow or division by zero")
492    }
493}
494
495impl AddAssign<Decimal> for Decimal {
496    #[inline]
497    fn add_assign(&mut self, other: Self) {
498        *self = *self + other;
499    }
500}
501
502impl SubAssign<Decimal> for Decimal {
503    #[inline]
504    fn sub_assign(&mut self, other: Self) {
505        *self = *self - other;
506    }
507}
508
509impl MulAssign<Decimal> for Decimal {
510    #[inline]
511    fn mul_assign(&mut self, other: Self) {
512        *self = *self * other;
513    }
514}
515
516impl DivAssign<Decimal> for Decimal {
517    #[inline]
518    fn div_assign(&mut self, other: Self) {
519        *self = *self / other;
520    }
521}
522
523macro_rules! impl_arith_ops {
524    ($type:ident) => {
525        impl CheckedAdd<$type> for Decimal {
526            type Output = Self;
527
528            fn checked_add(self, other: $type) -> Option<Self::Output> {
529                self.checked_add(Self::try_from(other).ok()?)
530            }
531        }
532
533        impl CheckedSub<$type> for Decimal {
534            type Output = Self;
535
536            fn checked_sub(self, other: $type) -> Option<Self::Output> {
537                self.checked_sub(Self::try_from(other).ok()?)
538            }
539        }
540
541        impl CheckedMul<$type> for Decimal {
542            type Output = Self;
543
544            fn checked_mul(self, other: $type) -> Option<Self::Output> {
545                self.checked_mul(Self::try_from(other).ok()?)
546            }
547        }
548
549        impl CheckedDiv<$type> for Decimal {
550            type Output = Self;
551
552            fn checked_div(self, other: $type) -> Option<Self::Output> {
553                self.checked_div(Self::try_from(other).ok()?)
554            }
555        }
556
557        impl Add<$type> for Decimal {
558            type Output = Self;
559
560            #[inline]
561            fn add(self, other: $type) -> Self::Output {
562                self.checked_add(other).expect("Overflow")
563            }
564        }
565
566        impl Sub<$type> for Decimal {
567            type Output = Self;
568
569            #[inline]
570            fn sub(self, other: $type) -> Self::Output {
571                self.checked_sub(other).expect("Overflow")
572            }
573        }
574
575        impl Mul<$type> for Decimal {
576            type Output = Self;
577
578            #[inline]
579            fn mul(self, other: $type) -> Self::Output {
580                self.checked_mul(other).expect("Overflow")
581            }
582        }
583
584        impl Div<$type> for Decimal {
585            type Output = Self;
586
587            #[inline]
588            fn div(self, other: $type) -> Self::Output {
589                self.checked_div(other)
590                    .expect("Overflow or division by zero")
591            }
592        }
593
594        impl Add<Decimal> for $type {
595            type Output = Decimal;
596
597            #[inline]
598            fn add(self, other: Decimal) -> Self::Output {
599                other + self
600            }
601        }
602
603        impl Sub<Decimal> for $type {
604            type Output = Decimal;
605
606            #[inline]
607            fn sub(self, other: Decimal) -> Self::Output {
608                // Cannot use self.checked_sub directly.
609                // It conflicts with already defined checked_sub for primitive types.
610                Decimal::try_from(self)
611                    .expect("Overflow")
612                    .checked_sub(other)
613                    .expect("Overflow")
614            }
615        }
616
617        impl Mul<Decimal> for $type {
618            type Output = Decimal;
619
620            #[inline]
621            fn mul(self, other: Decimal) -> Self::Output {
622                other * self
623            }
624        }
625
626        impl Div<Decimal> for $type {
627            type Output = Decimal;
628
629            #[inline]
630            fn div(self, other: Decimal) -> Self::Output {
631                // Cannot use self.checked_div directly.
632                // It conflicts with already defined checked_sub for primitive types.
633                Decimal::try_from(self)
634                    .expect("Overflow")
635                    .checked_div(other)
636                    .expect("Overflow or division by zero")
637            }
638        }
639
640        impl AddAssign<$type> for Decimal {
641            #[inline]
642            fn add_assign(&mut self, other: $type) {
643                *self = *self + other;
644            }
645        }
646
647        impl SubAssign<$type> for Decimal {
648            #[inline]
649            fn sub_assign(&mut self, other: $type) {
650                *self = *self - other;
651            }
652        }
653
654        impl MulAssign<$type> for Decimal {
655            #[inline]
656            fn mul_assign(&mut self, other: $type) {
657                *self = *self * other;
658            }
659        }
660
661        impl DivAssign<$type> for Decimal {
662            #[inline]
663            fn div_assign(&mut self, other: $type) {
664                *self = *self / other;
665            }
666        }
667    };
668}
669impl_arith_ops!(u8);
670impl_arith_ops!(u16);
671impl_arith_ops!(u32);
672impl_arith_ops!(u64);
673impl_arith_ops!(u128);
674impl_arith_ops!(usize);
675impl_arith_ops!(i8);
676impl_arith_ops!(i16);
677impl_arith_ops!(i32);
678impl_arith_ops!(i64);
679impl_arith_ops!(i128);
680impl_arith_ops!(isize);
681impl_arith_ops!(I192);
682impl_arith_ops!(I256);
683impl_arith_ops!(I320);
684impl_arith_ops!(I448);
685impl_arith_ops!(I512);
686impl_arith_ops!(U192);
687impl_arith_ops!(U256);
688impl_arith_ops!(U320);
689impl_arith_ops!(U448);
690impl_arith_ops!(U512);
691
692// Below implements CheckedX traits for given type with Decimal as an argument.
693// It cannot be used for primitive types, since they already implement these traits
694// but with different argument type.
695macro_rules! impl_arith_ops_non_primitives {
696    ($type:ident) => {
697        impl CheckedAdd<Decimal> for $type {
698            type Output = Decimal;
699
700            #[inline]
701            fn checked_add(self, other: Decimal) -> Option<Self::Output> {
702                other.checked_add(self)
703            }
704        }
705
706        impl CheckedSub<Decimal> for $type {
707            type Output = Decimal;
708
709            fn checked_sub(self, other: Decimal) -> Option<Self::Output> {
710                Decimal::try_from(self).ok()?.checked_sub(other)
711            }
712        }
713
714        impl CheckedMul<Decimal> for $type {
715            type Output = Decimal;
716
717            #[inline]
718            fn checked_mul(self, other: Decimal) -> Option<Self::Output> {
719                other.checked_mul(self)
720            }
721        }
722
723        impl CheckedDiv<Decimal> for $type {
724            type Output = Decimal;
725
726            fn checked_div(self, other: Decimal) -> Option<Self::Output> {
727                Decimal::try_from(self).ok()?.checked_div(other)
728            }
729        }
730    };
731}
732impl_arith_ops_non_primitives!(I192);
733impl_arith_ops_non_primitives!(I256);
734impl_arith_ops_non_primitives!(I320);
735impl_arith_ops_non_primitives!(I448);
736impl_arith_ops_non_primitives!(I512);
737impl_arith_ops_non_primitives!(U192);
738impl_arith_ops_non_primitives!(U256);
739impl_arith_ops_non_primitives!(U320);
740impl_arith_ops_non_primitives!(U448);
741impl_arith_ops_non_primitives!(U512);
742
743//========
744// binary
745//========
746
747impl TryFrom<&[u8]> for Decimal {
748    type Error = ParseDecimalError;
749
750    fn try_from(slice: &[u8]) -> Result<Self, Self::Error> {
751        if slice.len() == Self::BITS / 8 {
752            let val = I192::try_from(slice).expect("Length should have already been checked.");
753            Ok(Self(val))
754        } else {
755            Err(ParseDecimalError::InvalidLength(slice.len()))
756        }
757    }
758}
759
760impl Decimal {
761    pub fn to_vec(&self) -> Vec<u8> {
762        self.0.to_le_bytes().to_vec()
763    }
764}
765
766well_known_scrypto_custom_type!(
767    Decimal,
768    ScryptoCustomValueKind::Decimal,
769    Type::Decimal,
770    Decimal::BITS / 8,
771    DECIMAL_TYPE,
772    decimal_type_data
773);
774
775manifest_type!(Decimal, ManifestCustomValueKind::Decimal, Decimal::BITS / 8);
776
777//======
778// text
779//======
780
781impl FromStr for Decimal {
782    type Err = ParseDecimalError;
783
784    fn from_str(s: &str) -> Result<Self, Self::Err> {
785        let v: Vec<&str> = s.split('.').collect();
786
787        if v.len() > 2 {
788            return Err(ParseDecimalError::MoreThanOneDecimalPoint);
789        }
790
791        let integer_part = match I192::from_str(v[0]) {
792            Ok(val) => val,
793            Err(err) => match err {
794                ParseI192Error::NegativeToUnsigned => {
795                    unreachable!("NegativeToUnsigned is only for parsing unsigned types, not I192")
796                }
797                ParseI192Error::Overflow => return Err(ParseDecimalError::Overflow),
798                ParseI192Error::InvalidLength => {
799                    unreachable!("InvalidLength is only for parsing &[u8], not &str")
800                }
801                ParseI192Error::InvalidDigit => return Err(ParseDecimalError::InvalidDigit),
802                // We have decided to be restrictive to force people to type "0.123" instead of ".123"
803                // for clarity, and to align with how rust's float literal works
804                ParseI192Error::Empty => return Err(ParseDecimalError::EmptyIntegralPart),
805            },
806        };
807
808        let mut subunits = integer_part
809            .checked_mul(Self::ONE.0)
810            .ok_or(ParseDecimalError::Overflow)?;
811
812        if v.len() == 2 {
813            let scale = if let Some(scale) = Self::SCALE.checked_sub(v[1].len() as u32) {
814                Ok(scale)
815            } else {
816                Err(Self::Err::MoreThanEighteenDecimalPlaces)
817            }?;
818
819            let fractional_part = match I192::from_str(v[1]) {
820                Ok(val) => val,
821                Err(err) => match err {
822                    ParseI192Error::NegativeToUnsigned => {
823                        unreachable!(
824                            "NegativeToUnsigned is only for parsing unsigned types, no I192"
825                        )
826                    }
827                    ParseI192Error::Overflow => return Err(ParseDecimalError::Overflow),
828                    ParseI192Error::InvalidLength => {
829                        unreachable!("InvalidLength is only for parsing &[u8], not &str")
830                    }
831                    ParseI192Error::InvalidDigit => return Err(ParseDecimalError::InvalidDigit),
832                    ParseI192Error::Empty => return Err(ParseDecimalError::EmptyFractionalPart),
833                },
834            };
835
836            // The product of these must be less than Self::SCALE
837            let fractional_subunits = fractional_part
838                .checked_mul(I192::TEN.pow(scale))
839                .expect("No overflow possible");
840
841            // if input is -0. then from_str returns 0 and we loose '-' sign.
842            // Therefore check for '-' in input directly
843            if integer_part.is_negative() || v[0].starts_with('-') {
844                subunits = subunits
845                    .checked_sub(fractional_subunits)
846                    .ok_or(ParseDecimalError::Overflow)?;
847            } else {
848                subunits = subunits
849                    .checked_add(fractional_subunits)
850                    .ok_or(ParseDecimalError::Overflow)?;
851            }
852        }
853        Ok(Self(subunits))
854    }
855}
856
857impl fmt::Display for Decimal {
858    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
859        const MULTIPLIER: I192 = Decimal::ONE.0;
860        let quotient = self.0 / MULTIPLIER;
861        let remainder = self.0 % MULTIPLIER;
862
863        if !remainder.is_zero() {
864            // print remainder with leading zeroes
865            let mut sign = "".to_string();
866
867            // take care of sign in case quotient == zere and remainder < 0,
868            // eg.
869            //  self.0=-100000000000000000 -> -0.1
870            if remainder < I192::ZERO && quotient == I192::ZERO {
871                sign.push('-');
872            }
873            let rem_str = format!(fmt_remainder!(), remainder.abs());
874            write!(f, "{}{}.{}", sign, quotient, &rem_str.trim_end_matches('0'))
875        } else {
876            write!(f, "{}", quotient)
877        }
878    }
879}
880
881impl fmt::Debug for Decimal {
882    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
883        write!(f, "{}", self)
884    }
885}
886
887//========
888// ParseDecimalError, ParsePreciseDecimalError
889//========
890
891/// Represents an error when parsing Decimal from another type.
892#[derive(Debug, Clone, PartialEq, Eq)]
893pub enum ParseDecimalError {
894    InvalidDigit,
895    Overflow,
896    EmptyIntegralPart,
897    EmptyFractionalPart,
898    MoreThanEighteenDecimalPlaces,
899    MoreThanOneDecimalPoint,
900    InvalidLength(usize),
901}
902
903#[cfg(not(feature = "alloc"))]
904impl std::error::Error for ParseDecimalError {}
905
906#[cfg(not(feature = "alloc"))]
907impl fmt::Display for ParseDecimalError {
908    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
909        write!(f, "{:?}", self)
910    }
911}
912
913impl TryFrom<PreciseDecimal> for Decimal {
914    type Error = ParseDecimalError;
915
916    fn try_from(val: PreciseDecimal) -> Result<Self, Self::Error> {
917        val.checked_truncate(RoundingMode::ToZero)
918            .ok_or(ParseDecimalError::Overflow)
919    }
920}
921
922macro_rules! try_from_integer {
923    ($($t:ident),*) => {
924        $(
925            impl TryFrom<$t> for Decimal {
926                type Error = ParseDecimalError;
927
928                fn try_from(val: $t) -> Result<Self, Self::Error> {
929                    match I192::try_from(val) {
930                        Ok(val) => {
931                            match val.checked_mul(Self::ONE.0) {
932                                Some(mul) => Ok(Self(mul)),
933                                None => Err(ParseDecimalError::Overflow),
934                            }
935                        },
936                        Err(_) => Err(ParseDecimalError::Overflow),
937                    }
938                }
939            }
940        )*
941    };
942}
943try_from_integer!(I192, I256, I320, I448, I512, U192, U256, U320, U448, U512);
944
945#[cfg(test)]
946mod tests {
947    use super::*;
948    use crate::internal_prelude::*;
949    use paste::paste;
950
951    macro_rules! test_dec {
952        // NOTE: Decimal arithmetic operation safe unwrap.
953        // In general, it is assumed that reasonable literals are provided.
954        // If not then something is definitely wrong and panic is fine.
955        ($x:literal) => {
956            $crate::math::Decimal::try_from($x).unwrap()
957        };
958    }
959
960    #[test]
961    fn test_format_decimal() {
962        assert_eq!(Decimal(1i128.into()).to_string(), "0.000000000000000001");
963        assert_eq!(
964            Decimal(123456789123456789i128.into()).to_string(),
965            "0.123456789123456789"
966        );
967        assert_eq!(Decimal(1000000000000000000i128.into()).to_string(), "1");
968        assert_eq!(Decimal(123000000000000000000i128.into()).to_string(), "123");
969        assert_eq!(
970            Decimal(123456789123456789000000000000000000i128.into()).to_string(),
971            "123456789123456789"
972        );
973        assert_eq!(
974            Decimal::MAX.to_string(),
975            "3138550867693340381917894711603833208051.177722232017256447"
976        );
977        assert!(Decimal::MIN.is_negative());
978        assert_eq!(
979            Decimal::MIN.to_string(),
980            "-3138550867693340381917894711603833208051.177722232017256448"
981        );
982    }
983
984    #[test]
985    fn test_parse_decimal() {
986        assert_eq!(
987            Decimal::from_str("0.000000000000000001").unwrap(),
988            Decimal(1i128.into()),
989        );
990        assert_eq!(
991            Decimal::from_str("0.0000000000000000001"),
992            Err(ParseDecimalError::MoreThanEighteenDecimalPlaces),
993        );
994        assert_eq!(
995            Decimal::from_str("0.123456789123456789").unwrap(),
996            Decimal(123456789123456789i128.into()),
997        );
998        assert_eq!(
999            Decimal::from_str("1").unwrap(),
1000            Decimal(1000000000000000000i128.into()),
1001        );
1002        assert_eq!(
1003            Decimal::from_str("123456789123456789").unwrap(),
1004            Decimal(123456789123456789000000000000000000i128.into()),
1005        );
1006        assert_eq!(
1007            Decimal::from_str("3138550867693340381917894711603833208051.177722232017256447")
1008                .unwrap(),
1009            Decimal::MAX,
1010        );
1011        assert_eq!(
1012            Decimal::from_str("3138550867693340381917894711603833208051.177722232017256448"),
1013            Err(ParseDecimalError::Overflow),
1014        );
1015        assert_eq!(
1016            Decimal::from_str("3138550867693340381917894711603833208052.177722232017256447"),
1017            Err(ParseDecimalError::Overflow),
1018        );
1019        assert_eq!(
1020            Decimal::from_str("-3138550867693340381917894711603833208051.177722232017256448")
1021                .unwrap(),
1022            Decimal::MIN,
1023        );
1024        assert_eq!(
1025            Decimal::from_str("-3138550867693340381917894711603833208051.177722232017256449"),
1026            Err(ParseDecimalError::Overflow),
1027        );
1028        assert_eq!(
1029            Decimal::from_str(".000000000000000231"),
1030            Err(ParseDecimalError::EmptyIntegralPart),
1031        );
1032        assert_eq!(
1033            Decimal::from_str("231."),
1034            Err(ParseDecimalError::EmptyFractionalPart),
1035        );
1036
1037        assert_eq!(test_dec!("0"), Decimal::ZERO);
1038        assert_eq!(test_dec!("1"), Decimal::ONE);
1039        assert_eq!(test_dec!("0.1"), Decimal::ONE_TENTH);
1040        assert_eq!(test_dec!("10"), Decimal::TEN);
1041        assert_eq!(test_dec!("100"), Decimal::ONE_HUNDRED);
1042        assert_eq!(test_dec!("0.01"), Decimal::ONE_HUNDREDTH);
1043        assert_eq!(test_dec!("0.000000000000000001"), Decimal::ONE_ATTO);
1044
1045        assert_eq!("0", Decimal::ZERO.to_string());
1046        assert_eq!("1", Decimal::ONE.to_string());
1047        assert_eq!("0.1", Decimal::ONE_TENTH.to_string());
1048        assert_eq!("10", Decimal::TEN.to_string());
1049        assert_eq!("100", Decimal::ONE_HUNDRED.to_string());
1050        assert_eq!("0.01", Decimal::ONE_HUNDREDTH.to_string());
1051        assert_eq!("0.000000000000000001", Decimal::ONE_ATTO.to_string());
1052    }
1053
1054    #[test]
1055    fn test_add_decimal() {
1056        let a = Decimal::from(5u32);
1057        let b = Decimal::from(7u32);
1058        assert_eq!(a.checked_add(b).unwrap().to_string(), "12");
1059    }
1060
1061    #[test]
1062    fn test_add_overflow_decimal() {
1063        assert!(Decimal::MAX.checked_add(Decimal::ONE).is_none());
1064    }
1065
1066    #[test]
1067    fn test_sub_decimal() {
1068        let a = Decimal::from(5u32);
1069        let b = Decimal::from(7u32);
1070        assert_eq!(a.checked_sub(b).unwrap().to_string(), "-2");
1071        assert_eq!(b.checked_sub(a).unwrap().to_string(), "2");
1072    }
1073
1074    #[test]
1075    fn test_sub_overflow_decimal() {
1076        assert!(Decimal::MIN.checked_sub(Decimal::ONE).is_none());
1077    }
1078
1079    #[test]
1080    fn test_mul_decimal() {
1081        let a = Decimal::from(5u32);
1082        let b = Decimal::from(7u32);
1083        assert_eq!(a.checked_mul(b).unwrap().to_string(), "35");
1084        let a = Decimal::from_str("1000000000").unwrap();
1085        let b = Decimal::from_str("1000000000").unwrap();
1086        assert_eq!(a.checked_mul(b).unwrap().to_string(), "1000000000000000000");
1087        let a = Decimal::MAX;
1088        let b = test_dec!(1);
1089        assert_eq!(a.checked_mul(b).unwrap(), Decimal::MAX);
1090    }
1091
1092    #[test]
1093    fn test_mul_to_max_decimal() {
1094        let a = Decimal::MAX.checked_sqrt().unwrap();
1095        a.checked_mul(a).unwrap();
1096    }
1097
1098    #[test]
1099    fn test_mul_to_minimum_overflow_decimal() {
1100        let a = Decimal::MAX.checked_sqrt().unwrap();
1101        assert!(a.checked_mul(a + Decimal(I192::ONE)).is_none());
1102    }
1103
1104    #[test]
1105    fn test_mul_overflow_by_small_decimal() {
1106        assert!(Decimal::MAX
1107            .checked_mul(test_dec!("1.000000000000000001"))
1108            .is_none());
1109    }
1110
1111    #[test]
1112    fn test_mul_overflow_by_a_lot_decimal() {
1113        assert!(Decimal::MAX.checked_mul(test_dec!("1.1")).is_none());
1114    }
1115
1116    #[test]
1117    fn test_mul_neg_overflow_decimal() {
1118        assert!(Decimal::MAX
1119            .checked_neg()
1120            .unwrap()
1121            .checked_mul(test_dec!("-1.000000000000000001"))
1122            .is_none());
1123    }
1124
1125    #[test]
1126    fn test_div_by_zero_decimal() {
1127        let a = Decimal::from(5u32);
1128        let b = Decimal::from(0u32);
1129        assert!(a.checked_div(b).is_none());
1130    }
1131
1132    #[test]
1133    fn test_powi_exp_overflow_decimal() {
1134        let a = Decimal::from(5u32);
1135        let b = i64::MIN;
1136        assert!(a.checked_powi(b).is_none());
1137    }
1138
1139    #[test]
1140    fn test_1_powi_max_decimal() {
1141        let a = Decimal::from(1u32);
1142        let b = i64::MAX;
1143        assert_eq!(a.checked_powi(b).unwrap().to_string(), "1");
1144    }
1145
1146    #[test]
1147    fn test_1_powi_min_decimal() {
1148        let a = Decimal::from(1u32);
1149        let b = i64::MAX - 1;
1150        assert_eq!(a.checked_powi(b).unwrap().to_string(), "1");
1151    }
1152
1153    #[test]
1154    fn test_powi_max_decimal() {
1155        let _max = Decimal::MAX.checked_powi(1);
1156        let _max_sqrt = Decimal::MAX.checked_sqrt().unwrap();
1157        let _max_cbrt = Decimal::MAX.checked_cbrt().unwrap();
1158        let _max_dec_2 = _max_sqrt.checked_powi(2).unwrap();
1159        let _max_dec_3 = _max_cbrt.checked_powi(3).unwrap();
1160    }
1161
1162    #[test]
1163    fn test_div_decimal() {
1164        let a = Decimal::from(5u32);
1165        let b = Decimal::from(7u32);
1166        assert_eq!(
1167            a.checked_div(b).unwrap().to_string(),
1168            "0.714285714285714285"
1169        );
1170        assert_eq!(b.checked_div(a).unwrap().to_string(), "1.4");
1171        assert_eq!(
1172            Decimal::MAX.checked_div(test_dec!(1)).unwrap(),
1173            Decimal::MAX
1174        );
1175    }
1176
1177    #[test]
1178    fn test_div_negative_decimal() {
1179        let a = Decimal::from(-42);
1180        let b = Decimal::from(2);
1181        assert_eq!(a.checked_div(b).unwrap().to_string(), "-21");
1182    }
1183
1184    #[test]
1185    fn test_0_pow_0_decimal() {
1186        let a = test_dec!("0");
1187        assert_eq!((a.checked_powi(0).unwrap()).to_string(), "1");
1188    }
1189
1190    #[test]
1191    fn test_0_powi_1_decimal() {
1192        let a = test_dec!("0");
1193        assert_eq!((a.checked_powi(1).unwrap()).to_string(), "0");
1194    }
1195
1196    #[test]
1197    fn test_0_powi_10_decimal() {
1198        let a = test_dec!("0");
1199        assert_eq!((a.checked_powi(10).unwrap()).to_string(), "0");
1200    }
1201
1202    #[test]
1203    fn test_1_powi_0_decimal() {
1204        let a = test_dec!(1);
1205        assert_eq!((a.checked_powi(0).unwrap()).to_string(), "1");
1206    }
1207
1208    #[test]
1209    fn test_1_powi_1_decimal() {
1210        let a = test_dec!(1);
1211        assert_eq!((a.checked_powi(1).unwrap()).to_string(), "1");
1212    }
1213
1214    #[test]
1215    fn test_1_powi_10_decimal() {
1216        let a = test_dec!(1);
1217        assert_eq!((a.checked_powi(10).unwrap()).to_string(), "1");
1218    }
1219
1220    #[test]
1221    fn test_2_powi_0_decimal() {
1222        let a = test_dec!("2");
1223        assert_eq!(a.checked_powi(0).unwrap().to_string(), "1");
1224    }
1225
1226    #[test]
1227    fn test_2_powi_3724_decimal() {
1228        let a = test_dec!("1.000234891009084238");
1229        assert_eq!(
1230            a.checked_powi(3724).unwrap().to_string(),
1231            "2.397991232254669619"
1232        );
1233    }
1234
1235    #[test]
1236    fn test_2_powi_2_decimal() {
1237        let a = test_dec!("2");
1238        assert_eq!(a.checked_powi(2).unwrap().to_string(), "4");
1239    }
1240
1241    #[test]
1242    fn test_2_powi_3_decimal() {
1243        let a = test_dec!("2");
1244        assert_eq!(a.checked_powi(3).unwrap().to_string(), "8");
1245    }
1246
1247    #[test]
1248    fn test_10_powi_3_decimal() {
1249        let a = test_dec!("10");
1250        assert_eq!(a.checked_powi(3).unwrap().to_string(), "1000");
1251    }
1252
1253    #[test]
1254    fn test_5_powi_2_decimal() {
1255        let a = test_dec!("5");
1256        assert_eq!(a.checked_powi(2).unwrap().to_string(), "25");
1257    }
1258
1259    #[test]
1260    fn test_5_powi_minus2_decimal() {
1261        let a = test_dec!("5");
1262        assert_eq!(a.checked_powi(-2).unwrap().to_string(), "0.04");
1263    }
1264
1265    #[test]
1266    fn test_10_powi_minus3_decimal() {
1267        let a = test_dec!("10");
1268        assert_eq!(a.checked_powi(-3).unwrap().to_string(), "0.001");
1269    }
1270
1271    #[test]
1272    fn test_minus10_powi_minus3_decimal() {
1273        let a = test_dec!("-10");
1274        assert_eq!(a.checked_powi(-3).unwrap().to_string(), "-0.001");
1275    }
1276
1277    #[test]
1278    fn test_minus10_powi_minus2_decimal() {
1279        let a = test_dec!("-10");
1280        assert_eq!(a.checked_powi(-2).unwrap().to_string(), "0.01");
1281    }
1282
1283    #[test]
1284    fn test_minus05_powi_minus2_decimal() {
1285        let a = test_dec!("-0.5");
1286        assert_eq!(a.checked_powi(-2).unwrap().to_string(), "4");
1287    }
1288    #[test]
1289    fn test_minus05_powi_minus3_decimal() {
1290        let a = test_dec!("-0.5");
1291        assert_eq!(a.checked_powi(-3).unwrap().to_string(), "-8");
1292    }
1293
1294    #[test]
1295    fn test_10_powi_15_decimal() {
1296        let a = test_dec!(10i128);
1297        assert_eq!(a.checked_powi(15).unwrap().to_string(), "1000000000000000");
1298    }
1299
1300    #[test]
1301    fn test_10_powi_16_decimal() {
1302        let a = Decimal(10i128.into());
1303        assert_eq!(a.checked_powi(16).unwrap().to_string(), "0");
1304    }
1305
1306    #[test]
1307    fn test_one_and_zero_decimal() {
1308        assert_eq!(Decimal::one().to_string(), "1");
1309        assert_eq!(Decimal::zero().to_string(), "0");
1310    }
1311
1312    #[test]
1313    fn test_dec_string_decimal_decimal() {
1314        assert_eq!(
1315            test_dec!("1.123456789012345678").to_string(),
1316            "1.123456789012345678"
1317        );
1318        assert_eq!(test_dec!("-5.6").to_string(), "-5.6");
1319    }
1320
1321    #[test]
1322    fn test_dec_string_decimal() {
1323        assert_eq!(test_dec!(1).to_string(), "1");
1324        assert_eq!(test_dec!("0").to_string(), "0");
1325    }
1326
1327    #[test]
1328    fn test_dec_int_decimal() {
1329        assert_eq!(test_dec!(1).to_string(), "1");
1330        assert_eq!(test_dec!(5).to_string(), "5");
1331    }
1332
1333    #[test]
1334    fn test_dec_bool_decimal() {
1335        assert_eq!((test_dec!(false)).to_string(), "0");
1336    }
1337
1338    #[test]
1339    fn test_floor_decimal() {
1340        assert_eq!(
1341            Decimal::MAX.checked_floor().unwrap(),
1342            test_dec!("3138550867693340381917894711603833208051")
1343        );
1344        assert_eq!(test_dec!("1.2").checked_floor().unwrap(), test_dec!("1"));
1345        assert_eq!(test_dec!("1.0").checked_floor().unwrap(), test_dec!("1"));
1346        assert_eq!(test_dec!("0.9").checked_floor().unwrap(), test_dec!("0"));
1347        assert_eq!(test_dec!("0").checked_floor().unwrap(), test_dec!("0"));
1348        assert_eq!(test_dec!("-0.1").checked_floor().unwrap(), test_dec!("-1"));
1349        assert_eq!(test_dec!("-1").checked_floor().unwrap(), test_dec!("-1"));
1350        assert_eq!(test_dec!("-5.2").checked_floor().unwrap(), test_dec!("-6"));
1351
1352        assert_eq!(
1353            test_dec!("-3138550867693340381917894711603833208050.177722232017256448") // Decimal::MIN+1
1354                .checked_floor()
1355                .unwrap(),
1356            test_dec!("-3138550867693340381917894711603833208051")
1357        );
1358        assert_eq!(
1359            test_dec!("-3138550867693340381917894711603833208050.000000000000000001")
1360                .checked_floor()
1361                .unwrap(),
1362            test_dec!("-3138550867693340381917894711603833208051")
1363        );
1364        assert_eq!(
1365            test_dec!("-3138550867693340381917894711603833208051.000000000000000000")
1366                .checked_floor()
1367                .unwrap(),
1368            test_dec!("-3138550867693340381917894711603833208051")
1369        );
1370
1371        // below shall return None due to overflow
1372        assert!(Decimal::MIN.checked_floor().is_none());
1373
1374        assert!(
1375            test_dec!("-3138550867693340381917894711603833208051.000000000000000001")
1376                .checked_floor()
1377                .is_none()
1378        );
1379    }
1380
1381    #[test]
1382    fn test_abs_decimal() {
1383        assert_eq!(test_dec!(-2).checked_abs().unwrap(), test_dec!(2));
1384        assert_eq!(test_dec!(2).checked_abs().unwrap(), test_dec!(2));
1385        assert_eq!(test_dec!(0).checked_abs().unwrap(), test_dec!(0));
1386        assert_eq!(Decimal::MAX.checked_abs().unwrap(), Decimal::MAX);
1387
1388        // below shall return None due to overflow
1389        assert!(Decimal::MIN.checked_abs().is_none());
1390    }
1391
1392    #[test]
1393    fn test_ceiling_decimal() {
1394        assert_eq!(test_dec!("1.2").checked_ceiling().unwrap(), test_dec!("2"));
1395        assert_eq!(test_dec!("1.0").checked_ceiling().unwrap(), test_dec!("1"));
1396        assert_eq!(test_dec!("0.9").checked_ceiling().unwrap(), test_dec!("1"));
1397        assert_eq!(test_dec!("0").checked_ceiling().unwrap(), test_dec!("0"));
1398        assert_eq!(test_dec!("-0.1").checked_ceiling().unwrap(), test_dec!("0"));
1399        assert_eq!(test_dec!("-1").checked_ceiling().unwrap(), test_dec!("-1"));
1400        assert_eq!(
1401            test_dec!("-5.2").checked_ceiling().unwrap(),
1402            test_dec!("-5")
1403        );
1404        assert_eq!(
1405            Decimal::MIN.checked_ceiling().unwrap(),
1406            test_dec!("-3138550867693340381917894711603833208051")
1407        );
1408        assert_eq!(
1409            test_dec!("3138550867693340381917894711603833208050.177722232017256447") // Decimal::MAX-1
1410                .checked_ceiling()
1411                .unwrap(),
1412            test_dec!("3138550867693340381917894711603833208051")
1413        );
1414        assert_eq!(
1415            test_dec!("3138550867693340381917894711603833208050.000000000000000000")
1416                .checked_ceiling()
1417                .unwrap(),
1418            test_dec!("3138550867693340381917894711603833208050")
1419        );
1420
1421        // below shall return None due to overflow
1422        assert!(Decimal::MAX.checked_ceiling().is_none());
1423        assert!(
1424            test_dec!("3138550867693340381917894711603833208051.000000000000000001")
1425                .checked_ceiling()
1426                .is_none()
1427        );
1428    }
1429
1430    #[test]
1431    fn test_rounding_to_zero_decimal() {
1432        let mode = RoundingMode::ToZero;
1433        assert_eq!(
1434            test_dec!("1.2").checked_round(0, mode).unwrap(),
1435            test_dec!("1")
1436        );
1437        assert_eq!(
1438            test_dec!("1.0").checked_round(0, mode).unwrap(),
1439            test_dec!("1")
1440        );
1441        assert_eq!(
1442            test_dec!("0.9").checked_round(0, mode).unwrap(),
1443            test_dec!("0")
1444        );
1445        assert_eq!(
1446            test_dec!("0").checked_round(0, mode).unwrap(),
1447            test_dec!("0")
1448        );
1449        assert_eq!(
1450            test_dec!("-0.1").checked_round(0, mode).unwrap(),
1451            test_dec!("0")
1452        );
1453        assert_eq!(
1454            test_dec!("-1").checked_round(0, mode).unwrap(),
1455            test_dec!("-1")
1456        );
1457        assert_eq!(
1458            test_dec!("-5.2").checked_round(0, mode).unwrap(),
1459            test_dec!("-5")
1460        );
1461        assert_eq!(
1462            Decimal::MAX.checked_round(0, mode).unwrap(),
1463            test_dec!("3138550867693340381917894711603833208051")
1464        );
1465        assert_eq!(
1466            Decimal::MIN.checked_round(0, mode).unwrap(),
1467            test_dec!("-3138550867693340381917894711603833208051")
1468        );
1469    }
1470
1471    #[test]
1472    fn test_rounding_away_from_zero_decimal() {
1473        let mode = RoundingMode::AwayFromZero;
1474        assert_eq!(
1475            test_dec!("1.2").checked_round(0, mode).unwrap(),
1476            test_dec!("2")
1477        );
1478        assert_eq!(
1479            test_dec!("1.0").checked_round(0, mode).unwrap(),
1480            test_dec!("1")
1481        );
1482        assert_eq!(
1483            test_dec!("0.9").checked_round(0, mode).unwrap(),
1484            test_dec!("1")
1485        );
1486        assert_eq!(
1487            test_dec!("0").checked_round(0, mode).unwrap(),
1488            test_dec!("0")
1489        );
1490        assert_eq!(
1491            test_dec!("-0.1").checked_round(0, mode).unwrap(),
1492            test_dec!("-1")
1493        );
1494        assert_eq!(
1495            test_dec!("-1").checked_round(0, mode).unwrap(),
1496            test_dec!("-1")
1497        );
1498        assert_eq!(
1499            test_dec!("-5.2").checked_round(0, mode).unwrap(),
1500            test_dec!("-6")
1501        );
1502
1503        assert_eq!(
1504            test_dec!("-3138550867693340381917894711603833208050.9")
1505                .checked_round(0, mode)
1506                .unwrap(),
1507            test_dec!("-3138550867693340381917894711603833208051")
1508        );
1509        assert_eq!(
1510            test_dec!("3138550867693340381917894711603833208050.9")
1511                .checked_round(0, mode)
1512                .unwrap(),
1513            test_dec!("3138550867693340381917894711603833208051")
1514        );
1515
1516        // below shall return None due to overflow
1517        assert!(Decimal::MIN.checked_round(0, mode).is_none());
1518        assert!(test_dec!("-3138550867693340381917894711603833208051.1")
1519            .checked_round(0, mode)
1520            .is_none());
1521        assert!(Decimal::MAX.checked_round(0, mode).is_none());
1522        assert!(test_dec!("3138550867693340381917894711603833208051.1")
1523            .checked_round(0, mode)
1524            .is_none());
1525    }
1526
1527    #[test]
1528    fn test_rounding_midpoint_toward_zero_decimal() {
1529        let mode = RoundingMode::ToNearestMidpointTowardZero;
1530        assert_eq!(
1531            test_dec!("5.5").checked_round(0, mode).unwrap(),
1532            test_dec!("5")
1533        );
1534        assert_eq!(
1535            test_dec!("2.5").checked_round(0, mode).unwrap(),
1536            test_dec!("2")
1537        );
1538        assert_eq!(
1539            test_dec!("1.6").checked_round(0, mode).unwrap(),
1540            test_dec!("2")
1541        );
1542        assert_eq!(
1543            test_dec!("1.1").checked_round(0, mode).unwrap(),
1544            test_dec!("1")
1545        );
1546        assert_eq!(
1547            test_dec!("1.0").checked_round(0, mode).unwrap(),
1548            test_dec!("1")
1549        );
1550        assert_eq!(
1551            test_dec!("-1.0").checked_round(0, mode).unwrap(),
1552            test_dec!("-1")
1553        );
1554        assert_eq!(
1555            test_dec!("-1.1").checked_round(0, mode).unwrap(),
1556            test_dec!("-1")
1557        );
1558        assert_eq!(
1559            test_dec!("-1.6").checked_round(0, mode).unwrap(),
1560            test_dec!("-2")
1561        );
1562        assert_eq!(
1563            test_dec!("-2.5").checked_round(0, mode).unwrap(),
1564            test_dec!("-2")
1565        );
1566        assert_eq!(
1567            test_dec!("-5.5").checked_round(0, mode).unwrap(),
1568            test_dec!("-5")
1569        );
1570        assert_eq!(
1571            Decimal::MAX.checked_round(0, mode).unwrap(),
1572            test_dec!("3138550867693340381917894711603833208051")
1573        );
1574        assert_eq!(
1575            Decimal::MIN.checked_round(0, mode).unwrap(),
1576            test_dec!("-3138550867693340381917894711603833208051")
1577        );
1578    }
1579
1580    #[test]
1581    fn test_rounding_midpoint_away_from_zero_decimal() {
1582        let mode = RoundingMode::ToNearestMidpointAwayFromZero;
1583        assert_eq!(
1584            test_dec!("5.5").checked_round(0, mode).unwrap(),
1585            test_dec!("6")
1586        );
1587        assert_eq!(
1588            test_dec!("2.5").checked_round(0, mode).unwrap(),
1589            test_dec!("3")
1590        );
1591        assert_eq!(
1592            test_dec!("1.6").checked_round(0, mode).unwrap(),
1593            test_dec!("2")
1594        );
1595        assert_eq!(
1596            test_dec!("1.1").checked_round(0, mode).unwrap(),
1597            test_dec!("1")
1598        );
1599        assert_eq!(
1600            test_dec!("1.0").checked_round(0, mode).unwrap(),
1601            test_dec!("1")
1602        );
1603        assert_eq!(
1604            test_dec!("-1.0").checked_round(0, mode).unwrap(),
1605            test_dec!("-1")
1606        );
1607        assert_eq!(
1608            test_dec!("-1.1").checked_round(0, mode).unwrap(),
1609            test_dec!("-1")
1610        );
1611        assert_eq!(
1612            test_dec!("-1.6").checked_round(0, mode).unwrap(),
1613            test_dec!("-2")
1614        );
1615        assert_eq!(
1616            test_dec!("-2.5").checked_round(0, mode).unwrap(),
1617            test_dec!("-3")
1618        );
1619        assert_eq!(
1620            test_dec!("-5.5").checked_round(0, mode).unwrap(),
1621            test_dec!("-6")
1622        );
1623        assert_eq!(
1624            Decimal::MAX.checked_round(0, mode).unwrap(),
1625            test_dec!("3138550867693340381917894711603833208051")
1626        );
1627        assert_eq!(
1628            Decimal::MIN.checked_round(0, mode).unwrap(),
1629            test_dec!("-3138550867693340381917894711603833208051")
1630        );
1631    }
1632
1633    #[test]
1634    fn test_rounding_midpoint_nearest_even_zero_decimal() {
1635        let mode = RoundingMode::ToNearestMidpointToEven;
1636        assert_eq!(
1637            test_dec!("5.5").checked_round(0, mode).unwrap(),
1638            test_dec!("6")
1639        );
1640        assert_eq!(
1641            test_dec!("2.5").checked_round(0, mode).unwrap(),
1642            test_dec!("2")
1643        );
1644        assert_eq!(
1645            test_dec!("1.6").checked_round(0, mode).unwrap(),
1646            test_dec!("2")
1647        );
1648        assert_eq!(
1649            test_dec!("1.1").checked_round(0, mode).unwrap(),
1650            test_dec!("1")
1651        );
1652        assert_eq!(
1653            test_dec!("1.0").checked_round(0, mode).unwrap(),
1654            test_dec!("1")
1655        );
1656        assert_eq!(
1657            test_dec!("-1.0").checked_round(0, mode).unwrap(),
1658            test_dec!("-1")
1659        );
1660        assert_eq!(
1661            test_dec!("-1.1").checked_round(0, mode).unwrap(),
1662            test_dec!("-1")
1663        );
1664        assert_eq!(
1665            test_dec!("-1.6").checked_round(0, mode).unwrap(),
1666            test_dec!("-2")
1667        );
1668        assert_eq!(
1669            test_dec!("-2.5").checked_round(0, mode).unwrap(),
1670            test_dec!("-2")
1671        );
1672        assert_eq!(
1673            test_dec!("-5.5").checked_round(0, mode).unwrap(),
1674            test_dec!("-6")
1675        );
1676
1677        assert_eq!(
1678            Decimal::MAX.checked_round(0, mode).unwrap(),
1679            test_dec!("3138550867693340381917894711603833208051")
1680        );
1681        assert_eq!(
1682            Decimal::MIN.checked_round(0, mode).unwrap(),
1683            test_dec!("-3138550867693340381917894711603833208051")
1684        );
1685    }
1686
1687    #[test]
1688    fn test_various_decimal_places_decimal() {
1689        let num = test_dec!("2.4595");
1690        let mode = RoundingMode::AwayFromZero;
1691        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("3"));
1692        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.5"));
1693        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.46"));
1694        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.46"));
1695
1696        assert_eq!(
1697            test_dec!("3138550867693340381917894711603833208050.177722232017256447")
1698                .checked_round(1, mode)
1699                .unwrap(),
1700            test_dec!("3138550867693340381917894711603833208050.2")
1701        );
1702        assert_eq!(
1703            test_dec!("-3138550867693340381917894711603833208050.177722232017256448")
1704                .checked_round(1, mode)
1705                .unwrap(),
1706            test_dec!("-3138550867693340381917894711603833208050.2")
1707        );
1708
1709        let mode = RoundingMode::ToZero;
1710        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("2"));
1711        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.4"));
1712        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.45"));
1713        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.459"));
1714        let mode = RoundingMode::ToPositiveInfinity;
1715        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("3"));
1716        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.5"));
1717        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.46"));
1718        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.46"));
1719        let mode = RoundingMode::ToNegativeInfinity;
1720        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("2"));
1721        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.4"));
1722        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.45"));
1723        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.459"));
1724        let mode = RoundingMode::ToNearestMidpointAwayFromZero;
1725        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("2"));
1726        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.5"));
1727        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.46"));
1728        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.46"));
1729        let mode = RoundingMode::ToNearestMidpointTowardZero;
1730        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("2"));
1731        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.5"));
1732        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.46"));
1733        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.459"));
1734        let mode = RoundingMode::ToNearestMidpointToEven;
1735        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("2"));
1736        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("2.5"));
1737        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("2.46"));
1738        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("2.46"));
1739
1740        let num = test_dec!("-2.4595");
1741        let mode = RoundingMode::AwayFromZero;
1742        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-3"));
1743        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.5"));
1744        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.46"));
1745        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.46"));
1746        let mode = RoundingMode::ToZero;
1747        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-2"));
1748        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.4"));
1749        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.45"));
1750        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.459"));
1751        let mode = RoundingMode::ToPositiveInfinity;
1752        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-2"));
1753        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.4"));
1754        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.45"));
1755        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.459"));
1756        let mode = RoundingMode::ToNegativeInfinity;
1757        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-3"));
1758        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.5"));
1759        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.46"));
1760        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.46"));
1761        let mode = RoundingMode::ToNearestMidpointAwayFromZero;
1762        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-2"));
1763        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.5"));
1764        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.46"));
1765        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.46"));
1766        let mode = RoundingMode::ToNearestMidpointTowardZero;
1767        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-2"));
1768        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.5"));
1769        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.46"));
1770        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.459"));
1771        let mode = RoundingMode::ToNearestMidpointToEven;
1772        assert_eq!(num.checked_round(0, mode).unwrap(), test_dec!("-2"));
1773        assert_eq!(num.checked_round(1, mode).unwrap(), test_dec!("-2.5"));
1774        assert_eq!(num.checked_round(2, mode).unwrap(), test_dec!("-2.46"));
1775        assert_eq!(num.checked_round(3, mode).unwrap(), test_dec!("-2.46"));
1776    }
1777
1778    #[test]
1779    fn test_encode_decimal_value_decimal() {
1780        let dec = test_dec!("0");
1781        let bytes = scrypto_encode(&dec).unwrap();
1782        assert_eq!(bytes, {
1783            let mut a = [0; 26];
1784            a[0] = SCRYPTO_SBOR_V1_PAYLOAD_PREFIX;
1785            a[1] = ScryptoValueKind::Custom(ScryptoCustomValueKind::Decimal).as_u8();
1786            a
1787        });
1788    }
1789
1790    #[test]
1791    fn test_decode_decimal_value_decimal() {
1792        let dec = test_dec!("1.23456789");
1793        let bytes = scrypto_encode(&dec).unwrap();
1794        let decoded: Decimal = scrypto_decode(&bytes).unwrap();
1795        assert_eq!(decoded, test_dec!("1.23456789"));
1796    }
1797
1798    #[test]
1799    fn test_from_str_decimal() {
1800        let dec = Decimal::from_str("5.0").unwrap();
1801        assert_eq!(dec.to_string(), "5");
1802    }
1803
1804    #[test]
1805    fn test_from_str_failure_decimal() {
1806        let dec = Decimal::from_str("non_decimal_value");
1807        assert_eq!(dec, Err(ParseDecimalError::InvalidDigit));
1808    }
1809
1810    macro_rules! test_from_into_precise_decimal_decimal {
1811        ($(($from:expr, $expected:expr, $suffix:expr)),*) => {
1812            paste!{
1813            $(
1814                #[test]
1815                fn [<test_from_into_precise_decimal_decimal_ $suffix>]() {
1816                    let pdec = PreciseDecimal::try_from($from).unwrap();
1817                    let dec = Decimal::try_from(pdec).unwrap();
1818                    assert_eq!(dec.to_string(), $expected);
1819
1820                    let dec: Decimal = pdec.try_into().unwrap();
1821                    assert_eq!(dec.to_string(), $expected);
1822                }
1823            )*
1824            }
1825        };
1826    }
1827
1828    test_from_into_precise_decimal_decimal! {
1829        ("12345678.123456789012345678901234567890123456", "12345678.123456789012345678", 1),
1830        ("12345678.123456789012345678101234567890123456", "12345678.123456789012345678", 2),
1831        ("-12345678.123456789012345678901234567890123456", "-12345678.123456789012345678", 3),
1832        ("-12345678.123456789012345678101234567890123456", "-12345678.123456789012345678", 4),
1833        ("0.000000000000000000000000008901234567", "0", 5),
1834        ("-0.000000000000000000000000008901234567", "0", 6),
1835        ("5", "5", 7),
1836        ("12345678.1", "12345678.1", 8)
1837    }
1838
1839    macro_rules! test_from_precise_decimal_decimal_overflow {
1840        ($(($from:expr, $suffix:expr)),*) => {
1841            paste!{
1842            $(
1843                #[test]
1844                fn [<test_from_precise_decimal_decimal_overflow_ $suffix>]() {
1845                    let err = Decimal::try_from($from).unwrap_err();
1846                    assert_eq!(err, ParseDecimalError::Overflow);
1847                }
1848            )*
1849            }
1850        };
1851    }
1852
1853    test_from_precise_decimal_decimal_overflow! {
1854        (PreciseDecimal::MAX, 1),
1855        (PreciseDecimal::MIN, 2),
1856        (PreciseDecimal::from(Decimal::MAX).checked_add(Decimal::ONE).unwrap(), 3),
1857        (PreciseDecimal::from(Decimal::MIN).checked_sub(Decimal::ONE).unwrap(), 4)
1858    }
1859
1860    macro_rules! test_try_from_integer_overflow {
1861        ($(($from:expr, $suffix:expr)),*) => {
1862            paste!{
1863            $(
1864                #[test]
1865                fn [<test_try_from_integer_overflow_ $suffix>]() {
1866                    let err = Decimal::try_from($from).unwrap_err();
1867                    assert_eq!(err, ParseDecimalError::Overflow)
1868                }
1869            )*
1870            }
1871        };
1872    }
1873
1874    test_try_from_integer_overflow! {
1875        (I192::MAX, 1),
1876        (I192::MIN, 2),
1877        // maximal Decimal integer part + 1
1878        (I192::MAX/(I192::from(10).pow(Decimal::SCALE)) + I192::ONE, 3),
1879        // minimal Decimal integer part - 1
1880        (I192::MIN/(I192::from(10).pow(Decimal::SCALE)) - I192::ONE, 4),
1881        (I256::MAX, 5),
1882        (I256::MIN, 6),
1883        (I320::MAX, 7),
1884        (I320::MIN, 8),
1885        (I448::MAX, 9),
1886        (I448::MIN, 10),
1887        (I512::MAX, 11),
1888        (I512::MIN, 12),
1889        (U192::MAX, 13),
1890        (U256::MAX, 14),
1891        (U320::MAX, 15),
1892        (U448::MAX, 16),
1893        (U512::MAX, 17)
1894    }
1895
1896    macro_rules! test_try_from_integer {
1897        ($(($from:expr, $expected:expr, $suffix:expr)),*) => {
1898            paste!{
1899            $(
1900                #[test]
1901                fn [<test_try_from_integer_ $suffix>]() {
1902                    let dec = Decimal::try_from($from).unwrap();
1903                    assert_eq!(dec.to_string(), $expected)
1904                }
1905            )*
1906            }
1907        };
1908    }
1909
1910    test_try_from_integer! {
1911        (I192::ONE, "1", 1),
1912        (-I192::ONE, "-1", 2),
1913        (I256::ONE, "1", 3),
1914        (-I256::ONE, "-1", 4),
1915        (I320::ONE, "1", 5),
1916        (-I320::ONE, "-1", 6),
1917        (I448::ONE, "1", 7),
1918        (-I448::ONE, "-1", 8),
1919        (I512::ONE, "1", 9),
1920        (-I512::ONE, "-1", 10),
1921        // maximal Decimal integer part
1922        (I192::MAX/(I192::from(10_u64.pow(Decimal::SCALE))), "3138550867693340381917894711603833208051", 11),
1923        // minimal Decimal integer part
1924        (I192::MIN/(I192::from(10_u64.pow(Decimal::SCALE))), "-3138550867693340381917894711603833208051", 12),
1925        (U192::MIN, "0", 13),
1926        (U256::MIN, "0", 14),
1927        (U320::MIN, "0", 15),
1928        (U448::MIN, "0", 16),
1929        (U512::MIN, "0", 17)
1930    }
1931
1932    #[test]
1933    fn test_sqrt() {
1934        let sqrt_of_42 = test_dec!(42).checked_sqrt();
1935        let sqrt_of_0 = test_dec!(0).checked_sqrt();
1936        let sqrt_of_negative = test_dec!("-1").checked_sqrt();
1937        let sqrt_max = Decimal::MAX.checked_sqrt();
1938        assert_eq!(sqrt_of_42.unwrap(), test_dec!("6.48074069840786023"));
1939        assert_eq!(sqrt_of_0.unwrap(), test_dec!(0));
1940        assert_eq!(sqrt_of_negative, None);
1941        assert_eq!(
1942            sqrt_max.unwrap(),
1943            test_dec!("56022770974786139918.731938227458171762")
1944        );
1945    }
1946
1947    #[test]
1948    fn test_cbrt() {
1949        let cbrt_of_42 = test_dec!(42).checked_cbrt().unwrap();
1950        let cbrt_of_0 = test_dec!(0).checked_cbrt().unwrap();
1951        let cbrt_of_negative_42 = test_dec!("-42").checked_cbrt().unwrap();
1952        let cbrt_max = Decimal::MAX.checked_cbrt().unwrap();
1953        assert_eq!(cbrt_of_42, test_dec!("3.476026644886449786"));
1954        assert_eq!(cbrt_of_0, test_dec!("0"));
1955        assert_eq!(cbrt_of_negative_42, test_dec!("-3.476026644886449786"));
1956        assert_eq!(cbrt_max, test_dec!("14641190473997.345813510937532903"));
1957    }
1958
1959    #[test]
1960    fn test_nth_root() {
1961        let root_4_42 = test_dec!(42).checked_nth_root(4);
1962        let root_5_42 = test_dec!(42).checked_nth_root(5);
1963        let root_42_42 = test_dec!(42).checked_nth_root(42);
1964        let root_neg_4_42 = test_dec!("-42").checked_nth_root(4);
1965        let root_neg_5_42 = test_dec!("-42").checked_nth_root(5);
1966        let root_0 = test_dec!(42).checked_nth_root(0);
1967        assert_eq!(root_4_42.unwrap(), test_dec!("2.545729895021830518"));
1968        assert_eq!(root_5_42.unwrap(), test_dec!("2.111785764966753912"));
1969        assert_eq!(root_42_42.unwrap(), test_dec!("1.093072057934823618"));
1970        assert_eq!(root_neg_4_42, None);
1971        assert_eq!(root_neg_5_42.unwrap(), test_dec!("-2.111785764966753912"));
1972        assert_eq!(root_0, None);
1973    }
1974
1975    #[test]
1976    fn no_panic_with_18_decimal_places() {
1977        // Arrange
1978        let string = "1.111111111111111111";
1979
1980        // Act
1981        let decimal = Decimal::from_str(string);
1982
1983        // Assert
1984        assert!(decimal.is_ok())
1985    }
1986
1987    #[test]
1988    fn no_panic_with_19_decimal_places() {
1989        // Arrange
1990        let string = "1.1111111111111111111";
1991
1992        // Act
1993        let decimal = Decimal::from_str(string);
1994
1995        // Assert
1996        assert_matches!(
1997            decimal,
1998            Err(ParseDecimalError::MoreThanEighteenDecimalPlaces)
1999        );
2000    }
2001
2002    #[test]
2003    fn test_neg_decimal() {
2004        let d = Decimal::ONE;
2005        assert_eq!(-d, test_dec!("-1"));
2006        let d = Decimal::MAX;
2007        assert_eq!(-d, Decimal(I192::MIN + I192::ONE));
2008    }
2009
2010    #[test]
2011    #[should_panic(expected = "Overflow")]
2012    fn test_neg_decimal_panic() {
2013        let d = Decimal::MIN;
2014        let _ = -d;
2015    }
2016
2017    // These tests make sure that any basic arithmetic operation
2018    // between primitive type and Decimal produces a Decimal.
2019    // Example:
2020    //   Decimal(10) * 10_u32 -> Decimal(100)
2021    macro_rules! test_arith_decimal_primitive {
2022        ($type:ident) => {
2023            paste! {
2024                #[test]
2025                fn [<test_arith_decimal_$type>]() {
2026                    let d1 = test_dec!("2");
2027                    let u1 = $type::try_from(4).unwrap();
2028                    assert_eq!(d1.checked_add(u1).unwrap(), test_dec!("6"));
2029                    assert_eq!(d1.checked_sub(u1).unwrap(), test_dec!("-2"));
2030                    assert_eq!(d1.checked_mul(u1).unwrap(), test_dec!("8"));
2031                    assert_eq!(d1.checked_div(u1).unwrap(), test_dec!("0.5"));
2032
2033                    let d1 = test_dec!("2");
2034                    let u1 = $type::MAX;
2035                    let d2 = Decimal::from($type::MAX);
2036                    assert_eq!(d1.checked_add(u1).unwrap(), d1.checked_add(d2).unwrap());
2037                    assert_eq!(d1.checked_sub(u1).unwrap(), d1.checked_sub(d2).unwrap());
2038                    assert_eq!(d1.checked_mul(u1).unwrap(), d1.checked_mul(d2).unwrap());
2039                    assert_eq!(d1.checked_div(u1).unwrap(), d1.checked_div(d2).unwrap());
2040
2041                    let d1 = Decimal::from($type::MIN);
2042                    let u1 = 2 as $type;
2043                    let d2 = test_dec!("2");
2044                    assert_eq!(d1.checked_add(u1).unwrap(), d1.checked_add(d2).unwrap());
2045                    assert_eq!(d1.checked_sub(u1).unwrap(), d1.checked_sub(d2).unwrap());
2046                    assert_eq!(d1.checked_mul(u1).unwrap(), d1.checked_mul(d2).unwrap());
2047                    assert_eq!(d1.checked_div(u1).unwrap(), d1.checked_div(d2).unwrap());
2048                }
2049            }
2050        };
2051    }
2052    test_arith_decimal_primitive!(u8);
2053    test_arith_decimal_primitive!(u16);
2054    test_arith_decimal_primitive!(u32);
2055    test_arith_decimal_primitive!(u64);
2056    test_arith_decimal_primitive!(u128);
2057    test_arith_decimal_primitive!(usize);
2058    test_arith_decimal_primitive!(i8);
2059    test_arith_decimal_primitive!(i16);
2060    test_arith_decimal_primitive!(i32);
2061    test_arith_decimal_primitive!(i64);
2062    test_arith_decimal_primitive!(i128);
2063    test_arith_decimal_primitive!(isize);
2064
2065    macro_rules! test_arith_decimal_integer {
2066        ($type:ident) => {
2067            paste! {
2068                #[test]
2069                fn [<test_arith_decimal_$type:lower>]() {
2070                    let d1 = test_dec!("2");
2071                    let u1 = $type::try_from(4).unwrap();
2072                    let u2 = $type::try_from(2).unwrap();
2073                    let d2 = test_dec!("4");
2074                    assert_eq!(d1.checked_add(u1).unwrap(), u2.checked_add(d2).unwrap());
2075                    assert_eq!(d1.checked_sub(u1).unwrap(), u2.checked_sub(d2).unwrap());
2076                    assert_eq!(d1.checked_mul(u1).unwrap(), u2.checked_mul(d2).unwrap());
2077                    assert_eq!(d1.checked_div(u1).unwrap(), u2.checked_div(d2).unwrap());
2078
2079                    let d1 = test_dec!("2");
2080                    let u1 = $type::MAX;
2081                    assert!(d1.checked_add(u1).is_none());
2082                    assert!(d1.checked_sub(u1).is_none());
2083                    assert!(d1.checked_mul(u1).is_none());
2084                    assert!(d1.checked_div(u1).is_none());
2085
2086                    let d1 = Decimal::MAX;
2087                    let u1 = $type::try_from(2).unwrap();
2088                    assert_eq!(d1.checked_add(u1), None);
2089                    assert_eq!(d1.checked_sub(u1).unwrap(), Decimal::MAX - test_dec!("2"));
2090                    assert_eq!(d1.checked_mul(u1), None);
2091                    assert_eq!(d1.checked_div(u1).unwrap(), Decimal::MAX / test_dec!("2"));
2092
2093                }
2094            }
2095        };
2096    }
2097    test_arith_decimal_integer!(I192);
2098    test_arith_decimal_integer!(I256);
2099    test_arith_decimal_integer!(I512);
2100    test_arith_decimal_integer!(U192);
2101    test_arith_decimal_integer!(U256);
2102    test_arith_decimal_integer!(U512);
2103
2104    macro_rules! test_math_operands_decimal {
2105        ($type:ident) => {
2106            paste! {
2107                #[test]
2108                fn [<test_math_operands_decimal_$type:lower>]() {
2109                    let d1 = test_dec!("2");
2110                    let u1 = $type::try_from(4).unwrap();
2111                    assert_eq!(d1 + u1, test_dec!("6"));
2112                    assert_eq!(d1 - u1, test_dec!("-2"));
2113                    assert_eq!(d1 * u1, test_dec!("8"));
2114                    assert_eq!(d1 / u1, test_dec!("0.5"));
2115
2116                    let u1 = $type::try_from(2).unwrap();
2117                    let d1 = test_dec!("4");
2118                    assert_eq!(u1 + d1, test_dec!("6"));
2119                    assert_eq!(u1 - d1, test_dec!("-2"));
2120                    assert_eq!(u1 * d1, test_dec!("8"));
2121                    assert_eq!(u1 / d1, test_dec!("0.5"));
2122
2123                    let u1 = $type::try_from(4).unwrap();
2124
2125                    let mut d1 = test_dec!("2");
2126                    d1 += u1;
2127                    assert_eq!(d1, test_dec!("6"));
2128
2129                    let mut d1 = test_dec!("2");
2130                    d1 -= u1;
2131                    assert_eq!(d1, test_dec!("-2"));
2132
2133                    let mut d1 = test_dec!("2");
2134                    d1 *= u1;
2135                    assert_eq!(d1, test_dec!("8"));
2136
2137                    let mut d1 = test_dec!("2");
2138                    d1 /= u1;
2139                    assert_eq!(d1, test_dec!("0.5"));
2140                }
2141
2142                #[test]
2143                #[should_panic(expected = "Overflow")]
2144                fn [<test_math_add_decimal_$type:lower _panic>]() {
2145                    let d1 = Decimal::MAX;
2146                    let u1 = $type::try_from(1).unwrap();
2147                    let _ = d1 + u1;
2148                }
2149
2150                #[test]
2151                #[should_panic(expected = "Overflow")]
2152                fn [<test_math_add_$type:lower _xdecimal_panic>]() {
2153                    let d1 = Decimal::MAX;
2154                    let u1 = $type::try_from(1).unwrap();
2155                    let _ = u1 + d1;
2156                }
2157
2158                #[test]
2159                #[should_panic(expected = "Overflow")]
2160                fn [<test_math_sub_decimal_$type:lower _panic>]() {
2161                    let d1 = Decimal::MIN;
2162                    let u1 = $type::try_from(1).unwrap();
2163                    let _ = d1 - u1;
2164                }
2165
2166                #[test]
2167                #[should_panic(expected = "Overflow")]
2168                fn [<test_math_sub_$type:lower _xdecimal_panic>]() {
2169                    let d1 = Decimal::MIN;
2170                    let u1 = $type::try_from(1).unwrap();
2171                    let _ = u1 - d1;
2172                }
2173
2174                #[test]
2175                #[should_panic(expected = "Overflow")]
2176                fn [<test_math_mul_decimal_$type:lower _panic>]() {
2177                    let d1 = Decimal::MAX;
2178                    let u1 = $type::try_from(2).unwrap();
2179                    let _ = d1 * u1;
2180                }
2181
2182                #[test]
2183                #[should_panic(expected = "Overflow")]
2184                fn [<test_math_mul_$type:lower _xdecimal_panic>]() {
2185                    let d1 = Decimal::MAX;
2186                    let u1 = $type::try_from(2).unwrap();
2187                    let _ = u1 * d1;
2188                }
2189
2190                #[test]
2191                #[should_panic(expected = "Overflow")]
2192                fn [<test_math_div_zero_decimal_$type:lower _panic>]() {
2193                    let d1 = Decimal::MAX;
2194                    let u1 = $type::try_from(0).unwrap();
2195                    let _ = d1 / u1;
2196                }
2197
2198                #[test]
2199                #[should_panic(expected = "Overflow or division by zero")]
2200                fn [<test_math_div_zero_$type:lower _xdecimal_panic>]() {
2201                    let d1 = Decimal::ZERO;
2202                    let u1 = $type::try_from(1).unwrap();
2203                    let _ = u1 / d1;
2204                }
2205
2206                #[test]
2207                #[should_panic(expected = "Overflow")]
2208                fn [<test_math_add_assign_decimal_$type:lower _panic>]() {
2209                    let mut d1 = Decimal::MAX;
2210                    let u1 = $type::try_from(1).unwrap();
2211                    d1 += u1;
2212                }
2213
2214                #[test]
2215                #[should_panic(expected = "Overflow")]
2216                fn [<test_math_sub_assign_decimal_$type:lower _panic>]() {
2217                    let mut d1 = Decimal::MIN;
2218                    let u1 = $type::try_from(1).unwrap();
2219                    d1 -= u1;
2220                }
2221
2222                #[test]
2223                #[should_panic(expected = "Overflow")]
2224                fn [<test_math_mul_assign_decimal_$type:lower _panic>]() {
2225                    let mut d1 = Decimal::MAX;
2226                    let u1 = $type::try_from(2).unwrap();
2227                    d1 *= u1;
2228                }
2229
2230                #[test]
2231                #[should_panic(expected = "Overflow or division by zero")]
2232                fn [<test_math_div_assign_decimal_$type:lower _panic>]() {
2233                    let mut d1 = Decimal::MAX;
2234                    let u1 = $type::try_from(0).unwrap();
2235                    d1 /= u1;
2236                }
2237            }
2238        };
2239    }
2240    test_math_operands_decimal!(Decimal);
2241    test_math_operands_decimal!(u8);
2242    test_math_operands_decimal!(u16);
2243    test_math_operands_decimal!(u32);
2244    test_math_operands_decimal!(u64);
2245    test_math_operands_decimal!(u128);
2246    test_math_operands_decimal!(usize);
2247    test_math_operands_decimal!(i8);
2248    test_math_operands_decimal!(i16);
2249    test_math_operands_decimal!(i32);
2250    test_math_operands_decimal!(i64);
2251    test_math_operands_decimal!(i128);
2252    test_math_operands_decimal!(isize);
2253    test_math_operands_decimal!(I192);
2254    test_math_operands_decimal!(I256);
2255    test_math_operands_decimal!(I320);
2256    test_math_operands_decimal!(I448);
2257    test_math_operands_decimal!(I512);
2258    test_math_operands_decimal!(U192);
2259    test_math_operands_decimal!(U256);
2260    test_math_operands_decimal!(U320);
2261    test_math_operands_decimal!(U448);
2262    test_math_operands_decimal!(U512);
2263
2264    macro_rules! test_from_primitive_type {
2265        ($type:ident) => {
2266            paste! {
2267                #[test]
2268                fn [<test_decimal_from_primitive_$type>]() {
2269                    let v = $type::try_from(1).unwrap();
2270                    assert_eq!(Decimal::from(v), test_dec!(1));
2271
2272                    if $type::MIN != 0 {
2273                        let v = $type::try_from(-1).unwrap();
2274                        assert_eq!(Decimal::from(v), test_dec!(-1));
2275                    }
2276
2277                    let v = $type::MAX;
2278                    assert_eq!(Decimal::from(v), Decimal::from_str(&v.to_string()).unwrap());
2279
2280                    let v = $type::MIN;
2281                    assert_eq!(Decimal::from(v), Decimal::from_str(&v.to_string()).unwrap());
2282                }
2283            }
2284        };
2285    }
2286    test_from_primitive_type!(u8);
2287    test_from_primitive_type!(u16);
2288    test_from_primitive_type!(u32);
2289    test_from_primitive_type!(u64);
2290    test_from_primitive_type!(u128);
2291    test_from_primitive_type!(usize);
2292    test_from_primitive_type!(i8);
2293    test_from_primitive_type!(i16);
2294    test_from_primitive_type!(i32);
2295    test_from_primitive_type!(i64);
2296    test_from_primitive_type!(i128);
2297    test_from_primitive_type!(isize);
2298
2299    macro_rules! test_to_primitive_type {
2300        ($type:ident) => {
2301            paste! {
2302                #[test]
2303                fn [<test_decimal_to_primitive_$type>]() {
2304                    let d = test_dec!(1);
2305                    let v = $type::try_from(1).unwrap();
2306                    assert_eq!($type::try_from(d).unwrap(), v);
2307
2308                    if $type::MIN != 0 {
2309                        let d = test_dec!(-1);
2310                        let v = $type::try_from(-1).unwrap();
2311                        assert_eq!($type::try_from(d).unwrap(), v);
2312                    }
2313
2314                    let v = $type::MAX;
2315                    let d = Decimal::from(v);
2316                    assert_eq!($type::try_from(d).unwrap(), v);
2317
2318                    let v = $type::MIN;
2319                    let d = Decimal::from(v);
2320                    assert_eq!($type::try_from(d).unwrap(), v);
2321
2322                    let d = Decimal::MAX;
2323                    let err = $type::try_from(d).unwrap_err();
2324                    assert_eq!(err, ParseDecimalError::InvalidDigit);
2325
2326                    let v = $type::MAX;
2327                    let d = Decimal::from(v).checked_add(1).unwrap();
2328                    let err = $type::try_from(d).unwrap_err();
2329                    assert_eq!(err, ParseDecimalError::Overflow);
2330
2331                    let v = $type::MIN;
2332                    let d = Decimal::from(v).checked_sub(1).unwrap();
2333                    let err = $type::try_from(d).unwrap_err();
2334                    assert_eq!(err, ParseDecimalError::Overflow);
2335
2336                    let d = test_dec!("1.1");
2337                    let err = $type::try_from(d).unwrap_err();
2338                    assert_eq!(err, ParseDecimalError::InvalidDigit);
2339                }
2340            }
2341        };
2342    }
2343    test_to_primitive_type!(u8);
2344    test_to_primitive_type!(u16);
2345    test_to_primitive_type!(u32);
2346    test_to_primitive_type!(u64);
2347    test_to_primitive_type!(u128);
2348    test_to_primitive_type!(usize);
2349    test_to_primitive_type!(i8);
2350    test_to_primitive_type!(i16);
2351    test_to_primitive_type!(i32);
2352    test_to_primitive_type!(i64);
2353    test_to_primitive_type!(i128);
2354    test_to_primitive_type!(isize);
2355}