1use crate::fpdec_inner::FpdecInner;
2use crate::oob_scale_fpdec::OobScaleFpdec;
3use crate::{IntoRatioInt, ParseError, Rounding};
4
5use core::{fmt, num::ParseIntError, ops, str::FromStr};
6
7#[allow(unused_imports)]
8use num_traits::float::FloatCore; use num_traits::{cast::FromPrimitive, Num, Signed};
10
11#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Default)]
25#[repr(transparent)]
26pub struct ConstScaleFpdec<I, const S: i32>(I);
27
28impl<I, const S: i32> ConstScaleFpdec<I, S>
29where
30 I: FpdecInner,
31{
32 crate::none_scale_common::define_none_scale_common!();
33
34 pub const SCALE: i32 = S;
36
37 #[must_use]
44 pub fn checked_mul<J, const S2: i32, const SR: i32>(
45 self,
46 rhs: ConstScaleFpdec<J, S2>,
47 ) -> Option<ConstScaleFpdec<I, SR>>
48 where
49 J: FpdecInner,
50 {
51 self.checked_mul_ext(rhs, Rounding::Round)
52 }
53
54 #[must_use]
84 pub fn checked_mul_ext<J, const S2: i32, const SR: i32>(
85 self,
86 rhs: ConstScaleFpdec<J, S2>,
87 rounding: Rounding,
88 ) -> Option<ConstScaleFpdec<I, SR>>
89 where
90 J: FpdecInner,
91 {
92 self.0
93 .checked_mul_ext(I::from(rhs.0)?, S + S2 - SR, rounding)
94 .map(ConstScaleFpdec)
95 }
96
97 #[must_use]
105 pub fn checked_div<J, const S2: i32, const SR: i32>(
106 self,
107 rhs: ConstScaleFpdec<J, S2>,
108 ) -> Option<ConstScaleFpdec<I, SR>>
109 where
110 J: FpdecInner,
111 {
112 self.checked_div_ext(rhs, Rounding::Round)
113 }
114
115 #[must_use]
139 pub fn checked_div_ext<J, const S2: i32, const SR: i32>(
140 self,
141 rhs: ConstScaleFpdec<J, S2>,
142 rounding: Rounding,
143 ) -> Option<ConstScaleFpdec<I, SR>>
144 where
145 J: FpdecInner,
146 {
147 self.0
148 .checked_div_ext(I::from(rhs.0)?, S - S2 - SR, rounding)
149 .map(ConstScaleFpdec)
150 }
151
152 #[must_use]
156 pub fn round(self, scale: i32) -> Self {
157 self.round_ext(scale, Rounding::Round)
158 }
159
160 #[must_use]
177 pub fn round_ext(self, scale: i32, rounding: Rounding) -> Self {
178 Self(self.0.round_diff_with_rounding(S - scale, rounding))
179 }
180}
181
182impl<I, const S: i32> ConstScaleFpdec<I, S>
183where
184 I: FpdecInner + Signed,
185{
186 crate::none_scale_common::define_none_scale_common_signed!();
187}
188
189impl<I, const S: i32> fmt::Debug for ConstScaleFpdec<I, S>
190where
191 I: fmt::Display,
192{
193 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
194 write!(f, "Fpdec({},{})", self.0, S)
195 }
196}
197
198impl<I, const S: i32> fmt::Display for ConstScaleFpdec<I, S>
220where
221 I: FpdecInner + fmt::Display,
222{
223 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
224 self.0.display_fmt(S, f)
225 }
226}
227
228impl<I, const S: i32> FromStr for ConstScaleFpdec<I, S>
249where
250 I: FpdecInner + Num<FromStrRadixErr = ParseIntError>,
251{
252 type Err = ParseError;
253 fn from_str(s: &str) -> Result<Self, ParseError> {
254 I::try_from_str(s, S).map(Self)
255 }
256}
257
258impl<I, const S: i32> From<OobScaleFpdec<I>> for ConstScaleFpdec<I, S>
259where
260 I: FpdecInner,
261{
262 fn from(od: OobScaleFpdec<I>) -> Self {
276 Self(od.mantissa())
277 }
278}
279
280macro_rules! convert_from_int {
281 ($from_int_type:ty) => {
282 impl<I, const S: i32> TryFrom<$from_int_type> for ConstScaleFpdec<I, S>
283 where
284 I: FpdecInner,
285 {
286 type Error = ParseError;
287
288 fn try_from(i: $from_int_type) -> Result<Self, Self::Error> {
306 if S > 0 {
307 let i2 = I::from(i).ok_or(ParseError::Overflow)?;
309 I::checked_from_int(i2, S).map(Self)
310 } else {
311 let i2 = i.checked_from_int(S)?;
313 I::from(i2).ok_or(ParseError::Overflow).map(Self)
314 }
315 }
316 }
317 };
318}
319convert_from_int!(i8);
320convert_from_int!(i16);
321convert_from_int!(i32);
322convert_from_int!(i64);
323convert_from_int!(i128);
324convert_from_int!(u8);
325convert_from_int!(u16);
326convert_from_int!(u32);
327convert_from_int!(u64);
328convert_from_int!(u128);
329
330macro_rules! convert_from_float {
331 ($float_type:ty, $from_fn:ident, $to_fn:ident) => {
332 impl<I, const S: i32> TryFrom<$float_type> for ConstScaleFpdec<I, S>
333 where
334 I: FromPrimitive + FpdecInner,
335 {
336 type Error = ParseError;
337
338 fn try_from(f: $float_type) -> Result<Self, Self::Error> {
355 let inner_f = if S > 0 {
356 f * 10.0.powi(S)
357 } else if S < 0 {
358 f / 10.0.powi(-S)
359 } else {
360 f
361 };
362 I::$from_fn(inner_f.round())
363 .map(Self)
364 .ok_or(ParseError::Overflow)
365 }
366 }
367
368 impl<I, const S: i32> From<ConstScaleFpdec<I, S>> for $float_type
369 where
370 I: FpdecInner,
371 {
372 fn from(dec: ConstScaleFpdec<I, S>) -> Self {
391 let f = dec.0.$to_fn().unwrap();
392 if S > 0 {
393 f / 10.0.powi(S)
394 } else if S < 0 {
395 f * 10.0.powi(-S)
396 } else {
397 f
398 }
399 }
400 }
401 };
402}
403
404convert_from_float!(f32, from_f32, to_f32);
405convert_from_float!(f64, from_f64, to_f64);
406
407impl<I, const S: i32> ops::Neg for ConstScaleFpdec<I, S>
408where
409 I: FpdecInner + Signed,
410{
411 type Output = Self;
412 fn neg(self) -> Self::Output {
413 Self(-self.0)
414 }
415}
416
417impl<I, const S: i32> ops::Add for ConstScaleFpdec<I, S>
418where
419 I: FpdecInner,
420{
421 type Output = Self;
422 fn add(self, rhs: Self) -> Self::Output {
423 Self(self.0 + rhs.0)
424 }
425}
426
427impl<I, const S: i32> ops::Sub for ConstScaleFpdec<I, S>
428where
429 I: FpdecInner,
430{
431 type Output = Self;
432 fn sub(self, rhs: Self) -> Self::Output {
433 Self(self.0 - rhs.0)
434 }
435}
436
437impl<I, J, const S: i32, const S2: i32> ops::Mul<ConstScaleFpdec<J, S2>> for ConstScaleFpdec<I, S>
460where
461 I: FpdecInner,
462 J: FpdecInner,
463{
464 type Output = Self;
465 fn mul(self, rhs: ConstScaleFpdec<J, S2>) -> Self::Output {
466 self.checked_mul(rhs)
467 .expect("overflow in decimal multiplication")
468 }
469}
470
471impl<I, J, const S: i32> ops::Mul<J> for ConstScaleFpdec<I, S>
477where
478 I: FpdecInner,
479 J: Into<I> + Num, {
481 type Output = Self;
482 fn mul(self, rhs: J) -> Self::Output {
483 self.checked_mul_int(rhs)
484 .expect("overflow in decimal multiplication")
485 }
486}
487
488impl<I, J, const S: i32, const S2: i32> ops::Div<ConstScaleFpdec<J, S2>> for ConstScaleFpdec<I, S>
511where
512 I: FpdecInner,
513 J: FpdecInner,
514{
515 type Output = Self;
516 fn div(self, rhs: ConstScaleFpdec<J, S2>) -> Self::Output {
517 self.checked_div(rhs).expect("fail in decimal division")
518 }
519}
520
521impl<I, J, const S: i32> ops::Div<J> for ConstScaleFpdec<I, S>
527where
528 I: FpdecInner,
529 J: Into<I> + Num,
530{
531 type Output = Self;
532 fn div(self, rhs: J) -> Self::Output {
533 self.checked_div_int(rhs).expect("fail in decimal division")
534 }
535}
536
537impl<I, const S: i32> ops::AddAssign for ConstScaleFpdec<I, S>
538where
539 I: FpdecInner,
540{
541 fn add_assign(&mut self, rhs: Self) {
542 self.0 += rhs.0;
543 }
544}
545
546impl<I, const S: i32> ops::SubAssign for ConstScaleFpdec<I, S>
547where
548 I: FpdecInner,
549{
550 fn sub_assign(&mut self, rhs: Self) {
551 self.0 -= rhs.0;
552 }
553}
554
555impl<I, J, const S: i32, const S2: i32> ops::MulAssign<ConstScaleFpdec<J, S2>>
556 for ConstScaleFpdec<I, S>
557where
558 I: FpdecInner,
559 J: FpdecInner,
560{
561 fn mul_assign(&mut self, rhs: ConstScaleFpdec<J, S2>) {
562 *self = *self * rhs;
563 }
564}
565
566impl<I, J, const S: i32> ops::MulAssign<J> for ConstScaleFpdec<I, S>
567where
568 I: FpdecInner,
569 J: Into<I> + Num,
570{
571 fn mul_assign(&mut self, rhs: J) {
572 *self = *self * rhs;
573 }
574}
575
576impl<I, J, const S: i32, const S2: i32> ops::DivAssign<ConstScaleFpdec<J, S2>>
577 for ConstScaleFpdec<I, S>
578where
579 I: FpdecInner,
580 J: FpdecInner,
581{
582 fn div_assign(&mut self, rhs: ConstScaleFpdec<J, S2>) {
583 *self = *self / rhs;
584 }
585}
586
587impl<I, J, const S: i32> ops::DivAssign<J> for ConstScaleFpdec<I, S>
588where
589 I: FpdecInner,
590 J: Into<I> + Num,
591{
592 fn div_assign(&mut self, rhs: J) {
593 *self = *self / rhs;
594 }
595}
596
597impl<I, J, const S: i32> IntoRatioInt<J> for ConstScaleFpdec<I, S>
598where
599 I: FpdecInner + Into<J>,
600{
601 fn to_int(self) -> J {
602 self.mantissa().into()
603 }
604}
605
606#[cfg(feature = "serde")]
607use serde::{Deserialize, Deserializer, Serialize, Serializer};
608
609#[cfg(feature = "serde")]
610impl<I, const S0: i32> Serialize for ConstScaleFpdec<I, S0>
611where
612 I: FpdecInner + fmt::Display,
613{
614 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
615 where
616 S: Serializer,
617 {
618 if serializer.is_human_readable() {
620 serializer.collect_str(self)
621 } else {
622 Into::<f64>::into(*self).serialize(serializer)
623 }
624 }
625}
626
627#[cfg(feature = "serde")]
628impl<'de, I, const S: i32> Deserialize<'de> for ConstScaleFpdec<I, S>
629where
630 I: FromPrimitive + FpdecInner + Num<FromStrRadixErr = ParseIntError>,
631{
632 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
633 where
634 D: Deserializer<'de>,
635 {
636 use core::marker::PhantomData;
637 use core::str::FromStr;
638 use serde::de::{self, Visitor};
639
640 struct ConstScaleFpdecVistor<I, const S: i32>(PhantomData<I>);
641
642 macro_rules! visit_num {
643 ($func_name:ident, $num_type:ty) => {
644 fn $func_name<E: de::Error>(self, n: $num_type) -> Result<Self::Value, E> {
645 ConstScaleFpdec::try_from(n).map_err(|_| E::custom("decimal overflow"))
646 }
647 };
648 }
649
650 impl<'de, I, const S: i32> Visitor<'de> for ConstScaleFpdecVistor<I, S>
651 where
652 I: FromPrimitive + FpdecInner + Num<FromStrRadixErr = ParseIntError>,
653 {
654 type Value = ConstScaleFpdec<I, S>;
655
656 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
657 write!(formatter, "decimal")
658 }
659
660 fn visit_str<E: de::Error>(self, s: &str) -> Result<Self::Value, E> {
661 ConstScaleFpdec::from_str(s).map_err(E::custom)
662 }
663
664 visit_num!(visit_f32, f32);
665 visit_num!(visit_f64, f64);
666 visit_num!(visit_i8, i8);
667 visit_num!(visit_i16, i16);
668 visit_num!(visit_i32, i32);
669 visit_num!(visit_i64, i64);
670 visit_num!(visit_i128, i128);
671 visit_num!(visit_u8, u8);
672 visit_num!(visit_u16, u16);
673 visit_num!(visit_u32, u32);
674 visit_num!(visit_u64, u64);
675 visit_num!(visit_u128, u128);
676 }
677
678 deserializer.deserialize_any(ConstScaleFpdecVistor(PhantomData))
679 }
680}
681
682#[cfg(test)]
683mod tests {
684 use super::*;
685 use crate as primitive_fixed_point_decimal;
686 use crate::fpdec;
687
688 #[test]
689 fn test_mul() {
690 let two_p12: ConstScaleFpdec<i32, 12> = fpdec!(2e-12);
691 let two_n12: ConstScaleFpdec<i32, -12> = fpdec!(2e+12);
692 let two_p6: ConstScaleFpdec<i32, 6> = fpdec!(2e-6);
693 let two_n6: ConstScaleFpdec<i32, -6> = fpdec!(2e+6);
694 let two_p3: ConstScaleFpdec<i32, 3> = fpdec!(2e-3);
695 let two_n3: ConstScaleFpdec<i32, -3> = fpdec!(2e+3);
696 let two_0: ConstScaleFpdec<i32, 0> = fpdec!(2);
697
698 let zero_p6 = ConstScaleFpdec::<i32, 6>::ZERO;
699 let zero_n6 = ConstScaleFpdec::<i32, -6>::ZERO;
700
701 let four_p12: ConstScaleFpdec<i32, 12> = fpdec!(4e-12);
702 let four_n12: ConstScaleFpdec<i32, -12> = fpdec!(4e+12);
703 let four_p6: ConstScaleFpdec<i32, 6> = fpdec!(4e-6);
704 let four_n6: ConstScaleFpdec<i32, -6> = fpdec!(4e+6);
705 let four_p3: ConstScaleFpdec<i32, 3> = fpdec!(4e-3);
706 let four_n3: ConstScaleFpdec<i32, -3> = fpdec!(4e+3);
707 let four_0: ConstScaleFpdec<i32, 0> = fpdec!(4);
708
709 assert_eq!(two_p12.mantissa(), 2);
710 assert_eq!(two_n12.mantissa(), 2);
711 assert_eq!(two_p6.mantissa(), 2);
712 assert_eq!(two_n6.mantissa(), 2);
713 assert_eq!(two_p3.mantissa(), 2);
714 assert_eq!(two_n3.mantissa(), 2);
715 assert_eq!(two_0.mantissa(), 2);
716 assert_eq!(zero_p6.mantissa(), 0);
717 assert_eq!(zero_n6.mantissa(), 0);
718
719 assert_eq!(two_p3.checked_mul(two_p3), Some(four_p6));
721 assert_eq!(two_n3.checked_mul(two_n3), Some(four_n6));
722 assert_eq!(two_p6.checked_mul(two_p6), Some(four_p12));
723 assert_eq!(two_n6.checked_mul(two_n6), Some(four_n12));
724 assert_eq!(two_0.checked_mul(two_p6), Some(four_p6));
725 assert_eq!(two_0.checked_mul(two_n6), Some(four_n6));
726 assert_eq!(two_n6.checked_mul(two_p6), Some(four_0));
727
728 assert_eq!(two_p6.checked_mul(two_p6), Some(zero_p6));
730 assert_eq!(two_p6.checked_mul(two_p3), Some(zero_p6));
731 assert_eq!(two_n6.checked_mul(two_p3), Some(zero_n6));
732 assert_eq!(two_n12.checked_mul(two_p12), Some(zero_n6));
733
734 assert_eq!(two_p6.checked_mul(two_p3), four_p12.checked_mul_int(1000));
736 assert_eq!(two_p6.checked_mul(two_0), four_p12.checked_mul_int(1000000));
737 assert_eq!(two_n6.checked_mul(two_n3), four_n3.checked_mul_int(1000000));
738 assert_eq!(two_n6.checked_mul(two_p3), four_p3.checked_mul_int(1000000));
739 assert_eq!(two_p6.checked_mul(two_n3), four_p6.checked_mul_int(1000));
740 assert_eq!(two_n12.checked_mul(two_p12), four_p3.checked_mul_int(1000));
741
742 assert_eq!(two_p6.checked_mul::<_, 6, 0>(two_p6), None);
744 assert_eq!(two_p12.checked_mul::<_, 6, 6>(two_p6), None);
745 assert_eq!(two_p6.checked_mul::<_, -6, -10>(two_n6), None);
746
747 assert_eq!(two_n6.checked_mul::<_, -6, 0>(two_n6), None);
749 assert_eq!(two_n12.checked_mul::<_, -6, -6>(two_n6), None);
750 assert_eq!(two_n6.checked_mul::<_, 6, 10>(two_p6), None);
751 }
752
753 #[test]
754 fn test_mul_overflow() {
755 let max_p6 = ConstScaleFpdec::<i32, 6>::MAX;
756 let min_p6 = ConstScaleFpdec::<i32, 6>::MIN;
757 let ten_p6: ConstScaleFpdec<i32, 6> = fpdec!(10);
758 let half_min_p6 = ConstScaleFpdec::<i32, 6>::MIN.checked_div_int(2).unwrap();
759 let half_max_p6 = ConstScaleFpdec::<i32, 6>::MAX
760 .checked_div_int_ext(2, Rounding::Floor)
761 .unwrap();
762
763 let max_p5 = ConstScaleFpdec::<i32, 5>::MAX;
764 let min_p5 = ConstScaleFpdec::<i32, 5>::MIN;
765
766 assert_eq!(max_p6.checked_mul_int(2), None);
767 assert_eq!(min_p6.checked_mul_int(2), None);
768 assert_eq!(half_min_p6.checked_mul_int(2), Some(min_p6));
769 assert_eq!(
770 half_max_p6.checked_mul_int(2),
771 max_p6.checked_sub(fpdec!(1e-6))
772 );
773
774 assert_eq!(max_p6.checked_mul(ten_p6), Some(max_p5));
775 assert_eq!(min_p6.checked_mul(ten_p6), Some(min_p5));
776
777 assert_eq!(max_p6.checked_mul::<_, 6, 6>(max_p6), None);
779 assert_eq!(max_p6.checked_mul::<_, 6, 6>(ten_p6), None);
780 assert_eq!(half_max_p6.checked_mul::<_, 6, 6>(ten_p6), None);
781 assert_eq!(min_p6.checked_mul::<_, 6, 6>(min_p6), None);
782 assert_eq!(min_p6.checked_mul::<_, 6, 6>(ten_p6), None);
783 assert_eq!(half_min_p6.checked_mul::<_, 6, 6>(ten_p6), None);
784
785 assert_eq!(max_p6.checked_mul::<_, 6, 2>(max_p6), None);
787 assert_eq!(ten_p6.checked_mul::<_, 6, 2>(ten_p6), None);
788 assert_eq!(max_p6.checked_mul::<_, 6, -22>(max_p6), None);
789 assert_eq!(ten_p6.checked_mul::<_, 6, -22>(ten_p6), None);
790 }
791
792 #[test]
793 fn test_div() {
794 let two_p12: ConstScaleFpdec<i32, 12> = fpdec!(2e-12);
795 let two_n12: ConstScaleFpdec<i32, -12> = fpdec!(2e+12);
796 let two_p6: ConstScaleFpdec<i32, 6> = fpdec!(2e-6);
797 let two_n6: ConstScaleFpdec<i32, -6> = fpdec!(2e+6);
798 let two_p3: ConstScaleFpdec<i32, 3> = fpdec!(2e-3);
799 let two_n3: ConstScaleFpdec<i32, -3> = fpdec!(2e+3);
800 let two_0: ConstScaleFpdec<i32, 0> = fpdec!(2);
801
802 let zero_p6 = ConstScaleFpdec::<i32, 6>::ZERO;
803 let zero_n6 = ConstScaleFpdec::<i32, -6>::ZERO;
804
805 let four_p12: ConstScaleFpdec<i32, 12> = fpdec!(4e-12);
806 let four_n12: ConstScaleFpdec<i32, -12> = fpdec!(4e+12);
807 let four_p6: ConstScaleFpdec<i32, 6> = fpdec!(4e-6);
808 let four_n6: ConstScaleFpdec<i32, -6> = fpdec!(4e+6);
809 let four_p3: ConstScaleFpdec<i32, 3> = fpdec!(4e-3);
810 let four_n3: ConstScaleFpdec<i32, -3> = fpdec!(4e+3);
811 let four_0: ConstScaleFpdec<i32, 0> = fpdec!(4);
812
813 assert_eq!(four_p3.checked_div(two_p3), Some(two_0));
815 assert_eq!(four_n3.checked_div(two_n3), Some(two_0));
816 assert_eq!(four_p12.checked_div(two_p6), Some(two_p6));
817 assert_eq!(four_n6.checked_div(two_n12), Some(two_p6));
818 assert_eq!(four_0.checked_div(two_p6), Some(two_n6));
819 assert_eq!(four_0.checked_div(two_n6), Some(two_p6));
820 assert_eq!(four_n6.checked_div(two_p6), Some(two_n12));
821
822 assert_eq!(four_p6.checked_div(two_p6), Some(zero_n6));
824 assert_eq!(four_p12.checked_div(two_p3), Some(zero_p6));
825 assert_eq!(four_p6.checked_div(two_n3), Some(zero_p6));
826
827 assert_eq!(four_p6.checked_div(two_p3), two_p6.checked_mul_int(1000));
829 assert_eq!(four_p6.checked_div(two_0), two_p12.checked_mul_int(1000000));
830 assert_eq!(four_n6.checked_div(two_n3), two_0.checked_mul_int(1000));
831 assert_eq!(four_n6.checked_div(two_p3), two_n6.checked_mul_int(1000));
832 assert_eq!(four_p6.checked_div(two_n3), two_p12.checked_mul_int(1000));
833
834 assert_eq!(four_p6.checked_div::<_, 6, -10>(two_p6), None);
836 assert_eq!(four_p12.checked_div::<_, 6, -6>(two_p6), None);
837 assert_eq!(four_p6.checked_div::<_, -6, 0>(two_n6), None);
838
839 assert_eq!(four_n6.checked_div::<_, -6, 10>(two_n6), None);
841 assert_eq!(four_n12.checked_div::<_, -6, 6>(two_n6), None);
842 assert_eq!(four_n6.checked_div::<_, 6, 0>(two_p6), None);
843 }
844
845 #[test]
846 fn test_div_overflow() {
847 let max_p6 = ConstScaleFpdec::<i32, 6>::MAX;
848 let min_p6 = ConstScaleFpdec::<i32, 6>::MIN;
849 let cent_p6: ConstScaleFpdec<i32, 6> = fpdec!(0.1);
850 let half_min_p6 = ConstScaleFpdec::<i32, 6>::MIN.checked_div_int(2).unwrap();
851 let half_max_p6 = ConstScaleFpdec::<i32, 6>::MAX
852 .checked_div_int_ext(2, Rounding::Floor)
853 .unwrap();
854
855 let max_p5 = ConstScaleFpdec::<i32, 5>::MAX;
856 let min_p5 = ConstScaleFpdec::<i32, 5>::MIN;
857
858 assert_eq!(max_p6.checked_div(cent_p6), Some(max_p5));
859 assert_eq!(min_p6.checked_div(cent_p6), Some(min_p5));
860
861 assert_eq!(max_p6.checked_div::<_, 6, 6>(cent_p6), None);
863 assert_eq!(half_max_p6.checked_div::<_, 6, 6>(cent_p6), None);
864 assert_eq!(min_p6.checked_div::<_, 6, 6>(cent_p6), None);
865 assert_eq!(half_min_p6.checked_div::<_, 6, 6>(cent_p6), None);
866
867 assert_eq!(max_p6.checked_div::<_, 6, 10>(max_p6), None);
869 assert_eq!(cent_p6.checked_div::<_, 6, 10>(cent_p6), None);
870 assert_eq!(max_p6.checked_div::<_, 6, -10>(max_p6), None);
871 assert_eq!(cent_p6.checked_div::<_, 6, -10>(cent_p6), None);
872 }
873
874 type Dec32p2 = ConstScaleFpdec<i32, 2>;
875 type Dec32n2 = ConstScaleFpdec<i32, -2>;
876 #[test]
877 fn test_from_int() {
878 assert_eq!(Dec32p2::try_from(1_i16).unwrap().mantissa(), 100);
879 assert_eq!(Dec32p2::try_from(i32::MAX), Err(ParseError::Overflow));
880
881 assert_eq!(
883 Dec32p2::try_from(i16::MAX).unwrap().mantissa(),
884 i16::MAX as i32 * 100
885 );
886
887 assert_eq!(
889 Dec32n2::try_from(i32::MAX as i64 * 100).unwrap().mantissa(),
890 i32::MAX
891 );
892
893 assert_eq!(Dec32p2::try_from(i32::MAX), Err(ParseError::Overflow));
895 assert_eq!(
896 Dec32n2::try_from(i32::MAX as i64 * 1000),
897 Err(ParseError::Overflow)
898 );
899 }
900
901 #[test]
902 fn test_from_float() {
903 assert_eq!(Dec32p2::try_from(3.1415).unwrap().mantissa(), 314);
904 assert_eq!(Dec32n2::try_from(31415.16).unwrap().mantissa(), 314);
905
906 assert_eq!(Dec32p2::try_from(3.14e10), Err(ParseError::Overflow));
907 assert_eq!(Dec32n2::try_from(3.14e16), Err(ParseError::Overflow));
908 }
909
910 #[test]
911 fn test_fmt() {
912 assert_eq!(Dec32p2::from_str("0"), Ok(fpdec!(0)));
914 assert_eq!(Dec32p2::from_str("1000"), Ok(fpdec!(1000)));
915 assert_eq!(Dec32p2::from_str("-1000"), Ok(fpdec!(-1000)));
916 assert_eq!(Dec32p2::from_str("0.12"), Ok(fpdec!(0.12)));
917 assert_eq!(Dec32p2::from_str("-0.12"), Ok(fpdec!(-0.12)));
918 assert_eq!(Dec32p2::from_str("3.14"), Ok(fpdec!(3.14)));
919 assert_eq!(Dec32p2::from_str("-3.14"), Ok(fpdec!(-3.14)));
920 assert_eq!(Dec32p2::from_str("3.1415"), Err(ParseError::Precision));
921
922 assert_eq!(Dec32n2::from_str("1000"), Ok(fpdec!(1000)));
923 assert_eq!(Dec32n2::from_str("-1000"), Ok(fpdec!(-1000)));
924 assert_eq!(Dec32n2::from_str("1000.00"), Err(ParseError::Precision));
925 assert_eq!(Dec32n2::from_str("1001"), Err(ParseError::Precision));
926 }
927
928 struct Buffer {
930 data: [u8; 100],
931 len: usize,
932 }
933 impl Buffer {
934 fn new() -> Self {
935 Buffer {
936 data: [0; 100],
937 len: 0,
938 }
939 }
940 fn as_str(&self) -> &str {
941 unsafe { core::str::from_utf8_unchecked(&self.data[..self.len]) }
942 }
943 }
944 use core::fmt::Write;
945 impl Write for Buffer {
946 fn write_str(&mut self, s: &str) -> fmt::Result {
947 let bytes = s.as_bytes();
948 if self.len + bytes.len() > self.data.len() {
949 return Err(fmt::Error);
950 }
951 self.data[self.len..self.len + bytes.len()].copy_from_slice(bytes);
952 self.len += bytes.len();
953 Ok(())
954 }
955 }
956
957 type Dec64p7 = ConstScaleFpdec<i64, 7>;
958 fn do_check_fmt(f: f64) {
959 let mut buf = Buffer::new();
960 let dec: Dec64p7 = fpdec!(f);
961 write!(buf, "{dec}").unwrap();
962 let dec2: Dec64p7 = Dec64p7::from_str(buf.as_str()).unwrap();
963 assert_eq!(dec, dec2);
964
965 let mut buf = Buffer::new();
967 let dec: Dec64p7 = fpdec!(-f);
968 write!(buf, "{dec:.7}").unwrap();
969 let dec2: Dec64p7 = Dec64p7::from_str(buf.as_str()).unwrap();
970 assert_eq!(dec, dec2);
971
972 let mut buf = Buffer::new();
974 let dec: Dec64p7 = fpdec!(-f);
975 write!(buf, "{dec}").unwrap();
976 let dec2: Dec64p7 = Dec64p7::from_str(buf.as_str()).unwrap();
977 assert_eq!(dec, dec2);
978 }
979
980 #[test]
981 fn test_fmt2() {
982 do_check_fmt(0.0);
983 do_check_fmt(1.0);
984 do_check_fmt(123.0);
985 do_check_fmt(123.456);
986 do_check_fmt(123.4567);
987 do_check_fmt(123.002);
988 do_check_fmt(123.00002);
989 do_check_fmt(123.0000002);
990 do_check_fmt(0.456);
991 do_check_fmt(0.4567);
992 do_check_fmt(0.002);
993 do_check_fmt(0.00002);
994 do_check_fmt(0.0000002);
995 }
996}