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