1#![doc = docify::embed!("./src/lib.rs", fixed_u64)]
22#![doc = docify::embed!(
29 "./src/lib.rs",
30 fixed_u64_block_computation_example
31)]
32#![doc = docify::embed!(
40 "./src/lib.rs",
41 fixed_u64_operation_example
42)]
43use crate::{
46 helpers_128bit::{multiply_by_rational_with_rounding, sqrt},
47 traits::{
48 Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedSub, One,
49 SaturatedConversion, Saturating, UniqueSaturatedInto, Zero,
50 },
51 PerThing, Perbill, Rounding, SignedRounding,
52};
53use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode};
54use core::{
55 fmt::Debug,
56 ops::{self, Add, Div, Mul, Sub},
57};
58
59#[cfg(feature = "serde")]
60use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
61
62#[cfg(all(not(feature = "std"), feature = "serde"))]
63use alloc::string::{String, ToString};
64
65pub trait FixedPointOperand:
67 Copy
68 + Clone
69 + Bounded
70 + Zero
71 + Saturating
72 + PartialOrd<Self>
73 + UniqueSaturatedInto<u128>
74 + TryFrom<u128>
75 + CheckedNeg
76{
77}
78
79impl<T> FixedPointOperand for T where
80 T: Copy
81 + Clone
82 + Bounded
83 + Zero
84 + Saturating
85 + PartialOrd<Self>
86 + UniqueSaturatedInto<u128>
87 + TryFrom<u128>
88 + CheckedNeg
89{
90}
91
92pub trait FixedPointNumber:
100 Sized
101 + Copy
102 + Default
103 + Debug
104 + Saturating
105 + Bounded
106 + Eq
107 + PartialEq
108 + Ord
109 + PartialOrd
110 + CheckedSub
111 + CheckedAdd
112 + CheckedMul
113 + CheckedDiv
114 + Add
115 + Sub
116 + Div
117 + Mul
118 + Zero
119 + One
120{
121 type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
123
124 const DIV: Self::Inner;
126
127 const SIGNED: bool;
129
130 fn accuracy() -> Self::Inner {
132 Self::DIV
133 }
134
135 fn from_inner(int: Self::Inner) -> Self;
137
138 fn into_inner(self) -> Self::Inner;
140
141 #[must_use]
143 fn checked_sqrt(self) -> Option<Self>;
144
145 #[must_use]
149 fn saturating_from_integer<N: FixedPointOperand>(int: N) -> Self {
150 let mut n: I129 = int.into();
151 n.value = n.value.saturating_mul(Self::DIV.saturated_into());
152 Self::from_inner(from_i129(n).unwrap_or_else(|| to_bound(int, 0)))
153 }
154
155 #[must_use]
159 fn checked_from_integer<N: Into<Self::Inner>>(int: N) -> Option<Self> {
160 let int: Self::Inner = int.into();
161 int.checked_mul(&Self::DIV).map(Self::from_inner)
162 }
163
164 #[must_use]
168 fn saturating_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Self {
169 if d == D::zero() {
170 panic!("attempt to divide by zero")
171 }
172 Self::checked_from_rational(n, d).unwrap_or_else(|| to_bound(n, d))
173 }
174
175 #[must_use]
179 fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
180 n: N,
181 d: D,
182 ) -> Option<Self> {
183 if d == D::zero() {
184 return None;
185 }
186
187 let n: I129 = n.into();
188 let d: I129 = d.into();
189 let negative = n.negative != d.negative;
190
191 multiply_by_rational_with_rounding(
192 n.value,
193 Self::DIV.unique_saturated_into(),
194 d.value,
195 Rounding::from_signed(SignedRounding::Minor, negative),
196 )
197 .and_then(|value| from_i129(I129 { value, negative }))
198 .map(Self::from_inner)
199 }
200
201 #[must_use]
205 fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
206 let lhs: I129 = self.into_inner().into();
207 let rhs: I129 = n.into();
208 let negative = lhs.negative != rhs.negative;
209
210 multiply_by_rational_with_rounding(
211 lhs.value,
212 rhs.value,
213 Self::DIV.unique_saturated_into(),
214 Rounding::from_signed(SignedRounding::Minor, negative),
215 )
216 .and_then(|value| from_i129(I129 { value, negative }))
217 }
218
219 #[must_use]
223 fn saturating_mul_int<N: FixedPointOperand>(self, n: N) -> N {
224 self.checked_mul_int(n).unwrap_or_else(|| to_bound(self.into_inner(), n))
225 }
226
227 #[must_use]
231 fn checked_div_int<N: FixedPointOperand>(self, d: N) -> Option<N> {
232 let lhs: I129 = self.into_inner().into();
233 let rhs: I129 = d.into();
234 let negative = lhs.negative != rhs.negative;
235
236 lhs.value
237 .checked_div(rhs.value)
238 .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
239 .and_then(|value| from_i129(I129 { value, negative }))
240 }
241
242 #[must_use]
246 fn saturating_div_int<N: FixedPointOperand>(self, d: N) -> N {
247 if d == N::zero() {
248 panic!("attempt to divide by zero")
249 }
250 self.checked_div_int(d).unwrap_or_else(|| to_bound(self.into_inner(), d))
251 }
252
253 #[must_use]
258 fn saturating_mul_acc_int<N: FixedPointOperand>(self, n: N) -> N {
259 if self.is_negative() && n > N::zero() {
260 n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n))
261 } else {
262 self.saturating_mul_int(n).saturating_add(n)
263 }
264 }
265
266 #[must_use]
270 fn saturating_abs(self) -> Self {
271 let inner = self.into_inner();
272 if inner >= Self::Inner::zero() {
273 self
274 } else {
275 Self::from_inner(inner.checked_neg().unwrap_or_else(Self::Inner::max_value))
276 }
277 }
278
279 #[must_use]
283 fn reciprocal(self) -> Option<Self> {
284 Self::one().checked_div(&self)
285 }
286
287 fn is_one(&self) -> bool {
289 self.into_inner() == Self::Inner::one()
290 }
291
292 fn is_positive(self) -> bool {
294 self.into_inner() > Self::Inner::zero()
295 }
296
297 fn is_negative(self) -> bool {
299 self.into_inner() < Self::Inner::zero()
300 }
301
302 #[must_use]
304 fn trunc(self) -> Self {
305 self.into_inner()
306 .checked_div(&Self::DIV)
307 .expect("panics only if DIV is zero, DIV is not zero; qed")
308 .checked_mul(&Self::DIV)
309 .map(Self::from_inner)
310 .expect("can not overflow since fixed number is >= integer part")
311 }
312
313 #[must_use]
318 fn frac(self) -> Self {
319 let integer = self.trunc();
320 let fractional = self.saturating_sub(integer);
321 if integer == Self::zero() {
322 fractional
323 } else {
324 fractional.saturating_abs()
325 }
326 }
327
328 #[must_use]
332 fn ceil(self) -> Self {
333 if self.is_negative() {
334 self.trunc()
335 } else if self.frac() == Self::zero() {
336 self
337 } else {
338 self.saturating_add(Self::one()).trunc()
339 }
340 }
341
342 #[must_use]
346 fn floor(self) -> Self {
347 if self.is_negative() {
348 self.saturating_sub(Self::one()).trunc()
349 } else {
350 self.trunc()
351 }
352 }
353
354 #[must_use]
358 fn round(self) -> Self {
359 let n = self.frac().saturating_mul(Self::saturating_from_integer(10));
360 if n < Self::saturating_from_integer(5) {
361 self.trunc()
362 } else if self.is_positive() {
363 self.saturating_add(Self::one()).trunc()
364 } else {
365 self.saturating_sub(Self::one()).trunc()
366 }
367 }
368}
369
370struct I129 {
372 value: u128,
373 negative: bool,
374}
375
376impl<N: FixedPointOperand> From<N> for I129 {
377 fn from(n: N) -> I129 {
378 if n < N::zero() {
379 let value: u128 = n
380 .checked_neg()
381 .map(|n| n.unique_saturated_into())
382 .unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
383 I129 { value, negative: true }
384 } else {
385 I129 { value: n.unique_saturated_into(), negative: false }
386 }
387 }
388}
389
390fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
392 let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
393 if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
394 Some(N::min_value())
395 } else {
396 let unsigned_inner: N = n.value.try_into().ok()?;
397 let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner };
398 Some(inner)
399 }
400}
401
402fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
404 if (n < N::zero()) != (m < D::zero()) {
405 R::min_value()
406 } else {
407 R::max_value()
408 }
409}
410
411macro_rules! implement_fixed {
412 (
413 $name:ident,
414 $test_mod:ident,
415 $inner_type:ty,
416 $signed:tt,
417 $div:tt,
418 $title:expr $(,)?
419 ) => {
420 #[doc = $title]
422 #[derive(
423 Encode,
424 Decode,
425 DecodeWithMemTracking,
426 CompactAs,
427 Default,
428 Copy,
429 Clone,
430 codec::MaxEncodedLen,
431 PartialEq,
432 Eq,
433 PartialOrd,
434 Ord,
435 scale_info::TypeInfo,
436 )]
437 pub struct $name($inner_type);
438
439 impl From<$inner_type> for $name {
440 fn from(int: $inner_type) -> Self {
441 $name::saturating_from_integer(int)
442 }
443 }
444
445 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
446 fn from(r: (N, D)) -> Self {
447 $name::saturating_from_rational(r.0, r.1)
448 }
449 }
450
451 impl FixedPointNumber for $name {
452 type Inner = $inner_type;
453
454 const DIV: Self::Inner = $div;
455 const SIGNED: bool = $signed;
456
457 fn from_inner(inner: Self::Inner) -> Self {
458 Self(inner)
459 }
460
461 fn into_inner(self) -> Self::Inner {
462 self.0
463 }
464
465 fn checked_sqrt(self) -> Option<Self> {
466 self.checked_sqrt()
467 }
468 }
469
470 impl $name {
471 pub const fn from_inner(inner: $inner_type) -> Self {
475 Self(inner)
476 }
477
478 pub const fn into_inner(self) -> $inner_type {
482 self.0
483 }
484
485 pub const fn from_u32(n: u32) -> Self {
490 Self::from_inner((n as $inner_type) * $div)
491 }
492
493 #[cfg(any(feature = "std", test))]
495 pub fn from_float(x: f64) -> Self {
496 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
497 }
498
499 pub const fn from_perbill(n: Perbill) -> Self {
501 Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
502 }
503
504 pub const fn into_perbill(self) -> Perbill {
506 if self.0 <= 0 {
507 Perbill::zero()
508 } else if self.0 >= $div {
509 Perbill::one()
510 } else {
511 match multiply_by_rational_with_rounding(
512 self.0 as u128,
513 1_000_000_000,
514 Self::DIV as u128,
515 Rounding::NearestPrefDown,
516 ) {
517 Some(value) => {
518 if value > (u32::max_value() as u128) {
519 panic!(
520 "prior logic ensures 0<self.0<DIV; \
521 multiply ensures 0<self.0<1000000000; \
522 qed"
523 );
524 }
525 Perbill::from_parts(value as u32)
526 },
527 None => Perbill::zero(),
528 }
529 }
530 }
531
532 #[cfg(any(feature = "std", test))]
534 pub fn to_float(self) -> f64 {
535 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
536 }
537
538 pub fn try_into_perthing<P: PerThing>(self) -> Result<P, P> {
542 if self < Self::zero() {
543 Err(P::zero())
544 } else if self > Self::one() {
545 Err(P::one())
546 } else {
547 Ok(P::from_rational(self.0 as u128, $div))
548 }
549 }
550
551 pub fn into_clamped_perthing<P: PerThing>(self) -> P {
554 if self < Self::zero() {
555 P::zero()
556 } else if self > Self::one() {
557 P::one()
558 } else {
559 P::from_rational(self.0 as u128, $div)
560 }
561 }
562
563 pub const fn neg(self) -> Self {
568 Self(0 - self.0)
569 }
570
571 pub const fn sqrt(self) -> Self {
576 match self.checked_sqrt() {
577 Some(v) => v,
578 None => panic!("sqrt overflow or negative input"),
579 }
580 }
581
582 pub const fn checked_sqrt(self) -> Option<Self> {
584 if self.0 == 0 {
585 return Some(Self(0));
586 }
587 if self.0 < 1 {
588 return None;
589 }
590 let v = self.0 as u128;
591
592 let maybe_vd = u128::checked_mul(v, $div);
602 let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
603 Some(Self(r as $inner_type))
604 }
605
606 pub const fn add(self, rhs: Self) -> Self {
611 Self(self.0 + rhs.0)
612 }
613
614 pub const fn sub(self, rhs: Self) -> Self {
619 Self(self.0 - rhs.0)
620 }
621
622 pub const fn mul(self, rhs: Self) -> Self {
630 match $name::const_checked_mul(self, rhs) {
631 Some(v) => v,
632 None => panic!("attempt to multiply with overflow"),
633 }
634 }
635
636 pub const fn div(self, rhs: Self) -> Self {
644 match $name::const_checked_div(self, rhs) {
645 Some(v) => v,
646 None => panic!("attempt to divide with overflow or NaN"),
647 }
648 }
649
650 const fn into_i129(self) -> I129 {
655 #[allow(unused_comparisons)]
656 if self.0 < 0 {
657 let value = match self.0.checked_neg() {
658 Some(n) => n as u128,
659 None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
660 };
661 I129 { value, negative: true }
662 } else {
663 I129 { value: self.0 as u128, negative: false }
664 }
665 }
666
667 const fn from_i129(n: I129) -> Option<Self> {
672 let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
673 #[allow(unused_comparisons)]
674 let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
675 <$inner_type>::min_value()
676 } else {
677 let unsigned_inner = n.value as $inner_type;
678 if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
679 return None;
680 };
681 if n.negative {
682 match unsigned_inner.checked_neg() {
683 Some(v) => v,
684 None => return None,
685 }
686 } else {
687 unsigned_inner
688 }
689 };
690 Some(Self(inner))
691 }
692
693 pub const fn from_rational(a: u128, b: u128) -> Self {
701 Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
702 }
703
704 pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
709 if b == 0 {
710 panic!("attempt to divide by zero in from_rational")
711 }
712 match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
713 Some(value) => match Self::from_i129(I129 { value, negative: false }) {
714 Some(x) => x,
715 None => panic!("overflow in from_rational"),
716 },
717 None => panic!("overflow in from_rational"),
718 }
719 }
720
721 pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
726 self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
727 }
728
729 pub const fn const_checked_mul_with_rounding(
735 self,
736 other: Self,
737 rounding: SignedRounding,
738 ) -> Option<Self> {
739 let lhs = self.into_i129();
740 let rhs = other.into_i129();
741 let negative = lhs.negative != rhs.negative;
742
743 match multiply_by_rational_with_rounding(
744 lhs.value,
745 rhs.value,
746 Self::DIV as u128,
747 Rounding::from_signed(rounding, negative),
748 ) {
749 Some(value) => Self::from_i129(I129 { value, negative }),
750 None => None,
751 }
752 }
753
754 pub const fn const_checked_div(self, other: Self) -> Option<Self> {
759 self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
760 }
761
762 pub const fn checked_rounding_div(
768 self,
769 other: Self,
770 rounding: SignedRounding,
771 ) -> Option<Self> {
772 if other.0 == 0 {
773 return None;
774 }
775
776 let lhs = self.into_i129();
777 let rhs = other.into_i129();
778 let negative = lhs.negative != rhs.negative;
779
780 match multiply_by_rational_with_rounding(
781 lhs.value,
782 Self::DIV as u128,
783 rhs.value,
784 Rounding::from_signed(rounding, negative),
785 ) {
786 Some(value) => Self::from_i129(I129 { value, negative }),
787 None => None,
788 }
789 }
790 }
791
792 impl Saturating for $name {
793 fn saturating_add(self, rhs: Self) -> Self {
794 Self(self.0.saturating_add(rhs.0))
795 }
796
797 fn saturating_sub(self, rhs: Self) -> Self {
798 Self(self.0.saturating_sub(rhs.0))
799 }
800
801 fn saturating_mul(self, rhs: Self) -> Self {
802 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
803 }
804
805 fn saturating_pow(self, exp: usize) -> Self {
806 if exp == 0 {
807 return Self::saturating_from_integer(1);
808 }
809
810 let exp = exp as u32;
811 let msb_pos = 32 - exp.leading_zeros();
812
813 let mut result = Self::saturating_from_integer(1);
814 let mut pow_val = self;
815 for i in 0..msb_pos {
816 if ((1 << i) & exp) > 0 {
817 result = result.saturating_mul(pow_val);
818 }
819 pow_val = pow_val.saturating_mul(pow_val);
820 }
821 result
822 }
823 }
824
825 impl ops::Neg for $name {
826 type Output = Self;
827
828 fn neg(self) -> Self::Output {
829 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
830 }
831 }
832
833 impl ops::Add for $name {
834 type Output = Self;
835
836 fn add(self, rhs: Self) -> Self::Output {
837 Self(self.0 + rhs.0)
838 }
839 }
840
841 impl ops::Sub for $name {
842 type Output = Self;
843
844 fn sub(self, rhs: Self) -> Self::Output {
845 Self(self.0 - rhs.0)
846 }
847 }
848
849 impl ops::Mul for $name {
850 type Output = Self;
851
852 fn mul(self, rhs: Self) -> Self::Output {
853 self.checked_mul(&rhs)
854 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
855 }
856 }
857
858 impl ops::Div for $name {
859 type Output = Self;
860
861 fn div(self, rhs: Self) -> Self::Output {
862 if rhs.0 == 0 {
863 panic!("attempt to divide by zero")
864 }
865 self.checked_div(&rhs)
866 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
867 }
868 }
869
870 impl CheckedSub for $name {
871 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
872 self.0.checked_sub(rhs.0).map(Self)
873 }
874 }
875
876 impl CheckedAdd for $name {
877 fn checked_add(&self, rhs: &Self) -> Option<Self> {
878 self.0.checked_add(rhs.0).map(Self)
879 }
880 }
881
882 impl CheckedDiv for $name {
883 fn checked_div(&self, other: &Self) -> Option<Self> {
884 if other.0 == 0 {
885 return None;
886 }
887
888 let lhs: I129 = self.0.into();
889 let rhs: I129 = other.0.into();
890 let negative = lhs.negative != rhs.negative;
891
892 multiply_by_rational_with_rounding(
897 lhs.value,
898 Self::DIV as u128,
899 rhs.value,
900 Rounding::from_signed(SignedRounding::Minor, negative),
901 )
902 .and_then(|value| from_i129(I129 { value, negative }))
903 .map(Self)
904 }
905 }
906
907 impl CheckedMul for $name {
908 fn checked_mul(&self, other: &Self) -> Option<Self> {
909 let lhs: I129 = self.0.into();
910 let rhs: I129 = other.0.into();
911 let negative = lhs.negative != rhs.negative;
912
913 multiply_by_rational_with_rounding(
914 lhs.value,
915 rhs.value,
916 Self::DIV as u128,
917 Rounding::from_signed(SignedRounding::Minor, negative),
918 )
919 .and_then(|value| from_i129(I129 { value, negative }))
920 .map(Self)
921 }
922 }
923
924 impl Bounded for $name {
925 fn min_value() -> Self {
926 Self(<Self as FixedPointNumber>::Inner::min_value())
927 }
928
929 fn max_value() -> Self {
930 Self(<Self as FixedPointNumber>::Inner::max_value())
931 }
932 }
933
934 impl Zero for $name {
935 fn zero() -> Self {
936 Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
937 }
938
939 fn is_zero(&self) -> bool {
940 self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
941 }
942 }
943
944 impl One for $name {
945 fn one() -> Self {
946 Self::from_inner(Self::DIV)
947 }
948 }
949
950 impl ::core::fmt::Debug for $name {
951 #[cfg(feature = "std")]
952 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
953 let integral = {
954 let int = self.0 / Self::accuracy();
955 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
956 format!("{}{}", signum_for_zero, int)
957 };
958 let precision = (Self::accuracy() as f64).log10() as usize;
959 let fractional = format!(
960 "{:0>weight$}",
961 ((self.0 % Self::accuracy()) as i128).abs(),
962 weight = precision
963 );
964 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
965 }
966
967 #[cfg(not(feature = "std"))]
968 fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
969 Ok(())
970 }
971 }
972
973 impl<P: PerThing> From<P> for $name
974 where
975 P::Inner: FixedPointOperand,
976 {
977 fn from(p: P) -> Self {
978 let accuracy = P::ACCURACY;
979 let value = p.deconstruct();
980 $name::saturating_from_rational(value, accuracy)
981 }
982 }
983
984 impl ::core::fmt::Display for $name {
985 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
986 write!(f, "{}", self.0)
987 }
988 }
989
990 impl ::core::str::FromStr for $name {
991 type Err = &'static str;
992
993 fn from_str(s: &str) -> Result<Self, Self::Err> {
994 let s = s.trim();
995
996 if let Some(dot_pos) = s.find('.') {
998 let (integer_part, fractional_part) = s.split_at(dot_pos);
1000 let fractional_part = &fractional_part[1..]; let is_negative = integer_part.starts_with('-');
1004
1005 if is_negative && !$name::SIGNED {
1007 return Err(
1008 "negative numbers not supported for unsigned fixed point types",
1009 );
1010 }
1011
1012 let integer: i128 = if integer_part.is_empty() {
1014 0
1015 } else {
1016 integer_part
1017 .parse()
1018 .map_err(|_| "invalid integer part in decimal number")?
1019 };
1020
1021 let fractional_raw: u128 = if fractional_part.is_empty() {
1023 0
1024 } else {
1025 fractional_part
1026 .parse()
1027 .map_err(|_| "invalid fractional part in decimal number")?
1028 };
1029
1030 let fractional_digits = fractional_part.len() as u32;
1032
1033 let fractional_scaled: i128 = if fractional_digits > 0 {
1035 let Some(scale_factor) = 10u128.checked_pow(fractional_digits) else {
1037 return Err("fractional part has too many digits");
1038 };
1039
1040 let div_u128 = Self::DIV as u128;
1042
1043 let quotient = fractional_raw / scale_factor;
1047 let remainder = fractional_raw % scale_factor;
1048 quotient
1049 .checked_mul(div_u128)
1050 .and_then(|base| {
1051 let remainder_scaled = (remainder * div_u128) / scale_factor;
1052 base.checked_add(remainder_scaled)
1053 })
1054 .ok_or("fractional part overflow")?
1055 .try_into()
1056 .map_err(|_| "fractional part too large for signed representation")?
1057 } else {
1058 0
1059 };
1060
1061 let div_i128 = Self::DIV as i128;
1063 let integer_scaled =
1064 integer.checked_mul(div_i128).ok_or("integer part overflow")?;
1065
1066 let result = if is_negative {
1067 integer_scaled
1068 .checked_sub(fractional_scaled)
1069 .ok_or("number too large for fixed point representation")?
1070 } else {
1071 integer_scaled
1072 .checked_add(fractional_scaled)
1073 .ok_or("number too large for fixed point representation")?
1074 };
1075
1076 let inner = <Self as FixedPointNumber>::Inner::try_from(result)
1078 .map_err(|_| "number out of range for fixed point type")?;
1079
1080 Ok(Self::from_inner(inner))
1081 } else {
1082 let inner: <Self as FixedPointNumber>::Inner =
1084 s.parse().map_err(|_| "invalid string input for fixed point number")?;
1085 Ok(Self::from_inner(inner))
1086 }
1087 }
1088 }
1089
1090 #[cfg(feature = "serde")]
1093 impl Serialize for $name {
1094 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1095 where
1096 S: Serializer,
1097 {
1098 serializer.serialize_str(&self.to_string())
1099 }
1100 }
1101
1102 #[cfg(feature = "serde")]
1105 impl<'de> Deserialize<'de> for $name {
1106 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1107 where
1108 D: Deserializer<'de>,
1109 {
1110 use ::core::str::FromStr;
1111 let s = String::deserialize(deserializer)?;
1112 $name::from_str(&s).map_err(de::Error::custom)
1113 }
1114 }
1115
1116 #[cfg(test)]
1117 mod $test_mod {
1118 use super::*;
1119 use crate::{Perbill, Percent, Permill, Perquintill};
1120
1121 fn max() -> $name {
1122 $name::max_value()
1123 }
1124
1125 fn min() -> $name {
1126 $name::min_value()
1127 }
1128
1129 fn precision() -> usize {
1130 ($name::accuracy() as f64).log10() as usize
1131 }
1132
1133 #[test]
1134 fn macro_preconditions() {
1135 assert!($name::DIV > 0);
1136 }
1137
1138 #[test]
1139 fn has_max_encoded_len() {
1140 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1141 _data: T,
1142 }
1143
1144 let _ = AsMaxEncodedLen { _data: $name::min_value() };
1145 }
1146
1147 #[test]
1148 fn from_i129_works() {
1149 let a = I129 { value: 1, negative: true };
1150
1151 assert_eq!(from_i129::<u128>(a), None);
1153
1154 let a = I129 { value: u128::MAX - 1, negative: false };
1155
1156 assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1158
1159 let a = I129 { value: u128::MAX, negative: false };
1160
1161 assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1163
1164 let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1165
1166 assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1168
1169 let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1170
1171 assert_eq!(from_i129::<i128>(a), None);
1173
1174 let a = I129 { value: i128::MAX as u128, negative: false };
1175
1176 assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1178 }
1179
1180 #[test]
1181 fn to_bound_works() {
1182 let a = 1i32;
1183 let b = 1i32;
1184
1185 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1187
1188 let a = -1i32;
1189 let b = -1i32;
1190
1191 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1193
1194 let a = 1i32;
1195 let b = -1i32;
1196
1197 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1199
1200 let a = -1i32;
1201 let b = 1i32;
1202
1203 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1205
1206 let a = 1i32;
1207 let b = -1i32;
1208
1209 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1211 }
1212
1213 #[test]
1214 fn op_neg_works() {
1215 let a = $name::zero();
1216 let b = -a;
1217
1218 assert_eq!(a, b);
1220
1221 if $name::SIGNED {
1222 let a = $name::saturating_from_integer(5);
1223 let b = -a;
1224
1225 assert_eq!($name::saturating_from_integer(-5), b);
1227
1228 let a = $name::saturating_from_integer(-5);
1229 let b = -a;
1230
1231 assert_eq!($name::saturating_from_integer(5), b);
1233
1234 let a = $name::max_value();
1235 let b = -a;
1236
1237 assert_eq!($name::min_value() + $name::from_inner(1), b);
1239
1240 let a = $name::min_value() + $name::from_inner(1);
1241 let b = -a;
1242
1243 assert_eq!($name::max_value(), b);
1245 }
1246 }
1247
1248 #[test]
1249 fn op_checked_add_overflow_works() {
1250 let a = $name::max_value();
1251 let b = 1.into();
1252 assert!(a.checked_add(&b).is_none());
1253 }
1254
1255 #[test]
1256 fn op_add_works() {
1257 let a = $name::saturating_from_rational(5, 2);
1258 let b = $name::saturating_from_rational(1, 2);
1259
1260 assert_eq!($name::saturating_from_integer(3), a + b);
1262
1263 if $name::SIGNED {
1264 let b = $name::saturating_from_rational(1, -2);
1266 assert_eq!($name::saturating_from_integer(2), a + b);
1267 }
1268 }
1269
1270 #[test]
1271 fn op_checked_sub_underflow_works() {
1272 let a = $name::min_value();
1273 let b = 1.into();
1274 assert!(a.checked_sub(&b).is_none());
1275 }
1276
1277 #[test]
1278 fn op_sub_works() {
1279 let a = $name::saturating_from_rational(5, 2);
1280 let b = $name::saturating_from_rational(1, 2);
1281
1282 assert_eq!($name::saturating_from_integer(2), a - b);
1283 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1284 }
1285
1286 #[test]
1287 fn op_checked_mul_overflow_works() {
1288 let a = $name::max_value();
1289 let b = 2.into();
1290 assert!(a.checked_mul(&b).is_none());
1291 }
1292
1293 #[test]
1294 fn op_mul_works() {
1295 let a = $name::saturating_from_integer(42);
1296 let b = $name::saturating_from_integer(2);
1297 assert_eq!($name::saturating_from_integer(84), a * b);
1298
1299 let a = $name::saturating_from_integer(42);
1300 let b = $name::saturating_from_integer(-2);
1301 assert_eq!($name::saturating_from_integer(-84), a * b);
1302 }
1303
1304 #[test]
1305 #[should_panic(expected = "attempt to divide by zero")]
1306 fn op_div_panics_on_zero_divisor() {
1307 let a = $name::saturating_from_integer(1);
1308 let b = 0.into();
1309 let _c = a / b;
1310 }
1311
1312 #[test]
1313 fn op_checked_div_overflow_works() {
1314 if $name::SIGNED {
1315 let a = $name::min_value();
1316 let b = $name::zero().saturating_sub($name::one());
1317 assert!(a.checked_div(&b).is_none());
1318 }
1319 }
1320
1321 #[test]
1322 fn op_sqrt_works() {
1323 for i in 1..1_000i64 {
1324 let x = $name::saturating_from_rational(i, 1_000i64);
1325 assert_eq!((x * x).checked_sqrt(), Some(x));
1326 let x = $name::saturating_from_rational(i, 1i64);
1327 assert_eq!((x * x).checked_sqrt(), Some(x));
1328 }
1329 }
1330
1331 #[test]
1332 fn op_div_works() {
1333 let a = $name::saturating_from_integer(42);
1334 let b = $name::saturating_from_integer(2);
1335 assert_eq!($name::saturating_from_integer(21), a / b);
1336
1337 if $name::SIGNED {
1338 let a = $name::saturating_from_integer(42);
1339 let b = $name::saturating_from_integer(-2);
1340 assert_eq!($name::saturating_from_integer(-21), a / b);
1341 }
1342 }
1343
1344 #[test]
1345 fn saturating_from_integer_works() {
1346 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1347 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1348 let accuracy = $name::accuracy();
1349
1350 let a = $name::saturating_from_integer(42);
1352 assert_eq!(a.into_inner(), 42 * accuracy);
1353
1354 let a = $name::saturating_from_integer(-42);
1355 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1356
1357 let a = $name::saturating_from_integer(inner_max / accuracy);
1359 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1360
1361 let a = $name::saturating_from_integer(inner_min / accuracy);
1362 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1363
1364 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1366 assert_eq!(a.into_inner(), inner_max);
1367
1368 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1369 assert_eq!(a.into_inner(), inner_min);
1370 }
1371
1372 #[test]
1373 fn checked_from_integer_works() {
1374 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1375 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1376 let accuracy = $name::accuracy();
1377
1378 let a = $name::checked_from_integer::<$inner_type>(42)
1380 .expect("42 * accuracy <= inner_max; qed");
1381 assert_eq!(a.into_inner(), 42 * accuracy);
1382
1383 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1385 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1386 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1387
1388 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1390 assert_eq!(a, None);
1391
1392 if $name::SIGNED {
1393 let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1395 .expect("-42 * accuracy >= inner_min; qed");
1396 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1397
1398 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1400 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1401 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1402
1403 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1405 assert_eq!(a, None);
1406 }
1407 }
1408
1409 #[test]
1410 fn from_inner_works() {
1411 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1412 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1413
1414 assert_eq!(max(), $name::from_inner(inner_max));
1415 assert_eq!(min(), $name::from_inner(inner_min));
1416 }
1417
1418 #[test]
1419 #[should_panic(expected = "attempt to divide by zero")]
1420 fn saturating_from_rational_panics_on_zero_divisor() {
1421 let _ = $name::saturating_from_rational(1, 0);
1422 }
1423
1424 #[test]
1425 fn saturating_from_rational_works() {
1426 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1427 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1428 let accuracy = $name::accuracy();
1429
1430 let a = $name::saturating_from_rational(5, 2);
1431
1432 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1434
1435 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1437 assert_eq!(a.into_inner(), inner_max - 1);
1438
1439 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1441 assert_eq!(a.into_inner(), inner_min + 1);
1442
1443 let a = $name::saturating_from_rational(inner_max, accuracy);
1445 assert_eq!(a.into_inner(), inner_max);
1446
1447 let a = $name::saturating_from_rational(inner_min, accuracy);
1449 assert_eq!(a.into_inner(), inner_min);
1450
1451 let a = $name::saturating_from_rational(0, 1);
1453 assert_eq!(a.into_inner(), 0);
1454
1455 if $name::SIGNED {
1456 let a = $name::saturating_from_rational(-5, 2);
1458 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1459
1460 let a = $name::saturating_from_rational(5, -2);
1462 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1463
1464 let a = $name::saturating_from_rational(-5, -2);
1466 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1467
1468 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1470 assert_eq!(a.into_inner(), inner_max);
1471
1472 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1474 assert_eq!(a.into_inner(), inner_min);
1475
1476 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1477 assert_eq!(a.into_inner(), 0 - inner_max);
1478
1479 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1480 assert_eq!(a.into_inner(), inner_max);
1481
1482 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1483 assert_eq!(a.into_inner(), inner_max);
1484
1485 let a = $name::saturating_from_rational(inner_min, 0 - 1);
1486 assert_eq!(a.into_inner(), inner_max);
1487
1488 let a = $name::saturating_from_rational(inner_max, 0 - 1);
1489 assert_eq!(a.into_inner(), inner_min);
1490
1491 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1492 assert_eq!(a.into_inner(), 0 - accuracy);
1493
1494 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1495 assert_eq!(a.into_inner(), 0 - accuracy);
1496
1497 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1498 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1499
1500 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1501 assert_eq!(a.into_inner(), inner_max);
1502
1503 let a = $name::saturating_from_rational(1, 0 - accuracy);
1504 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1505
1506 let a = $name::saturating_from_rational(inner_min, inner_min);
1507 assert_eq!(a.into_inner(), accuracy);
1508
1509 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1511 assert_eq!(a.into_inner(), 0);
1512 }
1513
1514 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1515 assert_eq!(a.into_inner(), inner_max - 1);
1516
1517 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1518 assert_eq!(a.into_inner(), inner_min + 1);
1519
1520 let a = $name::saturating_from_rational(inner_max, 1);
1521 assert_eq!(a.into_inner(), inner_max);
1522
1523 let a = $name::saturating_from_rational(inner_min, 1);
1524 assert_eq!(a.into_inner(), inner_min);
1525
1526 let a = $name::saturating_from_rational(inner_max, inner_max);
1527 assert_eq!(a.into_inner(), accuracy);
1528
1529 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1530 assert_eq!(a.into_inner(), inner_max / 3);
1531
1532 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1533 assert_eq!(a.into_inner(), inner_min / 2);
1534
1535 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1536 assert_eq!(a.into_inner(), inner_min);
1537
1538 let a = $name::saturating_from_rational(1, accuracy);
1539 assert_eq!(a.into_inner(), 1);
1540
1541 let a = $name::saturating_from_rational(1, accuracy + 1);
1543 assert_eq!(a.into_inner(), 0);
1544 }
1545
1546 #[test]
1547 fn checked_from_rational_works() {
1548 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1549 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1550 let accuracy = $name::accuracy();
1551
1552 let a = $name::checked_from_rational(1, 0);
1554 assert_eq!(a, None);
1555
1556 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1558 assert_eq!(a.into_inner(), inner_max - 1);
1559
1560 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1562 assert_eq!(a.into_inner(), inner_min + 1);
1563
1564 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1566 assert_eq!(a.into_inner(), inner_max);
1567
1568 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1570 assert_eq!(a.into_inner(), inner_min);
1571
1572 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1574 assert_eq!(a, None);
1575
1576 if $name::SIGNED {
1577 let a = $name::checked_from_rational(
1579 inner_max as u128 + 2,
1580 0.saturating_sub(accuracy),
1581 );
1582 assert_eq!(a, None);
1583
1584 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1585 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1586
1587 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1588 assert_eq!(a, None);
1589
1590 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1591 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1592
1593 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1594 assert_eq!(a.into_inner(), 0);
1595
1596 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1597 assert_eq!(a, None);
1598 }
1599
1600 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1601 assert_eq!(a.into_inner(), inner_max / 3);
1602
1603 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1604 assert_eq!(a.into_inner(), inner_min / 2);
1605
1606 let a = $name::checked_from_rational(1, accuracy).unwrap();
1607 assert_eq!(a.into_inner(), 1);
1608
1609 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1610 assert_eq!(a.into_inner(), 0);
1611 }
1612
1613 #[test]
1614 fn from_rational_works() {
1615 let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1616 let inner_min: u128 = 0;
1617 let accuracy: u128 = $name::accuracy() as u128;
1618
1619 let a = $name::from_rational(inner_max - 1, accuracy);
1621 assert_eq!(a.into_inner() as u128, inner_max - 1);
1622
1623 let a = $name::from_rational(inner_min + 1, accuracy);
1625 assert_eq!(a.into_inner() as u128, inner_min + 1);
1626
1627 let a = $name::from_rational(inner_max, accuracy);
1629 assert_eq!(a.into_inner() as u128, inner_max);
1630
1631 let a = $name::from_rational(inner_min, accuracy);
1633 assert_eq!(a.into_inner() as u128, inner_min);
1634
1635 let a = $name::from_rational(inner_max, 3 * accuracy);
1636 assert_eq!(a.into_inner() as u128, inner_max / 3);
1637
1638 let a = $name::from_rational(1, accuracy);
1639 assert_eq!(a.into_inner() as u128, 1);
1640
1641 let a = $name::from_rational(1, accuracy + 1);
1642 assert_eq!(a.into_inner() as u128, 1);
1643
1644 let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1645 assert_eq!(a.into_inner() as u128, 0);
1646 }
1647
1648 #[test]
1649 fn checked_mul_int_works() {
1650 let a = $name::saturating_from_integer(2);
1651 assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1653 assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1655 assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1657
1658 if $name::SIGNED {
1659 assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1661 assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1663 assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1665
1666 let b = $name::saturating_from_rational(1, -2);
1667 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1668 assert_eq!(b.checked_mul_int(u128::MAX), None);
1669 assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1670 assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1671 }
1672
1673 let a = $name::saturating_from_rational(1, 2);
1674 assert_eq!(a.checked_mul_int(42i128), Some(21));
1675 assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1676 assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1677
1678 let c = $name::saturating_from_integer(255);
1679 assert_eq!(c.checked_mul_int(2i8), None);
1680 assert_eq!(c.checked_mul_int(2i128), Some(510));
1681 assert_eq!(c.checked_mul_int(i128::MAX), None);
1682 assert_eq!(c.checked_mul_int(i128::MIN), None);
1683 }
1684
1685 #[test]
1686 fn saturating_mul_int_works() {
1687 let a = $name::saturating_from_integer(2);
1688 assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1690 assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1692 assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1694
1695 assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1697 assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1699 assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1701
1702 if $name::SIGNED {
1703 let b = $name::saturating_from_rational(1, -2);
1704 assert_eq!(b.saturating_mul_int(42i32), -21);
1705 assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1706 assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1707 assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1708 }
1709
1710 let a = $name::saturating_from_rational(1, 2);
1711 assert_eq!(a.saturating_mul_int(42i32), 21);
1712 assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1713 assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1714
1715 let c = $name::saturating_from_integer(255);
1716 assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1717 assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1718 assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1719 assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1720 }
1721
1722 #[test]
1723 fn checked_mul_works() {
1724 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1725 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1726
1727 let a = $name::saturating_from_integer(2);
1728
1729 let b = $name::from_inner(inner_max - 1);
1731 assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1732
1733 let c = $name::from_inner(inner_max);
1735 assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1736
1737 let e = $name::from_inner(1);
1739 assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1740
1741 if $name::SIGNED {
1742 let b = $name::from_inner(inner_min + 1) / 2.into();
1744 let c = $name::from_inner(inner_min + 2);
1745 assert_eq!(a.checked_mul(&b), Some(c));
1746
1747 let b = $name::from_inner(inner_min) / 2.into();
1749 let c = $name::from_inner(inner_min);
1750 assert_eq!(a.checked_mul(&b), Some(c));
1751
1752 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1754 assert_eq!(a.checked_mul(&b), None);
1755
1756 let c = $name::saturating_from_integer(255);
1757 let b = $name::saturating_from_rational(1, -2);
1758
1759 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1760 assert_eq!(
1761 b.checked_mul(&$name::max_value()),
1762 $name::max_value().checked_div(&0.saturating_sub(2).into())
1763 );
1764 assert_eq!(
1765 b.checked_mul(&$name::min_value()),
1766 $name::min_value().checked_div(&0.saturating_sub(2).into())
1767 );
1768 assert_eq!(c.checked_mul(&$name::min_value()), None);
1769 }
1770
1771 let a = $name::saturating_from_rational(1, 2);
1772 let c = $name::saturating_from_integer(255);
1773
1774 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1775 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1776 assert_eq!(c.checked_mul(&$name::max_value()), None);
1777 assert_eq!(
1778 a.checked_mul(&$name::max_value()),
1779 $name::max_value().checked_div(&2.into())
1780 );
1781 assert_eq!(
1782 a.checked_mul(&$name::min_value()),
1783 $name::min_value().checked_div(&2.into())
1784 );
1785 }
1786
1787 #[test]
1788 fn const_checked_mul_works() {
1789 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1790 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1791
1792 let a = $name::saturating_from_integer(2u32);
1793
1794 let b = $name::from_inner(inner_max - 1);
1796 assert_eq!(a.const_checked_mul(b / 2.into()), Some(b));
1797
1798 let c = $name::from_inner(inner_max);
1800 assert_eq!(a.const_checked_mul(c / 2.into()), Some(b));
1801
1802 let e = $name::from_inner(1);
1804 assert_eq!(a.const_checked_mul(c / 2.into() + e), None);
1805
1806 if $name::SIGNED {
1807 let b = $name::from_inner(inner_min + 1) / 2.into();
1809 let c = $name::from_inner(inner_min + 2);
1810 assert_eq!(a.const_checked_mul(b), Some(c));
1811
1812 let b = $name::from_inner(inner_min) / 2.into();
1814 let c = $name::from_inner(inner_min);
1815 assert_eq!(a.const_checked_mul(b), Some(c));
1816
1817 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1819 assert_eq!(a.const_checked_mul(b), None);
1820
1821 let b = $name::saturating_from_rational(1i32, -2i32);
1822 let c = $name::saturating_from_integer(-21i32);
1823 let d = $name::saturating_from_integer(42);
1824
1825 assert_eq!(b.const_checked_mul(d), Some(c));
1826
1827 let minus_two = $name::saturating_from_integer(-2i32);
1828 assert_eq!(
1829 b.const_checked_mul($name::max_value()),
1830 $name::max_value().const_checked_div(minus_two)
1831 );
1832 assert_eq!(
1833 b.const_checked_mul($name::min_value()),
1834 $name::min_value().const_checked_div(minus_two)
1835 );
1836
1837 let c = $name::saturating_from_integer(255u32);
1838 assert_eq!(c.const_checked_mul($name::min_value()), None);
1839 }
1840
1841 let a = $name::saturating_from_rational(1i32, 2i32);
1842 let c = $name::saturating_from_integer(255i32);
1843
1844 assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1845 assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1846 assert_eq!(c.const_checked_mul($name::max_value()), None);
1847 assert_eq!(
1848 a.const_checked_mul($name::max_value()),
1849 $name::max_value().checked_div(&2.into())
1850 );
1851 assert_eq!(
1852 a.const_checked_mul($name::min_value()),
1853 $name::min_value().const_checked_div($name::saturating_from_integer(2))
1854 );
1855 }
1856
1857 #[test]
1858 fn checked_div_int_works() {
1859 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1860 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1861 let accuracy = $name::accuracy();
1862
1863 let a = $name::from_inner(inner_max);
1864 let b = $name::from_inner(inner_min);
1865 let c = $name::zero();
1866 let d = $name::one();
1867 let e = $name::saturating_from_integer(6);
1868 let f = $name::saturating_from_integer(5);
1869
1870 assert_eq!(e.checked_div_int(2.into()), Some(3));
1871 assert_eq!(f.checked_div_int(2.into()), Some(2));
1872
1873 assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1874 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1875 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1876 assert_eq!(a.checked_div_int(1i8), None);
1877
1878 if b < c {
1879 assert_eq!(
1881 a.checked_div_int(0.saturating_sub(2)),
1882 Some(0.saturating_sub(inner_max / (2 * accuracy)))
1883 );
1884 assert_eq!(
1885 a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1886 Some(0.saturating_sub(1))
1887 );
1888 assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1889 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1890 assert_eq!(b.checked_div_int(1i8), None);
1891 assert_eq!(
1892 b.checked_div_int(0.saturating_sub(2)),
1893 Some(0.saturating_sub(inner_min / (2 * accuracy)))
1894 );
1895 assert_eq!(
1896 b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1897 Some(0.saturating_sub(1))
1898 );
1899 assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1900 assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1901 }
1902
1903 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1904
1905 assert_eq!(c.checked_div_int(1), Some(0));
1906 assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1907 assert_eq!(c.checked_div_int(1i8), Some(0));
1908
1909 assert_eq!(d.checked_div_int(1), Some(1));
1910 assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1911 assert_eq!(d.checked_div_int(1i8), Some(1));
1912
1913 assert_eq!(a.checked_div_int(0), None);
1914 assert_eq!(b.checked_div_int(0), None);
1915 assert_eq!(c.checked_div_int(0), None);
1916 assert_eq!(d.checked_div_int(0), None);
1917 }
1918
1919 #[test]
1920 #[should_panic(expected = "attempt to divide by zero")]
1921 fn saturating_div_int_panics_when_divisor_is_zero() {
1922 let _ = $name::one().saturating_div_int(0);
1923 }
1924
1925 #[test]
1926 fn saturating_div_int_works() {
1927 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1928 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1929 let accuracy = $name::accuracy();
1930
1931 let a = $name::saturating_from_integer(5);
1932 assert_eq!(a.saturating_div_int(2), 2);
1933
1934 let a = $name::min_value();
1935 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1936
1937 if $name::SIGNED {
1938 let a = $name::saturating_from_integer(5);
1939 assert_eq!(a.saturating_div_int(-2), -2);
1940
1941 let a = $name::min_value();
1942 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1943 }
1944 }
1945
1946 #[test]
1947 fn saturating_abs_works() {
1948 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1949 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1950
1951 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1952 assert_eq!($name::zero().saturating_abs(), 0.into());
1953
1954 if $name::SIGNED {
1955 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1956 assert_eq!(
1957 $name::saturating_from_rational(-1, 2).saturating_abs(),
1958 (1, 2).into()
1959 );
1960 }
1961 }
1962
1963 #[test]
1964 fn saturating_mul_acc_int_works() {
1965 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1966 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1967
1968 assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1969 assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1970
1971 assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1972 assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1973
1974 if $name::SIGNED {
1975 let a = $name::saturating_from_rational(-1, 2);
1976 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1977 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1978 assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1979 }
1980 }
1981
1982 #[test]
1983 fn saturating_pow_should_work() {
1984 assert_eq!(
1985 $name::saturating_from_integer(2).saturating_pow(0),
1986 $name::saturating_from_integer(1)
1987 );
1988 assert_eq!(
1989 $name::saturating_from_integer(2).saturating_pow(1),
1990 $name::saturating_from_integer(2)
1991 );
1992 assert_eq!(
1993 $name::saturating_from_integer(2).saturating_pow(2),
1994 $name::saturating_from_integer(4)
1995 );
1996 assert_eq!(
1997 $name::saturating_from_integer(2).saturating_pow(3),
1998 $name::saturating_from_integer(8)
1999 );
2000 assert_eq!(
2001 $name::saturating_from_integer(2).saturating_pow(50),
2002 $name::saturating_from_integer(1125899906842624i64)
2003 );
2004
2005 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
2006 assert_eq!(
2007 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
2008 (1).into()
2009 );
2010
2011 if $name::SIGNED {
2012 assert_eq!(
2014 $name::saturating_from_integer(2).saturating_pow(68),
2015 $name::max_value()
2016 );
2017
2018 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
2019 assert_eq!(
2020 $name::saturating_from_integer(-1).saturating_pow(1001),
2021 0.saturating_sub(1).into()
2022 );
2023 assert_eq!(
2024 $name::saturating_from_integer(-1).saturating_pow(usize::MAX),
2025 0.saturating_sub(1).into()
2026 );
2027 assert_eq!(
2028 $name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
2029 (1).into()
2030 );
2031 }
2032
2033 assert_eq!(
2034 $name::saturating_from_integer(114209).saturating_pow(5),
2035 $name::max_value()
2036 );
2037
2038 assert_eq!(
2039 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
2040 (1).into()
2041 );
2042 assert_eq!(
2043 $name::saturating_from_integer(0).saturating_pow(usize::MAX),
2044 (0).into()
2045 );
2046 assert_eq!(
2047 $name::saturating_from_integer(2).saturating_pow(usize::MAX),
2048 $name::max_value()
2049 );
2050 }
2051
2052 #[test]
2053 fn checked_div_works() {
2054 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
2055 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
2056
2057 let a = $name::from_inner(inner_max);
2058 let b = $name::from_inner(inner_min);
2059 let c = $name::zero();
2060 let d = $name::one();
2061 let e = $name::saturating_from_integer(6);
2062 let f = $name::saturating_from_integer(5);
2063
2064 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
2065 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
2066
2067 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
2068 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
2069 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
2070 assert_eq!(a.checked_div(&d), Some(a));
2071
2072 if b < c {
2073 assert_eq!(
2075 a.checked_div(&0.saturating_sub(2).into()),
2076 Some($name::from_inner(0.saturating_sub(inner_max / 2)))
2077 );
2078 assert_eq!(
2079 a.checked_div(&-$name::max_value()),
2080 Some(0.saturating_sub(1).into())
2081 );
2082 assert_eq!(
2083 b.checked_div(&0.saturating_sub(2).into()),
2084 Some($name::from_inner(0.saturating_sub(inner_min / 2)))
2085 );
2086 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
2087 assert_eq!(b.checked_div(&b), Some($name::one()));
2088 }
2089
2090 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
2091 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
2092 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
2093 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
2094
2095 assert_eq!(a.checked_div(&$name::one()), Some(a));
2096 assert_eq!(b.checked_div(&$name::one()), Some(b));
2097 assert_eq!(c.checked_div(&$name::one()), Some(c));
2098 assert_eq!(d.checked_div(&$name::one()), Some(d));
2099
2100 assert_eq!(a.checked_div(&$name::zero()), None);
2101 assert_eq!(b.checked_div(&$name::zero()), None);
2102 assert_eq!(c.checked_div(&$name::zero()), None);
2103 assert_eq!(d.checked_div(&$name::zero()), None);
2104 }
2105
2106 #[test]
2107 fn is_positive_negative_works() {
2108 let one = $name::one();
2109 assert!(one.is_positive());
2110 assert!(!one.is_negative());
2111
2112 let zero = $name::zero();
2113 assert!(!zero.is_positive());
2114 assert!(!zero.is_negative());
2115
2116 if $signed {
2117 let minus_one = $name::saturating_from_integer(-1);
2118 assert!(minus_one.is_negative());
2119 assert!(!minus_one.is_positive());
2120 }
2121 }
2122
2123 #[test]
2124 fn trunc_works() {
2125 let n = $name::saturating_from_rational(5, 2).trunc();
2126 assert_eq!(n, $name::saturating_from_integer(2));
2127
2128 if $name::SIGNED {
2129 let n = $name::saturating_from_rational(-5, 2).trunc();
2130 assert_eq!(n, $name::saturating_from_integer(-2));
2131 }
2132 }
2133
2134 #[test]
2135 fn frac_works() {
2136 let n = $name::saturating_from_rational(5, 2);
2137 let i = n.trunc();
2138 let f = n.frac();
2139
2140 assert_eq!(n, i + f);
2141
2142 let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2143 assert_eq!(n, 5.into());
2144
2145 let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2146 assert_eq!(n, 5.into());
2147
2148 if $name::SIGNED {
2149 let n = $name::saturating_from_rational(-5, 2);
2150 let i = n.trunc();
2151 let f = n.frac();
2152 assert_eq!(n, i - f);
2153
2154 let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2156 assert_eq!(n, 5.into());
2157
2158 let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2159 assert_eq!(n, 0.saturating_sub(5).into());
2160 }
2161 }
2162
2163 #[test]
2164 fn ceil_works() {
2165 let n = $name::saturating_from_rational(5, 2);
2166 assert_eq!(n.ceil(), 3.into());
2167
2168 let n = $name::saturating_from_rational(-5, 2);
2169 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2170
2171 let n = $name::max_value();
2173 assert_eq!(n.ceil(), n.trunc());
2174
2175 let n = $name::min_value();
2176 assert_eq!(n.ceil(), n.trunc());
2177 }
2178
2179 #[test]
2180 fn floor_works() {
2181 let n = $name::saturating_from_rational(5, 2);
2182 assert_eq!(n.floor(), 2.into());
2183
2184 let n = $name::saturating_from_rational(-5, 2);
2185 assert_eq!(n.floor(), 0.saturating_sub(3).into());
2186
2187 let n = $name::max_value();
2189 assert_eq!(n.floor(), n.trunc());
2190
2191 let n = $name::min_value();
2192 assert_eq!(n.floor(), n.trunc());
2193 }
2194
2195 #[test]
2196 fn round_works() {
2197 let n = $name::zero();
2198 assert_eq!(n.round(), n);
2199
2200 let n = $name::one();
2201 assert_eq!(n.round(), n);
2202
2203 let n = $name::saturating_from_rational(5, 2);
2204 assert_eq!(n.round(), 3.into());
2205
2206 let n = $name::saturating_from_rational(-5, 2);
2207 assert_eq!(n.round(), 0.saturating_sub(3).into());
2208
2209 let n = $name::max_value();
2211 assert_eq!(n.round(), n.trunc());
2212
2213 let n = $name::min_value();
2214 assert_eq!(n.round(), n.trunc());
2215
2216 let n = $name::max_value()
2220 .saturating_sub(1.into())
2221 .trunc()
2222 .saturating_add((1, 3).into());
2223
2224 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2225
2226 let n = $name::max_value()
2228 .saturating_sub(1.into())
2229 .trunc()
2230 .saturating_add((1, 2).into());
2231
2232 assert_eq!(n.round(), $name::max_value().trunc());
2233
2234 if $name::SIGNED {
2235 let n = $name::min_value()
2237 .saturating_add(1.into())
2238 .trunc()
2239 .saturating_sub((1, 3).into());
2240
2241 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2242
2243 let n = $name::min_value()
2245 .saturating_add(1.into())
2246 .trunc()
2247 .saturating_sub((1, 2).into());
2248
2249 assert_eq!(n.round(), $name::min_value().trunc());
2250 }
2251 }
2252
2253 #[test]
2254 fn perthing_into_works() {
2255 let ten_percent_percent: $name = Percent::from_percent(10).into();
2256 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2257
2258 let ten_percent_permill: $name = Permill::from_percent(10).into();
2259 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2260
2261 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2262 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2263
2264 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2265 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2266 }
2267
2268 #[test]
2269 fn fmt_should_work() {
2270 let zero = $name::zero();
2271 assert_eq!(
2272 format!("{:?}", zero),
2273 format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2274 );
2275
2276 let one = $name::one();
2277 assert_eq!(
2278 format!("{:?}", one),
2279 format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2280 );
2281
2282 let frac = $name::saturating_from_rational(1, 2);
2283 assert_eq!(
2284 format!("{:?}", frac),
2285 format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2286 );
2287
2288 let frac = $name::saturating_from_rational(5, 2);
2289 assert_eq!(
2290 format!("{:?}", frac),
2291 format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2292 );
2293
2294 let frac = $name::saturating_from_rational(314, 100);
2295 assert_eq!(
2296 format!("{:?}", frac),
2297 format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2298 );
2299
2300 if $name::SIGNED {
2301 let neg = -$name::one();
2302 assert_eq!(
2303 format!("{:?}", neg),
2304 format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2305 );
2306
2307 let frac = $name::saturating_from_rational(-314, 100);
2308 assert_eq!(
2309 format!("{:?}", frac),
2310 format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2311 );
2312 }
2313 }
2314
2315 #[test]
2316 fn from_str_works() {
2317 use core::str::FromStr;
2318 let val = $name::from_str("1.0").unwrap();
2320 assert_eq!(val.into_inner(), $name::accuracy());
2321
2322 let val = $name::from_str("0.5").unwrap();
2323 assert_eq!(val.into_inner(), $name::accuracy() / 2);
2324
2325 let val = $name::from_str("2.5").unwrap();
2326 assert_eq!(val.into_inner(), $name::accuracy() * 5 / 2);
2327
2328 let val = $name::from_str("42").unwrap();
2330 assert_eq!(val.into_inner(), 42);
2331
2332 let val = $name::from_str("100.0").unwrap();
2333 assert_eq!(val.into_inner(), $name::accuracy() * 100);
2334
2335 let val = $name::from_str("0.25").unwrap();
2337 assert_eq!(val.into_inner(), $name::accuracy() / 4);
2338
2339 let val = $name::from_str(".5").unwrap();
2340 assert_eq!(val.into_inner(), $name::accuracy() / 2);
2341
2342 let val = $name::from_str("1.00045").unwrap();
2344 let expected = $name::accuracy() + ($name::accuracy() * 45 / 100000);
2345 assert_eq!(val.into_inner(), expected);
2346
2347 if $name::accuracy() >= 1_000_000_000_000_000_000 {
2349 let val = $name::from_str("0.123456789012345678").unwrap();
2351 let expected = ($name::accuracy() as u128 * 123456789012345678u128) /
2352 1000000000000000000u128;
2353 assert_eq!(val.into_inner() as u128, expected);
2354 } else {
2355 let val = $name::from_str("0.123456789").unwrap();
2357 let expected = ($name::accuracy() as u128 * 123456789u128) / 1000000000u128;
2358 assert_eq!(val.into_inner() as u128, expected);
2359 }
2360
2361 let val = $name::from_str("1000000000").unwrap();
2363 assert_eq!(val.into_inner(), 1000000000);
2364
2365 if $name::SIGNED {
2366 let val = $name::from_str("-1.0").unwrap();
2368 assert_eq!(val.into_inner(), 0 - $name::accuracy());
2369
2370 let val = $name::from_str("-0.5").unwrap();
2371 assert_eq!(val.into_inner(), 0 - $name::accuracy() / 2);
2372
2373 let val = $name::from_str("-2.5").unwrap();
2374 assert_eq!(val.into_inner(), 0 - $name::accuracy() * 5 / 2);
2375 } else {
2376 assert!($name::from_str("-1.0").is_err());
2378 assert!($name::from_str("-0.5").is_err());
2379 assert!($name::from_str("-123.456").is_err());
2380 }
2381
2382 assert!($name::from_str("").is_err());
2384 assert!($name::from_str("abc").is_err());
2385 assert!($name::from_str("1.2.3").is_err());
2386 assert!($name::from_str("1.abc").is_err());
2387 assert!($name::from_str("abc.1").is_err());
2388 }
2389 }
2390 };
2391}
2392
2393#[cfg(test)]
2394mod precision_tests {
2395 use super::*;
2396 use core::str::FromStr;
2397
2398 #[test]
2399 fn test_from_str_precision_verification() {
2400 let val = FixedU64::from_str("0.123456789").unwrap();
2402 let expected = 123456789u64; assert_eq!(val.into_inner(), expected);
2404
2405 let val = FixedU128::from_str("0.123456789012345678").unwrap();
2407 let expected = 123456789012345678u128; assert_eq!(val.into_inner(), expected);
2409
2410 let val = FixedU128::from_str("1.123456789012345678").unwrap();
2412 let expected = 1000000000000000000u128 + 123456789012345678u128;
2413 assert_eq!(val.into_inner(), expected);
2414
2415 let val = FixedI64::from_str("-0.123456789").unwrap();
2417 let expected = -123456789i64; assert_eq!(val.into_inner(), expected);
2419
2420 let val = FixedU64::from_str("1.000000001").unwrap();
2422 let expected = 1000000001u64; assert_eq!(val.into_inner(), expected);
2424
2425 let val = FixedU64::from_str("0.1234567891234").unwrap();
2427 let expected = 123456789u64; assert_eq!(val.into_inner(), expected);
2429 }
2430}
2431
2432implement_fixed!(
2433 FixedI64,
2434 test_fixed_i64,
2435 i64,
2436 true,
2437 1_000_000_000,
2438 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2439);
2440
2441implement_fixed!(
2442 FixedU64,
2443 test_fixed_u64,
2444 u64,
2445 false,
2446 1_000_000_000,
2447 "_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2448);
2449
2450implement_fixed!(
2451 FixedI128,
2452 test_fixed_i128,
2453 i128,
2454 true,
2455 1_000_000_000_000_000_000,
2456 "_Fixed Point 128 bits signed, range = \
2457 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2458);
2459
2460implement_fixed!(
2461 FixedU128,
2462 test_fixed_u128,
2463 u128,
2464 false,
2465 1_000_000_000_000_000_000,
2466 "_Fixed Point 128 bits unsigned, range = \
2467 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
2468);