1use std::{
2 cmp::Ordering,
3 fmt::{Debug, Display, Write},
4 ops::{Add, Div, Mul, Neg, Rem, Sub},
5 str::FromStr,
6};
7
8use smallstr::SmallString;
9
10use crate::{
11 Fixed, OutOfRange, ParseDecimalError, checked_pow10, debug_decimal, display_decimal,
12 parse_decimal, pow10, u256::I256,
13};
14
15use num_traits::CheckedDiv;
16use rand::Rng;
17use rand::distributions::uniform::{UniformInt, UniformSampler};
18
19#[derive(Copy, Clone, Default, PartialEq, Eq, Hash)]
52#[cfg_attr(feature = "size_of", derive(size_of::SizeOf))]
53#[cfg_attr(
54 feature = "rkyv",
55 derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
56)]
57pub struct DynamicDecimal {
58 sig: i128,
60
61 exponent: u8,
63}
64
65impl DynamicDecimal {
66 pub const MAX: Self = DynamicDecimal::new(i128::MAX, 0);
68
69 pub const MIN: Self = DynamicDecimal::new(i128::MIN, 0);
71
72 pub const ZERO: Self = DynamicDecimal::new(0, 0);
74
75 pub const ONE: Self = DynamicDecimal::new(1, 0);
77
78 pub const fn new(sig: i128, exponent: u8) -> Self {
80 if exponent == 0 {
81 Self { sig, exponent }
82 } else if sig == 0 {
83 Self { sig, exponent: 0 }
84 } else {
85 const fn reduce<const D: u8>(mut sig: i128, mut exponent: u8) -> (i128, u8) {
88 let scale = pow10(D as usize);
90
91 while exponent >= D
95 && sig.unsigned_abs() >= scale.cast_unsigned()
96 && (sig & ((1 << D) - 1)) == 0
97 && sig % scale == 0
98 {
99 sig /= scale;
100 exponent -= D;
101 }
102 (sig, exponent)
103 }
104
105 let (sig, exponent) = reduce::<8>(sig, exponent);
109 let (sig, exponent) = reduce::<4>(sig, exponent);
110 let (sig, exponent) = reduce::<1>(sig, exponent);
111 debug_assert!(sig % 10 != 0 || exponent == 0);
112 Self { sig, exponent }
113 }
114 }
115
116 pub const fn significand(&self) -> i128 {
118 self.sig
119 }
120
121 pub const fn exponent(&self) -> u8 {
123 self.exponent
124 }
125
126 pub fn trunc(&self) -> Self {
128 DynamicDecimal::new(self.sig / pow10(self.exponent as usize), 0)
129 }
130
131 pub fn trunc_digits(&self, digits: u8) -> Self {
134 if self.exponent() <= digits {
135 *self
136 } else if self.exponent - digits > 38 {
137 Self::ZERO
138 } else {
139 let divisor = pow10((self.exponent - digits) as usize);
140 Self::new(self.significand() / divisor, digits)
141 }
142 }
143
144 pub fn floor(&self) -> Self {
146 let trunc = self.trunc();
147 if self.is_negative() {
148 if trunc != *self {
149 trunc - DynamicDecimal::new(1, 0)
150 } else {
151 *self
152 }
153 } else {
154 trunc
155 }
156 }
157
158 pub const fn is_negative(self) -> bool {
160 self.sig.is_negative()
161 }
162
163 pub const fn abs(self) -> Self {
165 Self::new(self.sig.abs(), self.exponent)
166 }
167
168 #[doc(hidden)]
173 pub fn into_fixed_round_even<const P: usize, const S: usize>(
174 self,
175 ) -> Result<Fixed<P, S>, OutOfRange> {
176 Fixed::<P, S>::try_new_with_exponent_round_even(self.sig, S as i32 - self.exponent as i32)
177 .ok_or(OutOfRange)
178 }
179}
180
181impl<const P: usize, const S: usize> From<Fixed<P, S>> for DynamicDecimal {
182 fn from(value: Fixed<P, S>) -> Self {
185 Self::new(value.0, S as u8)
186 }
187}
188
189impl Neg for DynamicDecimal {
190 type Output = Self;
191
192 fn neg(self) -> Self {
193 DynamicDecimal::new(-self.sig, self.exponent)
194 }
195}
196
197impl Add<DynamicDecimal> for DynamicDecimal {
198 type Output = Self;
199
200 fn add(self, other: Self) -> Self {
201 match self.exponent.cmp(&other.exponent) {
202 Ordering::Less => {
203 let factor = pow10((other.exponent - self.exponent) as usize);
204 if self.sig <= i128::MAX / factor / 10 {
205 DynamicDecimal::new(
206 other.sig.checked_add(self.sig * factor).unwrap(),
207 other.exponent,
208 )
209 } else {
210 let result = (I256::from_product(self.sig, factor) + I256::from(other.sig))
211 .reduce_to_i128();
212 DynamicDecimal::new(result.0, result.1 as u8)
213 }
214 }
215 Ordering::Equal => {
216 DynamicDecimal::new(self.sig.checked_add(other.sig).unwrap(), self.exponent)
217 }
218 Ordering::Greater => {
219 let factor = pow10((self.exponent - other.exponent) as usize);
220 if other.sig <= i128::MAX / factor / 10 {
221 DynamicDecimal::new(
222 self.sig.checked_add(other.sig * factor).unwrap(),
223 self.exponent,
224 )
225 } else {
226 let result = (I256::from_product(other.sig, factor) + I256::from(self.sig))
227 .reduce_to_i128();
228 DynamicDecimal::new(result.0, result.1 as u8)
229 }
230 }
231 }
232 }
233}
234
235impl Sub<DynamicDecimal> for DynamicDecimal {
236 type Output = Self;
237
238 fn sub(self, other: Self) -> Self {
239 self.add(other.neg())
240 }
241}
242
243impl Mul<DynamicDecimal> for DynamicDecimal {
244 type Output = Self;
245
246 fn mul(self, other: Self) -> Self {
247 let result = I256::from_product(self.sig, other.sig).reduce_to_i128();
248 DynamicDecimal::new(result.0, result.1 as u8 + self.exponent + other.exponent)
249 }
250}
251
252impl CheckedDiv for DynamicDecimal {
253 fn checked_div(&self, other: &DynamicDecimal) -> Option<DynamicDecimal> {
254 if other.sig == 0i128 {
255 None
256 } else {
257 const MIN_DIGITS: u8 = 6;
260 let digits = std::cmp::max(std::cmp::max(MIN_DIGITS, self.exponent), other.exponent);
261
262 let shift_left = (other.exponent + digits).saturating_sub(self.exponent);
263 if shift_left > 38 {
264 None
268 } else {
269 let scaled = I256::from_product(self.sig, pow10(shift_left as usize));
270 let div = scaled.narrowing_div(other.sig).unwrap();
271 let exp = self.exponent.saturating_sub(other.exponent + digits);
272 let adjust = div * pow10(exp as usize);
273 Some(DynamicDecimal::new(adjust, digits))
274 }
275 }
276 }
277}
278
279impl Div<DynamicDecimal> for DynamicDecimal {
280 type Output = Self;
281
282 fn div(self, other: DynamicDecimal) -> DynamicDecimal {
283 match self.checked_div(&other) {
284 None => panic!("Overflow dividing {} / {}", self, other),
285 Some(v) => v,
286 }
287 }
288}
289
290impl Rem<DynamicDecimal> for DynamicDecimal {
291 type Output = Self;
292
293 fn rem(self, other: Self) -> Self {
294 let neg = self.is_negative();
295 let left = self.abs();
296 let right = other.abs();
297 let div = left.div(right);
298 let trunc = div.trunc();
299 let mul = right.mul(trunc);
300 let rem = left.sub(mul);
301 if neg { rem.neg() } else { rem }
302 }
303}
304
305impl<const P: usize, const S: usize> TryFrom<DynamicDecimal> for Fixed<P, S> {
306 type Error = OutOfRange;
307
308 fn try_from(value: DynamicDecimal) -> Result<Self, Self::Error> {
313 Self::try_new_with_exponent(value.sig, S as i32 - value.exponent as i32).ok_or(OutOfRange)
314 }
315}
316
317impl Debug for DynamicDecimal {
318 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
319 debug_decimal(self.sig, self.exponent as usize, f)
320 }
321}
322
323impl Display for DynamicDecimal {
324 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
325 display_decimal(self.sig, self.exponent as usize, f)
326 }
327}
328
329impl FromStr for DynamicDecimal {
330 type Err = ParseDecimalError;
331
332 fn from_str(s: &str) -> Result<Self, Self::Err> {
339 let (sig, exponent) = parse_decimal(s, 0)?;
340 match (sig, exponent) {
341 (0, _) => Ok(Self::ZERO),
342 (_, 1..) => {
343 let sig = checked_pow10(exponent.cast_unsigned())
344 .and_then(|m| m.checked_mul(sig))
345 .ok_or(ParseDecimalError::OutOfRange)?;
346 Ok(Self::new(sig, 0))
347 }
348 (_, 0) => Ok(Self { sig, exponent: 0 }),
349 (_, -255..0) => Ok(Self::new(sig, (-exponent) as u8)),
350 (_, ..-255) => {
351 Ok(Self::ZERO)
356 }
357 }
358 }
359}
360
361impl TryFrom<u128> for DynamicDecimal {
362 type Error = OutOfRange;
363
364 fn try_from(value: u128) -> Result<Self, Self::Error> {
365 Ok(Self::new(value.try_into().map_err(|_| OutOfRange)?, 0))
366 }
367}
368
369macro_rules! from_int {
370 ($type_name:ty) => {
371 impl From<$type_name> for DynamicDecimal {
372 fn from(value: $type_name) -> Self {
373 Self::new(value as i128, 0)
374 }
375 }
376 };
377}
378from_int!(i128);
379from_int!(i64);
380from_int!(i32);
381from_int!(i16);
382from_int!(i8);
383from_int!(isize);
384from_int!(u64);
385from_int!(u32);
386from_int!(u16);
387from_int!(u8);
388from_int!(usize);
389
390impl From<DynamicDecimal> for i128 {
391 fn from(value: DynamicDecimal) -> Self {
394 checked_pow10(value.exponent.into()).map_or(0, |divisor| value.sig / divisor)
395 }
396}
397
398macro_rules! try_to_signed_int {
399 ($type_name:ty) => {
400 impl TryFrom<DynamicDecimal> for $type_name {
401 type Error = OutOfRange;
402
403 fn try_from(value: DynamicDecimal) -> Result<Self, Self::Error> {
406 match checked_pow10(value.exponent.into()) {
407 Some(divisor) => (value.sig / divisor).try_into().map_err(|_| OutOfRange),
408 None => Ok(0),
409 }
410 }
411 }
412 };
413}
414try_to_signed_int!(i64);
415try_to_signed_int!(i32);
416try_to_signed_int!(i16);
417try_to_signed_int!(i8);
418try_to_signed_int!(isize);
419
420macro_rules! try_to_unsigned_int {
423 ($type_name:ty) => {
424 impl TryFrom<DynamicDecimal> for $type_name {
425 type Error = OutOfRange;
426
427 fn try_from(value: DynamicDecimal) -> Result<Self, Self::Error> {
433 match checked_pow10(value.exponent.into()) {
434 Some(divisor) => (value.sig / divisor).try_into().map_err(|_| OutOfRange),
435 None => Ok(0),
436 }
437 }
438 }
439 };
440}
441try_to_unsigned_int!(u128);
442try_to_unsigned_int!(u64);
443try_to_unsigned_int!(u32);
444try_to_unsigned_int!(u16);
445try_to_unsigned_int!(u8);
446try_to_unsigned_int!(usize);
447
448impl From<DynamicDecimal> for f64 {
449 fn from(value: DynamicDecimal) -> Self {
450 value.significand() as f64 / pow10(value.exponent() as usize) as f64
451 }
452}
453
454impl From<DynamicDecimal> for f32 {
455 fn from(value: DynamicDecimal) -> Self {
456 value.significand() as f32 / pow10(value.exponent() as usize) as f32
457 }
458}
459
460impl TryFrom<f64> for DynamicDecimal {
461 type Error = OutOfRange;
462
463 fn try_from(value: f64) -> Result<Self, Self::Error> {
466 let mut buf = SmallString::<[u8; 64]>::new();
472 write!(&mut buf, "{value:.15e}").unwrap();
473 buf.parse().map_err(|_| OutOfRange)
474 }
475}
476
477impl PartialOrd for DynamicDecimal {
478 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
479 Some(self.cmp(other))
480 }
481}
482
483impl Ord for DynamicDecimal {
484 fn cmp(&self, other: &Self) -> Ordering {
485 match self.exponent.cmp(&other.exponent) {
486 Ordering::Less => {
487 if let Some(multiplier) =
488 checked_pow10(other.exponent as u32 - self.exponent as u32)
489 {
490 I256::from_product(self.sig, multiplier).cmp(&I256::from(other.sig))
491 } else {
492 match self.sig.cmp(&0) {
493 Ordering::Equal => 0.cmp(&other.sig),
494 ordering => ordering,
495 }
496 }
497 }
498 Ordering::Equal => self.sig.cmp(&other.sig),
499 Ordering::Greater => {
500 if let Some(multiplier) =
501 checked_pow10(self.exponent as u32 - other.exponent as u32)
502 {
503 I256::from(self.sig).cmp(&I256::from_product(other.sig, multiplier))
504 } else {
505 match other.sig.cmp(&0) {
506 Ordering::Equal => self.sig.cmp(&0),
507 ordering => ordering.reverse(),
508 }
509 }
510 }
511 }
512 }
513}
514
515#[derive(Clone, Debug)]
519pub struct UniformDecimal {
520 significand: UniformInt<i128>,
521 scale: u8,
522}
523
524impl UniformDecimal {
525 pub fn new(low: i128, high: i128, scale: u8) -> Self {
528 if low >= high {
529 panic!("Invalid range");
530 }
531 Self {
532 significand: UniformInt::new(&low, &high),
533 scale,
534 }
535 }
536
537 pub fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> DynamicDecimal {
539 let value = self.significand.sample(rng);
540 DynamicDecimal::new(value, self.scale)
541 }
542}
543
544#[cfg(test)]
545mod test {
546 use crate::{DynamicDecimal, OutOfRange, ParseDecimalError};
547
548 #[test]
549 fn eq() {
550 assert_eq!(DynamicDecimal::new(123, 2), DynamicDecimal::new(1230, 3));
551 assert_eq!(DynamicDecimal::new(1230, 3), DynamicDecimal::new(123, 2));
552 assert_eq!(DynamicDecimal::new(123, 2), DynamicDecimal::new(123, 2));
553 assert_ne!(DynamicDecimal::new(123, 2), DynamicDecimal::new(123, 3));
554 }
555
556 #[test]
557 fn compare() {
558 type DD = DynamicDecimal;
559 fn check_comparisons(dx: DD, dy: DD, x: i128, y: i128) {
560 assert_eq!(dx == dy, x == y);
561 assert_eq!(dx != dy, x != y);
562 assert_eq!(dx > dy, x > y);
563 assert_eq!(dx >= dy, x >= y);
564 assert_eq!(dx < dy, x < y);
565 assert_eq!(dx <= dy, x <= y);
566 }
567
568 for x in -999..=999 {
569 let fx = DD::new(x, 1);
570 for y in -999..=999 {
571 check_comparisons(fx, DD::new(y, 0), x, y * 10);
572 check_comparisons(fx, DD::new(y, 1), x, y);
573 check_comparisons(fx, DD::new(y, 2), x * 10, y);
574 }
575 }
576
577 check_comparisons(DD::new(0, 40), DD::new(0, 0), 0, 0);
579 check_comparisons(DD::new(0, 0), DD::new(0, 40), 0, 0);
580
581 check_comparisons(DD::new(1, 40), DD::new(1, 0), 0, 1);
582 check_comparisons(DD::new(1, 40), DD::new(-1, 0), 1, 0);
583 check_comparisons(DD::new(-1, 40), DD::new(1, 0), 0, 1);
584 check_comparisons(DD::new(-1, 40), DD::new(-1, 0), 1, 0);
585
586 check_comparisons(DD::new(1, 0), DD::new(1, 40), 1, 0);
587 check_comparisons(DD::new(1, 0), DD::new(-1, 40), 1, 0);
588 check_comparisons(DD::new(-1, 0), DD::new(1, 40), 0, 1);
589 check_comparisons(DD::new(-1, 0), DD::new(-1, 40), 0, 1);
590 }
591
592 #[test]
593 fn from_str() {
594 for (s, expect) in [
595 ("0", Ok("0")),
596 ("0.", Ok("0")),
597 (".0", Ok("0")),
598 ("-0", Ok("0")),
599 ("+0", Ok("0")),
600 ("--0", Err(ParseDecimalError::SyntaxError)),
601 ("-+0", Err(ParseDecimalError::SyntaxError)),
602 ("0x", Err(ParseDecimalError::SyntaxError)),
603 ("0e5x", Err(ParseDecimalError::SyntaxError)),
604 ("1.23", Ok("1.23")),
605 ("-1.23", Ok("-1.23")),
606 ("+1.23", Ok("1.23")),
607 ("99999999", Ok("99999999")),
608 ("999999999", Ok("999999999")),
609 ("999999999E-1", Ok("99999999.9")),
610 ("9999999999e-1", Ok("999999999.9")),
611 ("9999999999E-2", Ok("99999999.99")),
612 ("99999999999e-2", Ok("999999999.99")),
613 ("99999999999e-3", Ok("99999999.999")),
614 ("99999999991e-3", Ok("99999999.991")),
615 (
619 "111111111111111111111111111111111111111111e-34",
620 Ok("11111111.1111111111111111111111111111111"),
621 ),
622 (
626 "1.23456788901234567890123456789012345678890123456",
627 Ok("1.23456788901234567890123456789012345678"),
628 ),
629 ("1e999999999999999", Err(ParseDecimalError::OutOfRange)),
631 ("0e999999999999999", Ok("0")),
633 ("1e-999999999999999", Ok("0")),
635 (
639 "111111111111111111111111111111111111111111e2147483644",
640 Err(ParseDecimalError::OutOfRange),
641 ),
642 (
645 ".1111111111111111111111111111111111111111e-2147483648",
646 Ok("0"),
647 ),
648 ("123e5", Ok("12300000")),
649 ("123E4", Ok("1230000")),
650 ("123e3", Ok("123000")),
651 ("123e2", Ok("12300")),
652 ("123e1", Ok("1230")),
653 ("123e0", Ok("123")),
654 ("123e-1", Ok("12.3")),
655 ("123e-2", Ok("1.23")),
656 (".123", Ok("0.123")),
657 (".124", Ok("0.124")),
658 (".125", Ok("0.125")),
659 (".126", Ok("0.126")),
660 (".133", Ok("0.133")),
661 (".134", Ok("0.134")),
662 (".135", Ok("0.135")),
663 (".136", Ok("0.136")),
664 ("1e38", Ok("100000000000000000000000000000000000000")),
665 ("1e39", Err(ParseDecimalError::OutOfRange)),
666 (
667 "1e-255",
668 Ok(
669 "0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001",
670 ),
671 ),
672 ("1e-256", Ok("0")),
673 ] {
674 println!("{s}: {:?}", s.parse::<DynamicDecimal>());
675 assert_eq!(
676 s.parse::<DynamicDecimal>().map(|d| d.to_string()),
677 expect.map(|d| d.to_string())
678 );
679 }
680 }
681
682 #[test]
683 fn to_integer() {
684 for x in -9999..=9999 {
685 let f = DynamicDecimal::new(x, 1);
686 assert_eq!(i128::from(f), x / 10);
687 assert_eq!(i64::try_from(f).unwrap(), (x / 10) as i64);
688 assert_eq!(i32::try_from(f).unwrap(), (x / 10) as i32);
689 assert_eq!(i16::try_from(f).unwrap(), (x / 10) as i16);
690 assert_eq!(
691 i8::try_from(f).ok(),
692 (-1289..=1279).contains(&x).then_some((x / 10) as i8)
693 );
694 assert_eq!(
695 u128::try_from(f).ok(),
696 (x > -10).then_some((x / 10) as u128)
697 );
698 assert_eq!(u64::try_from(f).ok(), (x > -10).then_some((x / 10) as u64));
699 assert_eq!(u32::try_from(f).ok(), (x > -10).then_some((x / 10) as u32));
700 assert_eq!(u16::try_from(f).ok(), (x > -10).then_some((x / 10) as u16));
701 assert_eq!(
702 u8::try_from(f).ok(),
703 (-9..=2559).contains(&x).then_some((x / 10) as u8)
704 );
705 }
706
707 assert_eq!(i128::from(DynamicDecimal::new(1, 40)), 0);
708 assert_eq!(i128::from(DynamicDecimal::new(i128::MAX, 0)), i128::MAX);
709 assert_eq!(i64::try_from(DynamicDecimal::new(1, 40)), Ok(0));
710 assert_eq!(
711 i64::try_from(DynamicDecimal::new(i128::MAX, 0)),
712 Err(OutOfRange)
713 );
714 assert_eq!(
715 i64::try_from(DynamicDecimal::new(i128::MIN, 0)),
716 Err(OutOfRange)
717 );
718 }
719
720 #[test]
721 fn mul() {
722 fn f(n: f64) -> DynamicDecimal {
723 DynamicDecimal::try_from(n).unwrap().trunc_digits(2)
724 }
725
726 assert_eq!((f(1.23) * f(2.34)).trunc_digits(2), f(2.87));
729 assert_eq!((f(-1.23) * f(2.34)).trunc_digits(2), f(-2.87));
730 assert_eq!((f(1.23) * f(-2.34)).trunc_digits(2), f(-2.87));
731 assert_eq!((f(-1.23) * f(-2.34)).trunc_digits(2), f(2.87));
732
733 for a in -999..=999 {
735 let af: DynamicDecimal = DynamicDecimal::new(a, 2);
736 for b in -999..=999 {
737 let bf = DynamicDecimal::new(b, 2);
738 assert_eq!(af * bf, DynamicDecimal::new(a * b, 4));
739 }
740 }
741 }
742
743 #[test]
744 fn add() {
745 fn f(n: f64) -> DynamicDecimal {
746 DynamicDecimal::try_from(n).unwrap().trunc_digits(2)
747 }
748
749 assert_eq!(f(1.23) + f(2.34), f(3.57));
751 assert_eq!(f(-1.23) + f(2.34), f(1.11));
752 assert_eq!(f(1.23) + f(-2.34), f(-1.11));
753 assert_eq!(f(-1.23) + f(-2.34), f(-3.57));
754
755 for a in -999..=999 {
756 let af = DynamicDecimal::new(a, 2);
757 for b in -999..=999 {
758 let bf = DynamicDecimal::new(b, 2);
759 assert_eq!(af + bf, DynamicDecimal::new(a + b, 2));
760 }
761 }
762 }
763
764 #[test]
765 fn sub() {
766 fn f(n: f64) -> DynamicDecimal {
767 DynamicDecimal::try_from(n).unwrap().trunc_digits(2)
768 }
769
770 assert_eq!(f(1.23) - f(2.34), f(-1.11));
771 assert_eq!(f(-1.23) - f(2.34), f(-3.57));
772 assert_eq!(f(1.23) - f(-2.34), f(3.57));
773 assert_eq!(f(-1.23) - f(-2.34), f(1.11));
774
775 for a in -999..=999 {
776 let af = DynamicDecimal::new(a, 2);
777 for b in -999..=999 {
778 let bf = DynamicDecimal::new(b, 2);
779 assert_eq!(af - bf, DynamicDecimal::new(a - b, 2));
780 }
781 }
782 }
783
784 #[test]
785 fn div() {
786 fn f(n: f64) -> DynamicDecimal {
787 DynamicDecimal::try_from(n).unwrap().trunc_digits(6)
788 }
789
790 assert_eq!(f(1.23) / f(2.34), f(0.525641));
791 assert_eq!(f(-1.23) / f(2.34), f(-0.525641));
792 assert_eq!(f(1.23) / f(-2.34), f(-0.525641));
793 assert_eq!(f(-1.23) / f(-2.34), f(0.525641));
794
795 for a in -999..=999 {
796 let af = DynamicDecimal::new(a, 2);
797 for b in -999..=999 {
798 let bf = DynamicDecimal::new(b, 2);
799 if b != 0 {
800 let expected = DynamicDecimal::new(a * 1000000 / b, 6);
801 assert_eq!(af / bf, expected);
802 }
803 }
804 }
805 }
806}