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