radix_common/math/
precise_decimal.rs

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