1#![doc = docify::embed!("./src/lib.rs", fixed_u64)]
22#![doc = docify::embed!(
30 "./src/lib.rs",
31 fixed_u64_block_computation_example
32)]
33#![doc = docify::embed!(
42 "./src/lib.rs",
43 fixed_u64_operation_example
44)]
45use crate::{
48 helpers_128bit::{multiply_by_rational_with_rounding, sqrt},
49 traits::{
50 Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedSub, One,
51 SaturatedConversion, Saturating, UniqueSaturatedInto, Zero,
52 },
53 PerThing, Perbill, Rounding, SignedRounding,
54};
55use codec::{CompactAs, Decode, DecodeWithMemTracking, Encode};
56use core::{
57 fmt::Debug,
58 ops::{self, Add, Div, Mul, Sub},
59};
60
61#[cfg(feature = "serde")]
62use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
63
64#[cfg(all(not(feature = "std"), feature = "serde"))]
65use alloc::string::{String, ToString};
66
67pub trait FixedPointOperand:
69 Copy
70 + Clone
71 + Bounded
72 + Zero
73 + Saturating
74 + PartialOrd<Self>
75 + UniqueSaturatedInto<u128>
76 + TryFrom<u128>
77 + CheckedNeg
78{
79}
80
81impl<T> FixedPointOperand for T where
82 T: Copy
83 + Clone
84 + Bounded
85 + Zero
86 + Saturating
87 + PartialOrd<Self>
88 + UniqueSaturatedInto<u128>
89 + TryFrom<u128>
90 + CheckedNeg
91{
92}
93
94pub trait FixedPointNumber:
102 Sized
103 + Copy
104 + Default
105 + Debug
106 + Saturating
107 + Bounded
108 + Eq
109 + PartialEq
110 + Ord
111 + PartialOrd
112 + CheckedSub
113 + CheckedAdd
114 + CheckedMul
115 + CheckedDiv
116 + Add
117 + Sub
118 + Div
119 + Mul
120 + Zero
121 + One
122{
123 type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
125
126 const DIV: Self::Inner;
128
129 const SIGNED: bool;
131
132 fn accuracy() -> Self::Inner {
134 Self::DIV
135 }
136
137 fn from_inner(int: Self::Inner) -> Self;
139
140 fn into_inner(self) -> Self::Inner;
142
143 #[must_use]
145 fn checked_sqrt(self) -> Option<Self>;
146
147 #[must_use]
151 fn saturating_from_integer<N: FixedPointOperand>(int: N) -> Self {
152 let mut n: I129 = int.into();
153 n.value = n.value.saturating_mul(Self::DIV.saturated_into());
154 Self::from_inner(from_i129(n).unwrap_or_else(|| to_bound(int, 0)))
155 }
156
157 #[must_use]
161 fn checked_from_integer<N: Into<Self::Inner>>(int: N) -> Option<Self> {
162 let int: Self::Inner = int.into();
163 int.checked_mul(&Self::DIV).map(Self::from_inner)
164 }
165
166 #[must_use]
170 fn saturating_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Self {
171 if d == D::zero() {
172 panic!("attempt to divide by zero")
173 }
174 Self::checked_from_rational(n, d).unwrap_or_else(|| to_bound(n, d))
175 }
176
177 #[must_use]
181 fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
182 n: N,
183 d: D,
184 ) -> Option<Self> {
185 if d == D::zero() {
186 return None
187 }
188
189 let n: I129 = n.into();
190 let d: I129 = d.into();
191 let negative = n.negative != d.negative;
192
193 multiply_by_rational_with_rounding(
194 n.value,
195 Self::DIV.unique_saturated_into(),
196 d.value,
197 Rounding::from_signed(SignedRounding::Minor, negative),
198 )
199 .and_then(|value| from_i129(I129 { value, negative }))
200 .map(Self::from_inner)
201 }
202
203 #[must_use]
207 fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
208 let lhs: I129 = self.into_inner().into();
209 let rhs: I129 = n.into();
210 let negative = lhs.negative != rhs.negative;
211
212 multiply_by_rational_with_rounding(
213 lhs.value,
214 rhs.value,
215 Self::DIV.unique_saturated_into(),
216 Rounding::from_signed(SignedRounding::Minor, negative),
217 )
218 .and_then(|value| from_i129(I129 { value, negative }))
219 }
220
221 #[must_use]
225 fn saturating_mul_int<N: FixedPointOperand>(self, n: N) -> N {
226 self.checked_mul_int(n).unwrap_or_else(|| to_bound(self.into_inner(), n))
227 }
228
229 #[must_use]
233 fn checked_div_int<N: FixedPointOperand>(self, d: N) -> Option<N> {
234 let lhs: I129 = self.into_inner().into();
235 let rhs: I129 = d.into();
236 let negative = lhs.negative != rhs.negative;
237
238 lhs.value
239 .checked_div(rhs.value)
240 .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
241 .and_then(|value| from_i129(I129 { value, negative }))
242 }
243
244 #[must_use]
248 fn saturating_div_int<N: FixedPointOperand>(self, d: N) -> N {
249 if d == N::zero() {
250 panic!("attempt to divide by zero")
251 }
252 self.checked_div_int(d).unwrap_or_else(|| to_bound(self.into_inner(), d))
253 }
254
255 #[must_use]
260 fn saturating_mul_acc_int<N: FixedPointOperand>(self, n: N) -> N {
261 if self.is_negative() && n > N::zero() {
262 n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n))
263 } else {
264 self.saturating_mul_int(n).saturating_add(n)
265 }
266 }
267
268 #[must_use]
272 fn saturating_abs(self) -> Self {
273 let inner = self.into_inner();
274 if inner >= Self::Inner::zero() {
275 self
276 } else {
277 Self::from_inner(inner.checked_neg().unwrap_or_else(Self::Inner::max_value))
278 }
279 }
280
281 #[must_use]
285 fn reciprocal(self) -> Option<Self> {
286 Self::one().checked_div(&self)
287 }
288
289 fn is_one(&self) -> bool {
291 self.into_inner() == Self::Inner::one()
292 }
293
294 fn is_positive(self) -> bool {
296 self.into_inner() > Self::Inner::zero()
297 }
298
299 fn is_negative(self) -> bool {
301 self.into_inner() < Self::Inner::zero()
302 }
303
304 #[must_use]
306 fn trunc(self) -> Self {
307 self.into_inner()
308 .checked_div(&Self::DIV)
309 .expect("panics only if DIV is zero, DIV is not zero; qed")
310 .checked_mul(&Self::DIV)
311 .map(Self::from_inner)
312 .expect("can not overflow since fixed number is >= integer part")
313 }
314
315 #[must_use]
320 fn frac(self) -> Self {
321 let integer = self.trunc();
322 let fractional = self.saturating_sub(integer);
323 if integer == Self::zero() {
324 fractional
325 } else {
326 fractional.saturating_abs()
327 }
328 }
329
330 #[must_use]
334 fn ceil(self) -> Self {
335 if self.is_negative() {
336 self.trunc()
337 } else if self.frac() == Self::zero() {
338 self
339 } else {
340 self.saturating_add(Self::one()).trunc()
341 }
342 }
343
344 #[must_use]
348 fn floor(self) -> Self {
349 if self.is_negative() {
350 self.saturating_sub(Self::one()).trunc()
351 } else {
352 self.trunc()
353 }
354 }
355
356 #[must_use]
360 fn round(self) -> Self {
361 let n = self.frac().saturating_mul(Self::saturating_from_integer(10));
362 if n < Self::saturating_from_integer(5) {
363 self.trunc()
364 } else if self.is_positive() {
365 self.saturating_add(Self::one()).trunc()
366 } else {
367 self.saturating_sub(Self::one()).trunc()
368 }
369 }
370}
371
372struct I129 {
374 value: u128,
375 negative: bool,
376}
377
378impl<N: FixedPointOperand> From<N> for I129 {
379 fn from(n: N) -> I129 {
380 if n < N::zero() {
381 let value: u128 = n
382 .checked_neg()
383 .map(|n| n.unique_saturated_into())
384 .unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
385 I129 { value, negative: true }
386 } else {
387 I129 { value: n.unique_saturated_into(), negative: false }
388 }
389 }
390}
391
392fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
394 let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
395 if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
396 Some(N::min_value())
397 } else {
398 let unsigned_inner: N = n.value.try_into().ok()?;
399 let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner };
400 Some(inner)
401 }
402}
403
404fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
406 if (n < N::zero()) != (m < D::zero()) {
407 R::min_value()
408 } else {
409 R::max_value()
410 }
411}
412
413macro_rules! implement_fixed {
414 (
415 $name:ident,
416 $test_mod:ident,
417 $inner_type:ty,
418 $signed:tt,
419 $div:tt,
420 $title:expr $(,)?
421 ) => {
422 #[doc = $title]
424 #[derive(
425 Encode,
426 Decode,
427 DecodeWithMemTracking,
428 CompactAs,
429 Default,
430 Copy,
431 Clone,
432 codec::MaxEncodedLen,
433 PartialEq,
434 Eq,
435 PartialOrd,
436 Ord,
437 scale_info::TypeInfo,
438 )]
439 pub struct $name($inner_type);
440
441 impl From<$inner_type> for $name {
442 fn from(int: $inner_type) -> Self {
443 $name::saturating_from_integer(int)
444 }
445 }
446
447 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
448 fn from(r: (N, D)) -> Self {
449 $name::saturating_from_rational(r.0, r.1)
450 }
451 }
452
453 impl FixedPointNumber for $name {
454 type Inner = $inner_type;
455
456 const DIV: Self::Inner = $div;
457 const SIGNED: bool = $signed;
458
459 fn from_inner(inner: Self::Inner) -> Self {
460 Self(inner)
461 }
462
463 fn into_inner(self) -> Self::Inner {
464 self.0
465 }
466
467 fn checked_sqrt(self) -> Option<Self> {
468 self.checked_sqrt()
469 }
470 }
471
472 impl $name {
473 pub const fn from_inner(inner: $inner_type) -> Self {
477 Self(inner)
478 }
479
480 pub const fn into_inner(self) -> $inner_type {
484 self.0
485 }
486
487 pub const fn from_u32(n: u32) -> Self {
492 Self::from_inner((n as $inner_type) * $div)
493 }
494
495 #[cfg(any(feature = "std", test))]
497 pub fn from_float(x: f64) -> Self {
498 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
499 }
500
501 pub const fn from_perbill(n: Perbill) -> Self {
503 Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
504 }
505
506 pub const fn into_perbill(self) -> Perbill {
508 if self.0 <= 0 {
509 Perbill::zero()
510 } else if self.0 >= $div {
511 Perbill::one()
512 } else {
513 match multiply_by_rational_with_rounding(
514 self.0 as u128,
515 1_000_000_000,
516 Self::DIV as u128,
517 Rounding::NearestPrefDown,
518 ) {
519 Some(value) => {
520 if value > (u32::max_value() as u128) {
521 panic!(
522 "prior logic ensures 0<self.0<DIV; \
523 multiply ensures 0<self.0<1000000000; \
524 qed"
525 );
526 }
527 Perbill::from_parts(value as u32)
528 },
529 None => Perbill::zero(),
530 }
531 }
532 }
533
534 #[cfg(any(feature = "std", test))]
536 pub fn to_float(self) -> f64 {
537 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
538 }
539
540 pub fn try_into_perthing<P: PerThing>(self) -> Result<P, P> {
544 if self < Self::zero() {
545 Err(P::zero())
546 } else if self > Self::one() {
547 Err(P::one())
548 } else {
549 Ok(P::from_rational(self.0 as u128, $div))
550 }
551 }
552
553 pub fn into_clamped_perthing<P: PerThing>(self) -> P {
556 if self < Self::zero() {
557 P::zero()
558 } else if self > Self::one() {
559 P::one()
560 } else {
561 P::from_rational(self.0 as u128, $div)
562 }
563 }
564
565 pub const fn neg(self) -> Self {
570 Self(0 - self.0)
571 }
572
573 pub const fn sqrt(self) -> Self {
578 match self.checked_sqrt() {
579 Some(v) => v,
580 None => panic!("sqrt overflow or negative input"),
581 }
582 }
583
584 #[deprecated(
585 note = "`try_sqrt` will be removed after October 2025. Use `checked_sqrt` instead."
586 )]
587 pub const fn try_sqrt(self) -> Option<Self> {
588 self.checked_sqrt()
589 }
590
591 pub const fn checked_sqrt(self) -> Option<Self> {
593 if self.0 == 0 {
594 return Some(Self(0))
595 }
596 if self.0 < 1 {
597 return None
598 }
599 let v = self.0 as u128;
600
601 let maybe_vd = u128::checked_mul(v, $div);
611 let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
612 Some(Self(r as $inner_type))
613 }
614
615 pub const fn add(self, rhs: Self) -> Self {
620 Self(self.0 + rhs.0)
621 }
622
623 pub const fn sub(self, rhs: Self) -> Self {
628 Self(self.0 - rhs.0)
629 }
630
631 pub const fn mul(self, rhs: Self) -> Self {
639 match $name::const_checked_mul(self, rhs) {
640 Some(v) => v,
641 None => panic!("attempt to multiply with overflow"),
642 }
643 }
644
645 pub const fn div(self, rhs: Self) -> Self {
653 match $name::const_checked_div(self, rhs) {
654 Some(v) => v,
655 None => panic!("attempt to divide with overflow or NaN"),
656 }
657 }
658
659 const fn into_i129(self) -> I129 {
664 #[allow(unused_comparisons)]
665 if self.0 < 0 {
666 let value = match self.0.checked_neg() {
667 Some(n) => n as u128,
668 None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
669 };
670 I129 { value, negative: true }
671 } else {
672 I129 { value: self.0 as u128, negative: false }
673 }
674 }
675
676 const fn from_i129(n: I129) -> Option<Self> {
681 let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
682 #[allow(unused_comparisons)]
683 let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
684 <$inner_type>::min_value()
685 } else {
686 let unsigned_inner = n.value as $inner_type;
687 if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
688 return None
689 };
690 if n.negative {
691 match unsigned_inner.checked_neg() {
692 Some(v) => v,
693 None => return None,
694 }
695 } else {
696 unsigned_inner
697 }
698 };
699 Some(Self(inner))
700 }
701
702 pub const fn from_rational(a: u128, b: u128) -> Self {
710 Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
711 }
712
713 pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
718 if b == 0 {
719 panic!("attempt to divide by zero in from_rational")
720 }
721 match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
722 Some(value) => match Self::from_i129(I129 { value, negative: false }) {
723 Some(x) => x,
724 None => panic!("overflow in from_rational"),
725 },
726 None => panic!("overflow in from_rational"),
727 }
728 }
729
730 pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
735 self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
736 }
737
738 pub const fn const_checked_mul_with_rounding(
744 self,
745 other: Self,
746 rounding: SignedRounding,
747 ) -> Option<Self> {
748 let lhs = self.into_i129();
749 let rhs = other.into_i129();
750 let negative = lhs.negative != rhs.negative;
751
752 match multiply_by_rational_with_rounding(
753 lhs.value,
754 rhs.value,
755 Self::DIV as u128,
756 Rounding::from_signed(rounding, negative),
757 ) {
758 Some(value) => Self::from_i129(I129 { value, negative }),
759 None => None,
760 }
761 }
762
763 pub const fn const_checked_div(self, other: Self) -> Option<Self> {
768 self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
769 }
770
771 pub const fn checked_rounding_div(
777 self,
778 other: Self,
779 rounding: SignedRounding,
780 ) -> Option<Self> {
781 if other.0 == 0 {
782 return None
783 }
784
785 let lhs = self.into_i129();
786 let rhs = other.into_i129();
787 let negative = lhs.negative != rhs.negative;
788
789 match multiply_by_rational_with_rounding(
790 lhs.value,
791 Self::DIV as u128,
792 rhs.value,
793 Rounding::from_signed(rounding, negative),
794 ) {
795 Some(value) => Self::from_i129(I129 { value, negative }),
796 None => None,
797 }
798 }
799 }
800
801 impl Saturating for $name {
802 fn saturating_add(self, rhs: Self) -> Self {
803 Self(self.0.saturating_add(rhs.0))
804 }
805
806 fn saturating_sub(self, rhs: Self) -> Self {
807 Self(self.0.saturating_sub(rhs.0))
808 }
809
810 fn saturating_mul(self, rhs: Self) -> Self {
811 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
812 }
813
814 fn saturating_pow(self, exp: usize) -> Self {
815 if exp == 0 {
816 return Self::saturating_from_integer(1)
817 }
818
819 let exp = exp as u32;
820 let msb_pos = 32 - exp.leading_zeros();
821
822 let mut result = Self::saturating_from_integer(1);
823 let mut pow_val = self;
824 for i in 0..msb_pos {
825 if ((1 << i) & exp) > 0 {
826 result = result.saturating_mul(pow_val);
827 }
828 pow_val = pow_val.saturating_mul(pow_val);
829 }
830 result
831 }
832 }
833
834 impl ops::Neg for $name {
835 type Output = Self;
836
837 fn neg(self) -> Self::Output {
838 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
839 }
840 }
841
842 impl ops::Add for $name {
843 type Output = Self;
844
845 fn add(self, rhs: Self) -> Self::Output {
846 Self(self.0 + rhs.0)
847 }
848 }
849
850 impl ops::Sub for $name {
851 type Output = Self;
852
853 fn sub(self, rhs: Self) -> Self::Output {
854 Self(self.0 - rhs.0)
855 }
856 }
857
858 impl ops::Mul for $name {
859 type Output = Self;
860
861 fn mul(self, rhs: Self) -> Self::Output {
862 self.checked_mul(&rhs)
863 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
864 }
865 }
866
867 impl ops::Div for $name {
868 type Output = Self;
869
870 fn div(self, rhs: Self) -> Self::Output {
871 if rhs.0 == 0 {
872 panic!("attempt to divide by zero")
873 }
874 self.checked_div(&rhs)
875 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
876 }
877 }
878
879 impl CheckedSub for $name {
880 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
881 self.0.checked_sub(rhs.0).map(Self)
882 }
883 }
884
885 impl CheckedAdd for $name {
886 fn checked_add(&self, rhs: &Self) -> Option<Self> {
887 self.0.checked_add(rhs.0).map(Self)
888 }
889 }
890
891 impl CheckedDiv for $name {
892 fn checked_div(&self, other: &Self) -> Option<Self> {
893 if other.0 == 0 {
894 return None
895 }
896
897 let lhs: I129 = self.0.into();
898 let rhs: I129 = other.0.into();
899 let negative = lhs.negative != rhs.negative;
900
901 multiply_by_rational_with_rounding(
906 lhs.value,
907 Self::DIV as u128,
908 rhs.value,
909 Rounding::from_signed(SignedRounding::Minor, negative),
910 )
911 .and_then(|value| from_i129(I129 { value, negative }))
912 .map(Self)
913 }
914 }
915
916 impl CheckedMul for $name {
917 fn checked_mul(&self, other: &Self) -> Option<Self> {
918 let lhs: I129 = self.0.into();
919 let rhs: I129 = other.0.into();
920 let negative = lhs.negative != rhs.negative;
921
922 multiply_by_rational_with_rounding(
923 lhs.value,
924 rhs.value,
925 Self::DIV as u128,
926 Rounding::from_signed(SignedRounding::Minor, negative),
927 )
928 .and_then(|value| from_i129(I129 { value, negative }))
929 .map(Self)
930 }
931 }
932
933 impl Bounded for $name {
934 fn min_value() -> Self {
935 Self(<Self as FixedPointNumber>::Inner::min_value())
936 }
937
938 fn max_value() -> Self {
939 Self(<Self as FixedPointNumber>::Inner::max_value())
940 }
941 }
942
943 impl Zero for $name {
944 fn zero() -> Self {
945 Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
946 }
947
948 fn is_zero(&self) -> bool {
949 self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
950 }
951 }
952
953 impl One for $name {
954 fn one() -> Self {
955 Self::from_inner(Self::DIV)
956 }
957 }
958
959 impl ::core::fmt::Debug for $name {
960 #[cfg(feature = "std")]
961 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
962 let integral = {
963 let int = self.0 / Self::accuracy();
964 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
965 format!("{}{}", signum_for_zero, int)
966 };
967 let precision = (Self::accuracy() as f64).log10() as usize;
968 let fractional = format!(
969 "{:0>weight$}",
970 ((self.0 % Self::accuracy()) as i128).abs(),
971 weight = precision
972 );
973 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
974 }
975
976 #[cfg(not(feature = "std"))]
977 fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
978 Ok(())
979 }
980 }
981
982 impl<P: PerThing> From<P> for $name
983 where
984 P::Inner: FixedPointOperand,
985 {
986 fn from(p: P) -> Self {
987 let accuracy = P::ACCURACY;
988 let value = p.deconstruct();
989 $name::saturating_from_rational(value, accuracy)
990 }
991 }
992
993 impl ::core::fmt::Display for $name {
994 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
995 write!(f, "{}", self.0)
996 }
997 }
998
999 impl ::core::str::FromStr for $name {
1000 type Err = &'static str;
1001
1002 fn from_str(s: &str) -> Result<Self, Self::Err> {
1003 let inner: <Self as FixedPointNumber>::Inner =
1004 s.parse().map_err(|_| "invalid string input for fixed point number")?;
1005 Ok(Self::from_inner(inner))
1006 }
1007 }
1008
1009 #[cfg(feature = "serde")]
1012 impl Serialize for $name {
1013 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1014 where
1015 S: Serializer,
1016 {
1017 serializer.serialize_str(&self.to_string())
1018 }
1019 }
1020
1021 #[cfg(feature = "serde")]
1024 impl<'de> Deserialize<'de> for $name {
1025 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1026 where
1027 D: Deserializer<'de>,
1028 {
1029 use ::core::str::FromStr;
1030 let s = String::deserialize(deserializer)?;
1031 $name::from_str(&s).map_err(de::Error::custom)
1032 }
1033 }
1034
1035 #[cfg(test)]
1036 mod $test_mod {
1037 use super::*;
1038 use crate::{Perbill, Percent, Permill, Perquintill};
1039
1040 fn max() -> $name {
1041 $name::max_value()
1042 }
1043
1044 fn min() -> $name {
1045 $name::min_value()
1046 }
1047
1048 fn precision() -> usize {
1049 ($name::accuracy() as f64).log10() as usize
1050 }
1051
1052 #[test]
1053 fn macro_preconditions() {
1054 assert!($name::DIV > 0);
1055 }
1056
1057 #[test]
1058 fn has_max_encoded_len() {
1059 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1060 _data: T,
1061 }
1062
1063 let _ = AsMaxEncodedLen { _data: $name::min_value() };
1064 }
1065
1066 #[test]
1067 fn from_i129_works() {
1068 let a = I129 { value: 1, negative: true };
1069
1070 assert_eq!(from_i129::<u128>(a), None);
1072
1073 let a = I129 { value: u128::MAX - 1, negative: false };
1074
1075 assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1077
1078 let a = I129 { value: u128::MAX, negative: false };
1079
1080 assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1082
1083 let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1084
1085 assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1087
1088 let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1089
1090 assert_eq!(from_i129::<i128>(a), None);
1092
1093 let a = I129 { value: i128::MAX as u128, negative: false };
1094
1095 assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1097 }
1098
1099 #[test]
1100 fn to_bound_works() {
1101 let a = 1i32;
1102 let b = 1i32;
1103
1104 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1106
1107 let a = -1i32;
1108 let b = -1i32;
1109
1110 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1112
1113 let a = 1i32;
1114 let b = -1i32;
1115
1116 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1118
1119 let a = -1i32;
1120 let b = 1i32;
1121
1122 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1124
1125 let a = 1i32;
1126 let b = -1i32;
1127
1128 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1130 }
1131
1132 #[test]
1133 fn op_neg_works() {
1134 let a = $name::zero();
1135 let b = -a;
1136
1137 assert_eq!(a, b);
1139
1140 if $name::SIGNED {
1141 let a = $name::saturating_from_integer(5);
1142 let b = -a;
1143
1144 assert_eq!($name::saturating_from_integer(-5), b);
1146
1147 let a = $name::saturating_from_integer(-5);
1148 let b = -a;
1149
1150 assert_eq!($name::saturating_from_integer(5), b);
1152
1153 let a = $name::max_value();
1154 let b = -a;
1155
1156 assert_eq!($name::min_value() + $name::from_inner(1), b);
1158
1159 let a = $name::min_value() + $name::from_inner(1);
1160 let b = -a;
1161
1162 assert_eq!($name::max_value(), b);
1164 }
1165 }
1166
1167 #[test]
1168 fn op_checked_add_overflow_works() {
1169 let a = $name::max_value();
1170 let b = 1.into();
1171 assert!(a.checked_add(&b).is_none());
1172 }
1173
1174 #[test]
1175 fn op_add_works() {
1176 let a = $name::saturating_from_rational(5, 2);
1177 let b = $name::saturating_from_rational(1, 2);
1178
1179 assert_eq!($name::saturating_from_integer(3), a + b);
1181
1182 if $name::SIGNED {
1183 let b = $name::saturating_from_rational(1, -2);
1185 assert_eq!($name::saturating_from_integer(2), a + b);
1186 }
1187 }
1188
1189 #[test]
1190 fn op_checked_sub_underflow_works() {
1191 let a = $name::min_value();
1192 let b = 1.into();
1193 assert!(a.checked_sub(&b).is_none());
1194 }
1195
1196 #[test]
1197 fn op_sub_works() {
1198 let a = $name::saturating_from_rational(5, 2);
1199 let b = $name::saturating_from_rational(1, 2);
1200
1201 assert_eq!($name::saturating_from_integer(2), a - b);
1202 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1203 }
1204
1205 #[test]
1206 fn op_checked_mul_overflow_works() {
1207 let a = $name::max_value();
1208 let b = 2.into();
1209 assert!(a.checked_mul(&b).is_none());
1210 }
1211
1212 #[test]
1213 fn op_mul_works() {
1214 let a = $name::saturating_from_integer(42);
1215 let b = $name::saturating_from_integer(2);
1216 assert_eq!($name::saturating_from_integer(84), a * b);
1217
1218 let a = $name::saturating_from_integer(42);
1219 let b = $name::saturating_from_integer(-2);
1220 assert_eq!($name::saturating_from_integer(-84), a * b);
1221 }
1222
1223 #[test]
1224 #[should_panic(expected = "attempt to divide by zero")]
1225 fn op_div_panics_on_zero_divisor() {
1226 let a = $name::saturating_from_integer(1);
1227 let b = 0.into();
1228 let _c = a / b;
1229 }
1230
1231 #[test]
1232 fn op_checked_div_overflow_works() {
1233 if $name::SIGNED {
1234 let a = $name::min_value();
1235 let b = $name::zero().saturating_sub($name::one());
1236 assert!(a.checked_div(&b).is_none());
1237 }
1238 }
1239
1240 #[test]
1241 fn op_sqrt_works() {
1242 for i in 1..1_000i64 {
1243 let x = $name::saturating_from_rational(i, 1_000i64);
1244 assert_eq!((x * x).checked_sqrt(), Some(x));
1245 let x = $name::saturating_from_rational(i, 1i64);
1246 assert_eq!((x * x).checked_sqrt(), Some(x));
1247 }
1248 }
1249
1250 #[test]
1251 fn op_div_works() {
1252 let a = $name::saturating_from_integer(42);
1253 let b = $name::saturating_from_integer(2);
1254 assert_eq!($name::saturating_from_integer(21), a / b);
1255
1256 if $name::SIGNED {
1257 let a = $name::saturating_from_integer(42);
1258 let b = $name::saturating_from_integer(-2);
1259 assert_eq!($name::saturating_from_integer(-21), a / b);
1260 }
1261 }
1262
1263 #[test]
1264 fn saturating_from_integer_works() {
1265 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1266 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1267 let accuracy = $name::accuracy();
1268
1269 let a = $name::saturating_from_integer(42);
1271 assert_eq!(a.into_inner(), 42 * accuracy);
1272
1273 let a = $name::saturating_from_integer(-42);
1274 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1275
1276 let a = $name::saturating_from_integer(inner_max / accuracy);
1278 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1279
1280 let a = $name::saturating_from_integer(inner_min / accuracy);
1281 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1282
1283 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1285 assert_eq!(a.into_inner(), inner_max);
1286
1287 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1288 assert_eq!(a.into_inner(), inner_min);
1289 }
1290
1291 #[test]
1292 fn checked_from_integer_works() {
1293 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1294 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1295 let accuracy = $name::accuracy();
1296
1297 let a = $name::checked_from_integer::<$inner_type>(42)
1299 .expect("42 * accuracy <= inner_max; qed");
1300 assert_eq!(a.into_inner(), 42 * accuracy);
1301
1302 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1304 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1305 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1306
1307 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1309 assert_eq!(a, None);
1310
1311 if $name::SIGNED {
1312 let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1314 .expect("-42 * accuracy >= inner_min; qed");
1315 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1316
1317 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1319 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1320 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1321
1322 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1324 assert_eq!(a, None);
1325 }
1326 }
1327
1328 #[test]
1329 fn from_inner_works() {
1330 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1331 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1332
1333 assert_eq!(max(), $name::from_inner(inner_max));
1334 assert_eq!(min(), $name::from_inner(inner_min));
1335 }
1336
1337 #[test]
1338 #[should_panic(expected = "attempt to divide by zero")]
1339 fn saturating_from_rational_panics_on_zero_divisor() {
1340 let _ = $name::saturating_from_rational(1, 0);
1341 }
1342
1343 #[test]
1344 fn saturating_from_rational_works() {
1345 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1346 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1347 let accuracy = $name::accuracy();
1348
1349 let a = $name::saturating_from_rational(5, 2);
1350
1351 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1353
1354 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1356 assert_eq!(a.into_inner(), inner_max - 1);
1357
1358 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1360 assert_eq!(a.into_inner(), inner_min + 1);
1361
1362 let a = $name::saturating_from_rational(inner_max, accuracy);
1364 assert_eq!(a.into_inner(), inner_max);
1365
1366 let a = $name::saturating_from_rational(inner_min, accuracy);
1368 assert_eq!(a.into_inner(), inner_min);
1369
1370 let a = $name::saturating_from_rational(0, 1);
1372 assert_eq!(a.into_inner(), 0);
1373
1374 if $name::SIGNED {
1375 let a = $name::saturating_from_rational(-5, 2);
1377 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1378
1379 let a = $name::saturating_from_rational(5, -2);
1381 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1382
1383 let a = $name::saturating_from_rational(-5, -2);
1385 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1386
1387 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1389 assert_eq!(a.into_inner(), inner_max);
1390
1391 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1393 assert_eq!(a.into_inner(), inner_min);
1394
1395 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1396 assert_eq!(a.into_inner(), 0 - inner_max);
1397
1398 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1399 assert_eq!(a.into_inner(), inner_max);
1400
1401 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1402 assert_eq!(a.into_inner(), inner_max);
1403
1404 let a = $name::saturating_from_rational(inner_min, 0 - 1);
1405 assert_eq!(a.into_inner(), inner_max);
1406
1407 let a = $name::saturating_from_rational(inner_max, 0 - 1);
1408 assert_eq!(a.into_inner(), inner_min);
1409
1410 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1411 assert_eq!(a.into_inner(), 0 - accuracy);
1412
1413 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1414 assert_eq!(a.into_inner(), 0 - accuracy);
1415
1416 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1417 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1418
1419 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1420 assert_eq!(a.into_inner(), inner_max);
1421
1422 let a = $name::saturating_from_rational(1, 0 - accuracy);
1423 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1424
1425 let a = $name::saturating_from_rational(inner_min, inner_min);
1426 assert_eq!(a.into_inner(), accuracy);
1427
1428 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1430 assert_eq!(a.into_inner(), 0);
1431 }
1432
1433 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1434 assert_eq!(a.into_inner(), inner_max - 1);
1435
1436 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1437 assert_eq!(a.into_inner(), inner_min + 1);
1438
1439 let a = $name::saturating_from_rational(inner_max, 1);
1440 assert_eq!(a.into_inner(), inner_max);
1441
1442 let a = $name::saturating_from_rational(inner_min, 1);
1443 assert_eq!(a.into_inner(), inner_min);
1444
1445 let a = $name::saturating_from_rational(inner_max, inner_max);
1446 assert_eq!(a.into_inner(), accuracy);
1447
1448 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1449 assert_eq!(a.into_inner(), inner_max / 3);
1450
1451 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1452 assert_eq!(a.into_inner(), inner_min / 2);
1453
1454 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1455 assert_eq!(a.into_inner(), inner_min);
1456
1457 let a = $name::saturating_from_rational(1, accuracy);
1458 assert_eq!(a.into_inner(), 1);
1459
1460 let a = $name::saturating_from_rational(1, accuracy + 1);
1462 assert_eq!(a.into_inner(), 0);
1463 }
1464
1465 #[test]
1466 fn checked_from_rational_works() {
1467 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1468 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1469 let accuracy = $name::accuracy();
1470
1471 let a = $name::checked_from_rational(1, 0);
1473 assert_eq!(a, None);
1474
1475 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1477 assert_eq!(a.into_inner(), inner_max - 1);
1478
1479 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1481 assert_eq!(a.into_inner(), inner_min + 1);
1482
1483 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1485 assert_eq!(a.into_inner(), inner_max);
1486
1487 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1489 assert_eq!(a.into_inner(), inner_min);
1490
1491 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1493 assert_eq!(a, None);
1494
1495 if $name::SIGNED {
1496 let a = $name::checked_from_rational(
1498 inner_max as u128 + 2,
1499 0.saturating_sub(accuracy),
1500 );
1501 assert_eq!(a, None);
1502
1503 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1504 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1505
1506 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1507 assert_eq!(a, None);
1508
1509 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1510 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1511
1512 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1513 assert_eq!(a.into_inner(), 0);
1514
1515 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1516 assert_eq!(a, None);
1517 }
1518
1519 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1520 assert_eq!(a.into_inner(), inner_max / 3);
1521
1522 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1523 assert_eq!(a.into_inner(), inner_min / 2);
1524
1525 let a = $name::checked_from_rational(1, accuracy).unwrap();
1526 assert_eq!(a.into_inner(), 1);
1527
1528 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1529 assert_eq!(a.into_inner(), 0);
1530 }
1531
1532 #[test]
1533 fn from_rational_works() {
1534 let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1535 let inner_min: u128 = 0;
1536 let accuracy: u128 = $name::accuracy() as u128;
1537
1538 let a = $name::from_rational(inner_max - 1, accuracy);
1540 assert_eq!(a.into_inner() as u128, inner_max - 1);
1541
1542 let a = $name::from_rational(inner_min + 1, accuracy);
1544 assert_eq!(a.into_inner() as u128, inner_min + 1);
1545
1546 let a = $name::from_rational(inner_max, accuracy);
1548 assert_eq!(a.into_inner() as u128, inner_max);
1549
1550 let a = $name::from_rational(inner_min, accuracy);
1552 assert_eq!(a.into_inner() as u128, inner_min);
1553
1554 let a = $name::from_rational(inner_max, 3 * accuracy);
1555 assert_eq!(a.into_inner() as u128, inner_max / 3);
1556
1557 let a = $name::from_rational(1, accuracy);
1558 assert_eq!(a.into_inner() as u128, 1);
1559
1560 let a = $name::from_rational(1, accuracy + 1);
1561 assert_eq!(a.into_inner() as u128, 1);
1562
1563 let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1564 assert_eq!(a.into_inner() as u128, 0);
1565 }
1566
1567 #[test]
1568 fn checked_mul_int_works() {
1569 let a = $name::saturating_from_integer(2);
1570 assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1572 assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1574 assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1576
1577 if $name::SIGNED {
1578 assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1580 assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1582 assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1584
1585 let b = $name::saturating_from_rational(1, -2);
1586 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1587 assert_eq!(b.checked_mul_int(u128::MAX), None);
1588 assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1589 assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1590 }
1591
1592 let a = $name::saturating_from_rational(1, 2);
1593 assert_eq!(a.checked_mul_int(42i128), Some(21));
1594 assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1595 assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1596
1597 let c = $name::saturating_from_integer(255);
1598 assert_eq!(c.checked_mul_int(2i8), None);
1599 assert_eq!(c.checked_mul_int(2i128), Some(510));
1600 assert_eq!(c.checked_mul_int(i128::MAX), None);
1601 assert_eq!(c.checked_mul_int(i128::MIN), None);
1602 }
1603
1604 #[test]
1605 fn saturating_mul_int_works() {
1606 let a = $name::saturating_from_integer(2);
1607 assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1609 assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1611 assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1613
1614 assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1616 assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1618 assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1620
1621 if $name::SIGNED {
1622 let b = $name::saturating_from_rational(1, -2);
1623 assert_eq!(b.saturating_mul_int(42i32), -21);
1624 assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1625 assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1626 assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1627 }
1628
1629 let a = $name::saturating_from_rational(1, 2);
1630 assert_eq!(a.saturating_mul_int(42i32), 21);
1631 assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1632 assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1633
1634 let c = $name::saturating_from_integer(255);
1635 assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1636 assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1637 assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1638 assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1639 }
1640
1641 #[test]
1642 fn checked_mul_works() {
1643 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1644 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1645
1646 let a = $name::saturating_from_integer(2);
1647
1648 let b = $name::from_inner(inner_max - 1);
1650 assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1651
1652 let c = $name::from_inner(inner_max);
1654 assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1655
1656 let e = $name::from_inner(1);
1658 assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1659
1660 if $name::SIGNED {
1661 let b = $name::from_inner(inner_min + 1) / 2.into();
1663 let c = $name::from_inner(inner_min + 2);
1664 assert_eq!(a.checked_mul(&b), Some(c));
1665
1666 let b = $name::from_inner(inner_min) / 2.into();
1668 let c = $name::from_inner(inner_min);
1669 assert_eq!(a.checked_mul(&b), Some(c));
1670
1671 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1673 assert_eq!(a.checked_mul(&b), None);
1674
1675 let c = $name::saturating_from_integer(255);
1676 let b = $name::saturating_from_rational(1, -2);
1677
1678 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1679 assert_eq!(
1680 b.checked_mul(&$name::max_value()),
1681 $name::max_value().checked_div(&0.saturating_sub(2).into())
1682 );
1683 assert_eq!(
1684 b.checked_mul(&$name::min_value()),
1685 $name::min_value().checked_div(&0.saturating_sub(2).into())
1686 );
1687 assert_eq!(c.checked_mul(&$name::min_value()), None);
1688 }
1689
1690 let a = $name::saturating_from_rational(1, 2);
1691 let c = $name::saturating_from_integer(255);
1692
1693 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1694 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1695 assert_eq!(c.checked_mul(&$name::max_value()), None);
1696 assert_eq!(
1697 a.checked_mul(&$name::max_value()),
1698 $name::max_value().checked_div(&2.into())
1699 );
1700 assert_eq!(
1701 a.checked_mul(&$name::min_value()),
1702 $name::min_value().checked_div(&2.into())
1703 );
1704 }
1705
1706 #[test]
1707 fn const_checked_mul_works() {
1708 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1709 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1710
1711 let a = $name::saturating_from_integer(2u32);
1712
1713 let b = $name::from_inner(inner_max - 1);
1715 assert_eq!(a.const_checked_mul((b / 2.into())), Some(b));
1716
1717 let c = $name::from_inner(inner_max);
1719 assert_eq!(a.const_checked_mul((c / 2.into())), Some(b));
1720
1721 let e = $name::from_inner(1);
1723 assert_eq!(a.const_checked_mul((c / 2.into() + e)), None);
1724
1725 if $name::SIGNED {
1726 let b = $name::from_inner(inner_min + 1) / 2.into();
1728 let c = $name::from_inner(inner_min + 2);
1729 assert_eq!(a.const_checked_mul(b), Some(c));
1730
1731 let b = $name::from_inner(inner_min) / 2.into();
1733 let c = $name::from_inner(inner_min);
1734 assert_eq!(a.const_checked_mul(b), Some(c));
1735
1736 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1738 assert_eq!(a.const_checked_mul(b), None);
1739
1740 let b = $name::saturating_from_rational(1i32, -2i32);
1741 let c = $name::saturating_from_integer(-21i32);
1742 let d = $name::saturating_from_integer(42);
1743
1744 assert_eq!(b.const_checked_mul(d), Some(c));
1745
1746 let minus_two = $name::saturating_from_integer(-2i32);
1747 assert_eq!(
1748 b.const_checked_mul($name::max_value()),
1749 $name::max_value().const_checked_div(minus_two)
1750 );
1751 assert_eq!(
1752 b.const_checked_mul($name::min_value()),
1753 $name::min_value().const_checked_div(minus_two)
1754 );
1755
1756 let c = $name::saturating_from_integer(255u32);
1757 assert_eq!(c.const_checked_mul($name::min_value()), None);
1758 }
1759
1760 let a = $name::saturating_from_rational(1i32, 2i32);
1761 let c = $name::saturating_from_integer(255i32);
1762
1763 assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1764 assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1765 assert_eq!(c.const_checked_mul($name::max_value()), None);
1766 assert_eq!(
1767 a.const_checked_mul($name::max_value()),
1768 $name::max_value().checked_div(&2.into())
1769 );
1770 assert_eq!(
1771 a.const_checked_mul($name::min_value()),
1772 $name::min_value().const_checked_div($name::saturating_from_integer(2))
1773 );
1774 }
1775
1776 #[test]
1777 fn checked_div_int_works() {
1778 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1779 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1780 let accuracy = $name::accuracy();
1781
1782 let a = $name::from_inner(inner_max);
1783 let b = $name::from_inner(inner_min);
1784 let c = $name::zero();
1785 let d = $name::one();
1786 let e = $name::saturating_from_integer(6);
1787 let f = $name::saturating_from_integer(5);
1788
1789 assert_eq!(e.checked_div_int(2.into()), Some(3));
1790 assert_eq!(f.checked_div_int(2.into()), Some(2));
1791
1792 assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1793 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1794 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1795 assert_eq!(a.checked_div_int(1i8), None);
1796
1797 if b < c {
1798 assert_eq!(
1800 a.checked_div_int(0.saturating_sub(2)),
1801 Some(0.saturating_sub(inner_max / (2 * accuracy)))
1802 );
1803 assert_eq!(
1804 a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1805 Some(0.saturating_sub(1))
1806 );
1807 assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1808 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1809 assert_eq!(b.checked_div_int(1i8), None);
1810 assert_eq!(
1811 b.checked_div_int(0.saturating_sub(2)),
1812 Some(0.saturating_sub(inner_min / (2 * accuracy)))
1813 );
1814 assert_eq!(
1815 b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1816 Some(0.saturating_sub(1))
1817 );
1818 assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1819 assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1820 }
1821
1822 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1823
1824 assert_eq!(c.checked_div_int(1), Some(0));
1825 assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1826 assert_eq!(c.checked_div_int(1i8), Some(0));
1827
1828 assert_eq!(d.checked_div_int(1), Some(1));
1829 assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1830 assert_eq!(d.checked_div_int(1i8), Some(1));
1831
1832 assert_eq!(a.checked_div_int(0), None);
1833 assert_eq!(b.checked_div_int(0), None);
1834 assert_eq!(c.checked_div_int(0), None);
1835 assert_eq!(d.checked_div_int(0), None);
1836 }
1837
1838 #[test]
1839 #[should_panic(expected = "attempt to divide by zero")]
1840 fn saturating_div_int_panics_when_divisor_is_zero() {
1841 let _ = $name::one().saturating_div_int(0);
1842 }
1843
1844 #[test]
1845 fn saturating_div_int_works() {
1846 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1847 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1848 let accuracy = $name::accuracy();
1849
1850 let a = $name::saturating_from_integer(5);
1851 assert_eq!(a.saturating_div_int(2), 2);
1852
1853 let a = $name::min_value();
1854 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1855
1856 if $name::SIGNED {
1857 let a = $name::saturating_from_integer(5);
1858 assert_eq!(a.saturating_div_int(-2), -2);
1859
1860 let a = $name::min_value();
1861 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1862 }
1863 }
1864
1865 #[test]
1866 fn saturating_abs_works() {
1867 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1868 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1869
1870 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1871 assert_eq!($name::zero().saturating_abs(), 0.into());
1872
1873 if $name::SIGNED {
1874 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1875 assert_eq!(
1876 $name::saturating_from_rational(-1, 2).saturating_abs(),
1877 (1, 2).into()
1878 );
1879 }
1880 }
1881
1882 #[test]
1883 fn saturating_mul_acc_int_works() {
1884 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1885 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1886
1887 assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1888 assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1889
1890 assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1891 assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1892
1893 if $name::SIGNED {
1894 let a = $name::saturating_from_rational(-1, 2);
1895 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1896 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1897 assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1898 }
1899 }
1900
1901 #[test]
1902 fn saturating_pow_should_work() {
1903 assert_eq!(
1904 $name::saturating_from_integer(2).saturating_pow(0),
1905 $name::saturating_from_integer(1)
1906 );
1907 assert_eq!(
1908 $name::saturating_from_integer(2).saturating_pow(1),
1909 $name::saturating_from_integer(2)
1910 );
1911 assert_eq!(
1912 $name::saturating_from_integer(2).saturating_pow(2),
1913 $name::saturating_from_integer(4)
1914 );
1915 assert_eq!(
1916 $name::saturating_from_integer(2).saturating_pow(3),
1917 $name::saturating_from_integer(8)
1918 );
1919 assert_eq!(
1920 $name::saturating_from_integer(2).saturating_pow(50),
1921 $name::saturating_from_integer(1125899906842624i64)
1922 );
1923
1924 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
1925 assert_eq!(
1926 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1927 (1).into()
1928 );
1929
1930 if $name::SIGNED {
1931 assert_eq!(
1933 $name::saturating_from_integer(2).saturating_pow(68),
1934 $name::max_value()
1935 );
1936
1937 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
1938 assert_eq!(
1939 $name::saturating_from_integer(-1).saturating_pow(1001),
1940 0.saturating_sub(1).into()
1941 );
1942 assert_eq!(
1943 $name::saturating_from_integer(-1).saturating_pow(usize::MAX),
1944 0.saturating_sub(1).into()
1945 );
1946 assert_eq!(
1947 $name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
1948 (1).into()
1949 );
1950 }
1951
1952 assert_eq!(
1953 $name::saturating_from_integer(114209).saturating_pow(5),
1954 $name::max_value()
1955 );
1956
1957 assert_eq!(
1958 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1959 (1).into()
1960 );
1961 assert_eq!(
1962 $name::saturating_from_integer(0).saturating_pow(usize::MAX),
1963 (0).into()
1964 );
1965 assert_eq!(
1966 $name::saturating_from_integer(2).saturating_pow(usize::MAX),
1967 $name::max_value()
1968 );
1969 }
1970
1971 #[test]
1972 fn checked_div_works() {
1973 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1974 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1975
1976 let a = $name::from_inner(inner_max);
1977 let b = $name::from_inner(inner_min);
1978 let c = $name::zero();
1979 let d = $name::one();
1980 let e = $name::saturating_from_integer(6);
1981 let f = $name::saturating_from_integer(5);
1982
1983 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
1984 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
1985
1986 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
1987 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
1988 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
1989 assert_eq!(a.checked_div(&d), Some(a));
1990
1991 if b < c {
1992 assert_eq!(
1994 a.checked_div(&0.saturating_sub(2).into()),
1995 Some($name::from_inner(0.saturating_sub(inner_max / 2)))
1996 );
1997 assert_eq!(
1998 a.checked_div(&-$name::max_value()),
1999 Some(0.saturating_sub(1).into())
2000 );
2001 assert_eq!(
2002 b.checked_div(&0.saturating_sub(2).into()),
2003 Some($name::from_inner(0.saturating_sub(inner_min / 2)))
2004 );
2005 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
2006 assert_eq!(b.checked_div(&b), Some($name::one()));
2007 }
2008
2009 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
2010 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
2011 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
2012 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
2013
2014 assert_eq!(a.checked_div(&$name::one()), Some(a));
2015 assert_eq!(b.checked_div(&$name::one()), Some(b));
2016 assert_eq!(c.checked_div(&$name::one()), Some(c));
2017 assert_eq!(d.checked_div(&$name::one()), Some(d));
2018
2019 assert_eq!(a.checked_div(&$name::zero()), None);
2020 assert_eq!(b.checked_div(&$name::zero()), None);
2021 assert_eq!(c.checked_div(&$name::zero()), None);
2022 assert_eq!(d.checked_div(&$name::zero()), None);
2023 }
2024
2025 #[test]
2026 fn is_positive_negative_works() {
2027 let one = $name::one();
2028 assert!(one.is_positive());
2029 assert!(!one.is_negative());
2030
2031 let zero = $name::zero();
2032 assert!(!zero.is_positive());
2033 assert!(!zero.is_negative());
2034
2035 if $signed {
2036 let minus_one = $name::saturating_from_integer(-1);
2037 assert!(minus_one.is_negative());
2038 assert!(!minus_one.is_positive());
2039 }
2040 }
2041
2042 #[test]
2043 fn trunc_works() {
2044 let n = $name::saturating_from_rational(5, 2).trunc();
2045 assert_eq!(n, $name::saturating_from_integer(2));
2046
2047 if $name::SIGNED {
2048 let n = $name::saturating_from_rational(-5, 2).trunc();
2049 assert_eq!(n, $name::saturating_from_integer(-2));
2050 }
2051 }
2052
2053 #[test]
2054 fn frac_works() {
2055 let n = $name::saturating_from_rational(5, 2);
2056 let i = n.trunc();
2057 let f = n.frac();
2058
2059 assert_eq!(n, i + f);
2060
2061 let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2062 assert_eq!(n, 5.into());
2063
2064 let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2065 assert_eq!(n, 5.into());
2066
2067 if $name::SIGNED {
2068 let n = $name::saturating_from_rational(-5, 2);
2069 let i = n.trunc();
2070 let f = n.frac();
2071 assert_eq!(n, i - f);
2072
2073 let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2075 assert_eq!(n, 5.into());
2076
2077 let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2078 assert_eq!(n, 0.saturating_sub(5).into());
2079 }
2080 }
2081
2082 #[test]
2083 fn ceil_works() {
2084 let n = $name::saturating_from_rational(5, 2);
2085 assert_eq!(n.ceil(), 3.into());
2086
2087 let n = $name::saturating_from_rational(-5, 2);
2088 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2089
2090 let n = $name::max_value();
2092 assert_eq!(n.ceil(), n.trunc());
2093
2094 let n = $name::min_value();
2095 assert_eq!(n.ceil(), n.trunc());
2096 }
2097
2098 #[test]
2099 fn floor_works() {
2100 let n = $name::saturating_from_rational(5, 2);
2101 assert_eq!(n.floor(), 2.into());
2102
2103 let n = $name::saturating_from_rational(-5, 2);
2104 assert_eq!(n.floor(), 0.saturating_sub(3).into());
2105
2106 let n = $name::max_value();
2108 assert_eq!(n.floor(), n.trunc());
2109
2110 let n = $name::min_value();
2111 assert_eq!(n.floor(), n.trunc());
2112 }
2113
2114 #[test]
2115 fn round_works() {
2116 let n = $name::zero();
2117 assert_eq!(n.round(), n);
2118
2119 let n = $name::one();
2120 assert_eq!(n.round(), n);
2121
2122 let n = $name::saturating_from_rational(5, 2);
2123 assert_eq!(n.round(), 3.into());
2124
2125 let n = $name::saturating_from_rational(-5, 2);
2126 assert_eq!(n.round(), 0.saturating_sub(3).into());
2127
2128 let n = $name::max_value();
2130 assert_eq!(n.round(), n.trunc());
2131
2132 let n = $name::min_value();
2133 assert_eq!(n.round(), n.trunc());
2134
2135 let n = $name::max_value()
2139 .saturating_sub(1.into())
2140 .trunc()
2141 .saturating_add((1, 3).into());
2142
2143 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2144
2145 let n = $name::max_value()
2147 .saturating_sub(1.into())
2148 .trunc()
2149 .saturating_add((1, 2).into());
2150
2151 assert_eq!(n.round(), $name::max_value().trunc());
2152
2153 if $name::SIGNED {
2154 let n = $name::min_value()
2156 .saturating_add(1.into())
2157 .trunc()
2158 .saturating_sub((1, 3).into());
2159
2160 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2161
2162 let n = $name::min_value()
2164 .saturating_add(1.into())
2165 .trunc()
2166 .saturating_sub((1, 2).into());
2167
2168 assert_eq!(n.round(), $name::min_value().trunc());
2169 }
2170 }
2171
2172 #[test]
2173 fn perthing_into_works() {
2174 let ten_percent_percent: $name = Percent::from_percent(10).into();
2175 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2176
2177 let ten_percent_permill: $name = Permill::from_percent(10).into();
2178 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2179
2180 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2181 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2182
2183 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2184 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2185 }
2186
2187 #[test]
2188 fn fmt_should_work() {
2189 let zero = $name::zero();
2190 assert_eq!(
2191 format!("{:?}", zero),
2192 format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2193 );
2194
2195 let one = $name::one();
2196 assert_eq!(
2197 format!("{:?}", one),
2198 format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2199 );
2200
2201 let frac = $name::saturating_from_rational(1, 2);
2202 assert_eq!(
2203 format!("{:?}", frac),
2204 format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2205 );
2206
2207 let frac = $name::saturating_from_rational(5, 2);
2208 assert_eq!(
2209 format!("{:?}", frac),
2210 format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2211 );
2212
2213 let frac = $name::saturating_from_rational(314, 100);
2214 assert_eq!(
2215 format!("{:?}", frac),
2216 format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2217 );
2218
2219 if $name::SIGNED {
2220 let neg = -$name::one();
2221 assert_eq!(
2222 format!("{:?}", neg),
2223 format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2224 );
2225
2226 let frac = $name::saturating_from_rational(-314, 100);
2227 assert_eq!(
2228 format!("{:?}", frac),
2229 format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2230 );
2231 }
2232 }
2233 }
2234 };
2235}
2236
2237implement_fixed!(
2238 FixedI64,
2239 test_fixed_i64,
2240 i64,
2241 true,
2242 1_000_000_000,
2243 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2244);
2245
2246implement_fixed!(
2247 FixedU64,
2248 test_fixed_u64,
2249 u64,
2250 false,
2251 1_000_000_000,
2252 "_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2253);
2254
2255implement_fixed!(
2256 FixedI128,
2257 test_fixed_i128,
2258 i128,
2259 true,
2260 1_000_000_000_000_000_000,
2261 "_Fixed Point 128 bits signed, range = \
2262 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2263);
2264
2265implement_fixed!(
2266 FixedU128,
2267 test_fixed_u128,
2268 u128,
2269 false,
2270 1_000_000_000_000_000_000,
2271 "_Fixed Point 128 bits unsigned, range = \
2272 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
2273);