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#[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
45macro_rules! fmt_remainder {
47 () => {
48 "{:036}"
49 };
50}
51
52impl PreciseDecimal {
53 pub const MIN: Self = Self(I256::MIN);
55
56 pub const MAX: Self = Self(I256::MAX);
58
59 pub const BITS: usize = I256::BITS as usize;
61
62 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 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 pub const fn from_precise_subunits(precise_subunits: I256) -> Self {
104 Self(precise_subunits)
105 }
106
107 pub const fn precise_subunits(self) -> I256 {
109 self.0
110 }
111
112 pub const fn zero() -> Self {
114 Self::ZERO
115 }
116
117 pub const fn one() -> Self {
119 Self::ONE
120 }
121
122 pub fn is_zero(&self) -> bool {
124 self.0 == I256::zero()
125 }
126
127 pub fn is_positive(&self) -> bool {
129 self.0 > I256::zero()
130 }
131
132 pub fn is_negative(&self) -> bool {
134 self.0 < I256::zero()
135 }
136
137 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 pub fn checked_floor(&self) -> Option<Self> {
148 self.checked_round(0, RoundingMode::ToNegativeInfinity)
149 }
150
151 pub fn checked_ceiling(&self) -> Option<Self> {
153 self.checked_round(0, RoundingMode::ToPositiveInfinity)
154 }
155
156 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 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; 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; if self.is_positive() {
199 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 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 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 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 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 pub fn checked_cbrt(&self) -> Option<Self> {
279 if self.is_zero() {
280 return Some(Self::ZERO);
281 }
282
283 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 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 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
357impl 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 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 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 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 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
696macro_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
748impl 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
786impl 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 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 let fractional_subunits = fractional_part
851 .checked_mul(I256::TEN.pow(scale))
852 .expect("No overflow possible");
853
854 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 let mut sign = "".to_string();
879
880 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#[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 ($x:literal) => {
987 $crate::math::Decimal::try_from($x).unwrap()
988 };
989 }
990
991 macro_rules! test_pdec {
992 ($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 ) .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 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 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 ) .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 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 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 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 (I256::MAX/(I256::from(10).pow(PreciseDecimal::SCALE)) + I256::ONE, 11),
2013 (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 (I256::MAX/(I256::from(10).pow(PreciseDecimal::SCALE)), "57896044618658097711785492504343953926634", 11),
2049 (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 let string = "1.111111111111111111111111111111111111";
2166
2167 let decimal = PreciseDecimal::from_str(string);
2169
2170 assert!(decimal.is_ok())
2172 }
2173
2174 #[test]
2175 fn no_panic_with_37_decimal_places() {
2176 let string = "1.1111111111111111111111111111111111111";
2178
2179 let decimal = PreciseDecimal::from_str(string);
2181
2182 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 #[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 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}