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 fn checked_sqrt(self) -> Option<Self>;
145
146 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 fn checked_from_integer<N: Into<Self::Inner>>(int: N) -> Option<Self> {
159 let int: Self::Inner = int.into();
160 int.checked_mul(&Self::DIV).map(Self::from_inner)
161 }
162
163 fn saturating_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Self {
167 if d == D::zero() {
168 panic!("attempt to divide by zero")
169 }
170 Self::checked_from_rational(n, d).unwrap_or_else(|| to_bound(n, d))
171 }
172
173 fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
177 n: N,
178 d: D,
179 ) -> Option<Self> {
180 if d == D::zero() {
181 return None
182 }
183
184 let n: I129 = n.into();
185 let d: I129 = d.into();
186 let negative = n.negative != d.negative;
187
188 multiply_by_rational_with_rounding(
189 n.value,
190 Self::DIV.unique_saturated_into(),
191 d.value,
192 Rounding::from_signed(SignedRounding::Minor, negative),
193 )
194 .and_then(|value| from_i129(I129 { value, negative }))
195 .map(Self::from_inner)
196 }
197
198 fn checked_mul_int<N: FixedPointOperand>(self, n: N) -> Option<N> {
202 let lhs: I129 = self.into_inner().into();
203 let rhs: I129 = n.into();
204 let negative = lhs.negative != rhs.negative;
205
206 multiply_by_rational_with_rounding(
207 lhs.value,
208 rhs.value,
209 Self::DIV.unique_saturated_into(),
210 Rounding::from_signed(SignedRounding::Minor, negative),
211 )
212 .and_then(|value| from_i129(I129 { value, negative }))
213 }
214
215 fn saturating_mul_int<N: FixedPointOperand>(self, n: N) -> N {
219 self.checked_mul_int(n).unwrap_or_else(|| to_bound(self.into_inner(), n))
220 }
221
222 fn checked_div_int<N: FixedPointOperand>(self, d: N) -> Option<N> {
226 let lhs: I129 = self.into_inner().into();
227 let rhs: I129 = d.into();
228 let negative = lhs.negative != rhs.negative;
229
230 lhs.value
231 .checked_div(rhs.value)
232 .and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
233 .and_then(|value| from_i129(I129 { value, negative }))
234 }
235
236 fn saturating_div_int<N: FixedPointOperand>(self, d: N) -> N {
240 if d == N::zero() {
241 panic!("attempt to divide by zero")
242 }
243 self.checked_div_int(d).unwrap_or_else(|| to_bound(self.into_inner(), d))
244 }
245
246 fn saturating_mul_acc_int<N: FixedPointOperand>(self, n: N) -> N {
251 if self.is_negative() && n > N::zero() {
252 n.saturating_sub(Self::zero().saturating_sub(self).saturating_mul_int(n))
253 } else {
254 self.saturating_mul_int(n).saturating_add(n)
255 }
256 }
257
258 fn saturating_abs(self) -> Self {
262 let inner = self.into_inner();
263 if inner >= Self::Inner::zero() {
264 self
265 } else {
266 Self::from_inner(inner.checked_neg().unwrap_or_else(Self::Inner::max_value))
267 }
268 }
269
270 fn reciprocal(self) -> Option<Self> {
274 Self::one().checked_div(&self)
275 }
276
277 fn is_one(&self) -> bool {
279 self.into_inner() == Self::Inner::one()
280 }
281
282 fn is_positive(self) -> bool {
284 self.into_inner() > Self::Inner::zero()
285 }
286
287 fn is_negative(self) -> bool {
289 self.into_inner() < Self::Inner::zero()
290 }
291
292 fn trunc(self) -> Self {
294 self.into_inner()
295 .checked_div(&Self::DIV)
296 .expect("panics only if DIV is zero, DIV is not zero; qed")
297 .checked_mul(&Self::DIV)
298 .map(Self::from_inner)
299 .expect("can not overflow since fixed number is >= integer part")
300 }
301
302 fn frac(self) -> Self {
307 let integer = self.trunc();
308 let fractional = self.saturating_sub(integer);
309 if integer == Self::zero() {
310 fractional
311 } else {
312 fractional.saturating_abs()
313 }
314 }
315
316 fn ceil(self) -> Self {
320 if self.is_negative() {
321 self.trunc()
322 } else if self.frac() == Self::zero() {
323 self
324 } else {
325 self.saturating_add(Self::one()).trunc()
326 }
327 }
328
329 fn floor(self) -> Self {
333 if self.is_negative() {
334 self.saturating_sub(Self::one()).trunc()
335 } else {
336 self.trunc()
337 }
338 }
339
340 fn round(self) -> Self {
344 let n = self.frac().saturating_mul(Self::saturating_from_integer(10));
345 if n < Self::saturating_from_integer(5) {
346 self.trunc()
347 } else if self.is_positive() {
348 self.saturating_add(Self::one()).trunc()
349 } else {
350 self.saturating_sub(Self::one()).trunc()
351 }
352 }
353}
354
355struct I129 {
357 value: u128,
358 negative: bool,
359}
360
361impl<N: FixedPointOperand> From<N> for I129 {
362 fn from(n: N) -> I129 {
363 if n < N::zero() {
364 let value: u128 = n
365 .checked_neg()
366 .map(|n| n.unique_saturated_into())
367 .unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
368 I129 { value, negative: true }
369 } else {
370 I129 { value: n.unique_saturated_into(), negative: false }
371 }
372 }
373}
374
375fn from_i129<N: FixedPointOperand>(n: I129) -> Option<N> {
377 let max_plus_one: u128 = N::max_value().unique_saturated_into().saturating_add(1);
378 if n.negative && N::min_value() < N::zero() && n.value == max_plus_one {
379 Some(N::min_value())
380 } else {
381 let unsigned_inner: N = n.value.try_into().ok()?;
382 let inner = if n.negative { unsigned_inner.checked_neg()? } else { unsigned_inner };
383 Some(inner)
384 }
385}
386
387fn to_bound<N: FixedPointOperand, D: FixedPointOperand, R: Bounded>(n: N, m: D) -> R {
389 if (n < N::zero()) != (m < D::zero()) {
390 R::min_value()
391 } else {
392 R::max_value()
393 }
394}
395
396macro_rules! implement_fixed {
397 (
398 $name:ident,
399 $test_mod:ident,
400 $inner_type:ty,
401 $signed:tt,
402 $div:tt,
403 $title:expr $(,)?
404 ) => {
405 #[doc = $title]
407 #[derive(
408 Encode,
409 Decode,
410 DecodeWithMemTracking,
411 CompactAs,
412 Default,
413 Copy,
414 Clone,
415 codec::MaxEncodedLen,
416 PartialEq,
417 Eq,
418 PartialOrd,
419 Ord,
420 scale_info::TypeInfo,
421 )]
422 pub struct $name($inner_type);
423
424 impl From<$inner_type> for $name {
425 fn from(int: $inner_type) -> Self {
426 $name::saturating_from_integer(int)
427 }
428 }
429
430 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
431 fn from(r: (N, D)) -> Self {
432 $name::saturating_from_rational(r.0, r.1)
433 }
434 }
435
436 impl FixedPointNumber for $name {
437 type Inner = $inner_type;
438
439 const DIV: Self::Inner = $div;
440 const SIGNED: bool = $signed;
441
442 fn from_inner(inner: Self::Inner) -> Self {
443 Self(inner)
444 }
445
446 fn into_inner(self) -> Self::Inner {
447 self.0
448 }
449
450 fn checked_sqrt(self) -> Option<Self> {
451 self.checked_sqrt()
452 }
453 }
454
455 impl $name {
456 pub const fn from_inner(inner: $inner_type) -> Self {
460 Self(inner)
461 }
462
463 pub const fn into_inner(self) -> $inner_type {
467 self.0
468 }
469
470 pub const fn from_u32(n: u32) -> Self {
475 Self::from_inner((n as $inner_type) * $div)
476 }
477
478 #[cfg(any(feature = "std", test))]
480 pub fn from_float(x: f64) -> Self {
481 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
482 }
483
484 pub const fn from_perbill(n: Perbill) -> Self {
486 Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
487 }
488
489 pub const fn into_perbill(self) -> Perbill {
491 if self.0 <= 0 {
492 Perbill::zero()
493 } else if self.0 >= $div {
494 Perbill::one()
495 } else {
496 match multiply_by_rational_with_rounding(
497 self.0 as u128,
498 1_000_000_000,
499 Self::DIV as u128,
500 Rounding::NearestPrefDown,
501 ) {
502 Some(value) => {
503 if value > (u32::max_value() as u128) {
504 panic!(
505 "prior logic ensures 0<self.0<DIV; \
506 multiply ensures 0<self.0<1000000000; \
507 qed"
508 );
509 }
510 Perbill::from_parts(value as u32)
511 },
512 None => Perbill::zero(),
513 }
514 }
515 }
516
517 #[cfg(any(feature = "std", test))]
519 pub fn to_float(self) -> f64 {
520 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
521 }
522
523 pub fn try_into_perthing<P: PerThing>(self) -> Result<P, P> {
527 if self < Self::zero() {
528 Err(P::zero())
529 } else if self > Self::one() {
530 Err(P::one())
531 } else {
532 Ok(P::from_rational(self.0 as u128, $div))
533 }
534 }
535
536 pub fn into_clamped_perthing<P: PerThing>(self) -> P {
539 if self < Self::zero() {
540 P::zero()
541 } else if self > Self::one() {
542 P::one()
543 } else {
544 P::from_rational(self.0 as u128, $div)
545 }
546 }
547
548 pub const fn neg(self) -> Self {
553 Self(0 - self.0)
554 }
555
556 pub const fn sqrt(self) -> Self {
561 match self.checked_sqrt() {
562 Some(v) => v,
563 None => panic!("sqrt overflow or negative input"),
564 }
565 }
566
567 #[deprecated(
568 note = "`try_sqrt` will be removed after October 2025. Use `checked_sqrt` instead."
569 )]
570 pub const fn try_sqrt(self) -> Option<Self> {
571 self.checked_sqrt()
572 }
573
574 pub const fn checked_sqrt(self) -> Option<Self> {
576 if self.0 == 0 {
577 return Some(Self(0))
578 }
579 if self.0 < 1 {
580 return None
581 }
582 let v = self.0 as u128;
583
584 let maybe_vd = u128::checked_mul(v, $div);
594 let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
595 Some(Self(r as $inner_type))
596 }
597
598 pub const fn add(self, rhs: Self) -> Self {
603 Self(self.0 + rhs.0)
604 }
605
606 pub const fn sub(self, rhs: Self) -> Self {
611 Self(self.0 - rhs.0)
612 }
613
614 pub const fn mul(self, rhs: Self) -> Self {
622 match $name::const_checked_mul(self, rhs) {
623 Some(v) => v,
624 None => panic!("attempt to multiply with overflow"),
625 }
626 }
627
628 pub const fn div(self, rhs: Self) -> Self {
636 match $name::const_checked_div(self, rhs) {
637 Some(v) => v,
638 None => panic!("attempt to divide with overflow or NaN"),
639 }
640 }
641
642 const fn into_i129(self) -> I129 {
647 #[allow(unused_comparisons)]
648 if self.0 < 0 {
649 let value = match self.0.checked_neg() {
650 Some(n) => n as u128,
651 None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
652 };
653 I129 { value, negative: true }
654 } else {
655 I129 { value: self.0 as u128, negative: false }
656 }
657 }
658
659 const fn from_i129(n: I129) -> Option<Self> {
664 let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
665 #[allow(unused_comparisons)]
666 let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
667 <$inner_type>::min_value()
668 } else {
669 let unsigned_inner = n.value as $inner_type;
670 if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
671 return None
672 };
673 if n.negative {
674 match unsigned_inner.checked_neg() {
675 Some(v) => v,
676 None => return None,
677 }
678 } else {
679 unsigned_inner
680 }
681 };
682 Some(Self(inner))
683 }
684
685 pub const fn from_rational(a: u128, b: u128) -> Self {
693 Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
694 }
695
696 pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
701 if b == 0 {
702 panic!("attempt to divide by zero in from_rational")
703 }
704 match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
705 Some(value) => match Self::from_i129(I129 { value, negative: false }) {
706 Some(x) => x,
707 None => panic!("overflow in from_rational"),
708 },
709 None => panic!("overflow in from_rational"),
710 }
711 }
712
713 pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
718 self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
719 }
720
721 pub const fn const_checked_mul_with_rounding(
727 self,
728 other: Self,
729 rounding: SignedRounding,
730 ) -> Option<Self> {
731 let lhs = self.into_i129();
732 let rhs = other.into_i129();
733 let negative = lhs.negative != rhs.negative;
734
735 match multiply_by_rational_with_rounding(
736 lhs.value,
737 rhs.value,
738 Self::DIV as u128,
739 Rounding::from_signed(rounding, negative),
740 ) {
741 Some(value) => Self::from_i129(I129 { value, negative }),
742 None => None,
743 }
744 }
745
746 pub const fn const_checked_div(self, other: Self) -> Option<Self> {
751 self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
752 }
753
754 pub const fn checked_rounding_div(
760 self,
761 other: Self,
762 rounding: SignedRounding,
763 ) -> Option<Self> {
764 if other.0 == 0 {
765 return None
766 }
767
768 let lhs = self.into_i129();
769 let rhs = other.into_i129();
770 let negative = lhs.negative != rhs.negative;
771
772 match multiply_by_rational_with_rounding(
773 lhs.value,
774 Self::DIV as u128,
775 rhs.value,
776 Rounding::from_signed(rounding, negative),
777 ) {
778 Some(value) => Self::from_i129(I129 { value, negative }),
779 None => None,
780 }
781 }
782 }
783
784 impl Saturating for $name {
785 fn saturating_add(self, rhs: Self) -> Self {
786 Self(self.0.saturating_add(rhs.0))
787 }
788
789 fn saturating_sub(self, rhs: Self) -> Self {
790 Self(self.0.saturating_sub(rhs.0))
791 }
792
793 fn saturating_mul(self, rhs: Self) -> Self {
794 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
795 }
796
797 fn saturating_pow(self, exp: usize) -> Self {
798 if exp == 0 {
799 return Self::saturating_from_integer(1)
800 }
801
802 let exp = exp as u32;
803 let msb_pos = 32 - exp.leading_zeros();
804
805 let mut result = Self::saturating_from_integer(1);
806 let mut pow_val = self;
807 for i in 0..msb_pos {
808 if ((1 << i) & exp) > 0 {
809 result = result.saturating_mul(pow_val);
810 }
811 pow_val = pow_val.saturating_mul(pow_val);
812 }
813 result
814 }
815 }
816
817 impl ops::Neg for $name {
818 type Output = Self;
819
820 fn neg(self) -> Self::Output {
821 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
822 }
823 }
824
825 impl ops::Add for $name {
826 type Output = Self;
827
828 fn add(self, rhs: Self) -> Self::Output {
829 Self(self.0 + rhs.0)
830 }
831 }
832
833 impl ops::Sub for $name {
834 type Output = Self;
835
836 fn sub(self, rhs: Self) -> Self::Output {
837 Self(self.0 - rhs.0)
838 }
839 }
840
841 impl ops::Mul for $name {
842 type Output = Self;
843
844 fn mul(self, rhs: Self) -> Self::Output {
845 self.checked_mul(&rhs)
846 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
847 }
848 }
849
850 impl ops::Div for $name {
851 type Output = Self;
852
853 fn div(self, rhs: Self) -> Self::Output {
854 if rhs.0 == 0 {
855 panic!("attempt to divide by zero")
856 }
857 self.checked_div(&rhs)
858 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
859 }
860 }
861
862 impl CheckedSub for $name {
863 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
864 self.0.checked_sub(rhs.0).map(Self)
865 }
866 }
867
868 impl CheckedAdd for $name {
869 fn checked_add(&self, rhs: &Self) -> Option<Self> {
870 self.0.checked_add(rhs.0).map(Self)
871 }
872 }
873
874 impl CheckedDiv for $name {
875 fn checked_div(&self, other: &Self) -> Option<Self> {
876 if other.0 == 0 {
877 return None
878 }
879
880 let lhs: I129 = self.0.into();
881 let rhs: I129 = other.0.into();
882 let negative = lhs.negative != rhs.negative;
883
884 multiply_by_rational_with_rounding(
889 lhs.value,
890 Self::DIV as u128,
891 rhs.value,
892 Rounding::from_signed(SignedRounding::Minor, negative),
893 )
894 .and_then(|value| from_i129(I129 { value, negative }))
895 .map(Self)
896 }
897 }
898
899 impl CheckedMul for $name {
900 fn checked_mul(&self, other: &Self) -> Option<Self> {
901 let lhs: I129 = self.0.into();
902 let rhs: I129 = other.0.into();
903 let negative = lhs.negative != rhs.negative;
904
905 multiply_by_rational_with_rounding(
906 lhs.value,
907 rhs.value,
908 Self::DIV as u128,
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 Bounded for $name {
917 fn min_value() -> Self {
918 Self(<Self as FixedPointNumber>::Inner::min_value())
919 }
920
921 fn max_value() -> Self {
922 Self(<Self as FixedPointNumber>::Inner::max_value())
923 }
924 }
925
926 impl Zero for $name {
927 fn zero() -> Self {
928 Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
929 }
930
931 fn is_zero(&self) -> bool {
932 self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
933 }
934 }
935
936 impl One for $name {
937 fn one() -> Self {
938 Self::from_inner(Self::DIV)
939 }
940 }
941
942 impl ::core::fmt::Debug for $name {
943 #[cfg(feature = "std")]
944 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
945 let integral = {
946 let int = self.0 / Self::accuracy();
947 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
948 format!("{}{}", signum_for_zero, int)
949 };
950 let precision = (Self::accuracy() as f64).log10() as usize;
951 let fractional = format!(
952 "{:0>weight$}",
953 ((self.0 % Self::accuracy()) as i128).abs(),
954 weight = precision
955 );
956 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
957 }
958
959 #[cfg(not(feature = "std"))]
960 fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
961 Ok(())
962 }
963 }
964
965 impl<P: PerThing> From<P> for $name
966 where
967 P::Inner: FixedPointOperand,
968 {
969 fn from(p: P) -> Self {
970 let accuracy = P::ACCURACY;
971 let value = p.deconstruct();
972 $name::saturating_from_rational(value, accuracy)
973 }
974 }
975
976 impl ::core::fmt::Display for $name {
977 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
978 write!(f, "{}", self.0)
979 }
980 }
981
982 impl ::core::str::FromStr for $name {
983 type Err = &'static str;
984
985 fn from_str(s: &str) -> Result<Self, Self::Err> {
986 let inner: <Self as FixedPointNumber>::Inner =
987 s.parse().map_err(|_| "invalid string input for fixed point number")?;
988 Ok(Self::from_inner(inner))
989 }
990 }
991
992 #[cfg(feature = "serde")]
995 impl Serialize for $name {
996 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
997 where
998 S: Serializer,
999 {
1000 serializer.serialize_str(&self.to_string())
1001 }
1002 }
1003
1004 #[cfg(feature = "serde")]
1007 impl<'de> Deserialize<'de> for $name {
1008 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1009 where
1010 D: Deserializer<'de>,
1011 {
1012 use ::core::str::FromStr;
1013 let s = String::deserialize(deserializer)?;
1014 $name::from_str(&s).map_err(de::Error::custom)
1015 }
1016 }
1017
1018 #[cfg(test)]
1019 mod $test_mod {
1020 use super::*;
1021 use crate::{Perbill, Percent, Permill, Perquintill};
1022
1023 fn max() -> $name {
1024 $name::max_value()
1025 }
1026
1027 fn min() -> $name {
1028 $name::min_value()
1029 }
1030
1031 fn precision() -> usize {
1032 ($name::accuracy() as f64).log10() as usize
1033 }
1034
1035 #[test]
1036 fn macro_preconditions() {
1037 assert!($name::DIV > 0);
1038 }
1039
1040 #[test]
1041 fn has_max_encoded_len() {
1042 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1043 _data: T,
1044 }
1045
1046 let _ = AsMaxEncodedLen { _data: $name::min_value() };
1047 }
1048
1049 #[test]
1050 fn from_i129_works() {
1051 let a = I129 { value: 1, negative: true };
1052
1053 assert_eq!(from_i129::<u128>(a), None);
1055
1056 let a = I129 { value: u128::MAX - 1, negative: false };
1057
1058 assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1060
1061 let a = I129 { value: u128::MAX, negative: false };
1062
1063 assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1065
1066 let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1067
1068 assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1070
1071 let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1072
1073 assert_eq!(from_i129::<i128>(a), None);
1075
1076 let a = I129 { value: i128::MAX as u128, negative: false };
1077
1078 assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1080 }
1081
1082 #[test]
1083 fn to_bound_works() {
1084 let a = 1i32;
1085 let b = 1i32;
1086
1087 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1089
1090 let a = -1i32;
1091 let b = -1i32;
1092
1093 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1095
1096 let a = 1i32;
1097 let b = -1i32;
1098
1099 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1101
1102 let a = -1i32;
1103 let b = 1i32;
1104
1105 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1107
1108 let a = 1i32;
1109 let b = -1i32;
1110
1111 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1113 }
1114
1115 #[test]
1116 fn op_neg_works() {
1117 let a = $name::zero();
1118 let b = -a;
1119
1120 assert_eq!(a, b);
1122
1123 if $name::SIGNED {
1124 let a = $name::saturating_from_integer(5);
1125 let b = -a;
1126
1127 assert_eq!($name::saturating_from_integer(-5), b);
1129
1130 let a = $name::saturating_from_integer(-5);
1131 let b = -a;
1132
1133 assert_eq!($name::saturating_from_integer(5), b);
1135
1136 let a = $name::max_value();
1137 let b = -a;
1138
1139 assert_eq!($name::min_value() + $name::from_inner(1), b);
1141
1142 let a = $name::min_value() + $name::from_inner(1);
1143 let b = -a;
1144
1145 assert_eq!($name::max_value(), b);
1147 }
1148 }
1149
1150 #[test]
1151 fn op_checked_add_overflow_works() {
1152 let a = $name::max_value();
1153 let b = 1.into();
1154 assert!(a.checked_add(&b).is_none());
1155 }
1156
1157 #[test]
1158 fn op_add_works() {
1159 let a = $name::saturating_from_rational(5, 2);
1160 let b = $name::saturating_from_rational(1, 2);
1161
1162 assert_eq!($name::saturating_from_integer(3), a + b);
1164
1165 if $name::SIGNED {
1166 let b = $name::saturating_from_rational(1, -2);
1168 assert_eq!($name::saturating_from_integer(2), a + b);
1169 }
1170 }
1171
1172 #[test]
1173 fn op_checked_sub_underflow_works() {
1174 let a = $name::min_value();
1175 let b = 1.into();
1176 assert!(a.checked_sub(&b).is_none());
1177 }
1178
1179 #[test]
1180 fn op_sub_works() {
1181 let a = $name::saturating_from_rational(5, 2);
1182 let b = $name::saturating_from_rational(1, 2);
1183
1184 assert_eq!($name::saturating_from_integer(2), a - b);
1185 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1186 }
1187
1188 #[test]
1189 fn op_checked_mul_overflow_works() {
1190 let a = $name::max_value();
1191 let b = 2.into();
1192 assert!(a.checked_mul(&b).is_none());
1193 }
1194
1195 #[test]
1196 fn op_mul_works() {
1197 let a = $name::saturating_from_integer(42);
1198 let b = $name::saturating_from_integer(2);
1199 assert_eq!($name::saturating_from_integer(84), a * b);
1200
1201 let a = $name::saturating_from_integer(42);
1202 let b = $name::saturating_from_integer(-2);
1203 assert_eq!($name::saturating_from_integer(-84), a * b);
1204 }
1205
1206 #[test]
1207 #[should_panic(expected = "attempt to divide by zero")]
1208 fn op_div_panics_on_zero_divisor() {
1209 let a = $name::saturating_from_integer(1);
1210 let b = 0.into();
1211 let _c = a / b;
1212 }
1213
1214 #[test]
1215 fn op_checked_div_overflow_works() {
1216 if $name::SIGNED {
1217 let a = $name::min_value();
1218 let b = $name::zero().saturating_sub($name::one());
1219 assert!(a.checked_div(&b).is_none());
1220 }
1221 }
1222
1223 #[test]
1224 fn op_sqrt_works() {
1225 for i in 1..1_000i64 {
1226 let x = $name::saturating_from_rational(i, 1_000i64);
1227 assert_eq!((x * x).checked_sqrt(), Some(x));
1228 let x = $name::saturating_from_rational(i, 1i64);
1229 assert_eq!((x * x).checked_sqrt(), Some(x));
1230 }
1231 }
1232
1233 #[test]
1234 fn op_div_works() {
1235 let a = $name::saturating_from_integer(42);
1236 let b = $name::saturating_from_integer(2);
1237 assert_eq!($name::saturating_from_integer(21), a / b);
1238
1239 if $name::SIGNED {
1240 let a = $name::saturating_from_integer(42);
1241 let b = $name::saturating_from_integer(-2);
1242 assert_eq!($name::saturating_from_integer(-21), a / b);
1243 }
1244 }
1245
1246 #[test]
1247 fn saturating_from_integer_works() {
1248 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1249 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1250 let accuracy = $name::accuracy();
1251
1252 let a = $name::saturating_from_integer(42);
1254 assert_eq!(a.into_inner(), 42 * accuracy);
1255
1256 let a = $name::saturating_from_integer(-42);
1257 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1258
1259 let a = $name::saturating_from_integer(inner_max / accuracy);
1261 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1262
1263 let a = $name::saturating_from_integer(inner_min / accuracy);
1264 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1265
1266 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1268 assert_eq!(a.into_inner(), inner_max);
1269
1270 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1271 assert_eq!(a.into_inner(), inner_min);
1272 }
1273
1274 #[test]
1275 fn checked_from_integer_works() {
1276 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1277 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1278 let accuracy = $name::accuracy();
1279
1280 let a = $name::checked_from_integer::<$inner_type>(42)
1282 .expect("42 * accuracy <= inner_max; qed");
1283 assert_eq!(a.into_inner(), 42 * accuracy);
1284
1285 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1287 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1288 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1289
1290 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1292 assert_eq!(a, None);
1293
1294 if $name::SIGNED {
1295 let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1297 .expect("-42 * accuracy >= inner_min; qed");
1298 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1299
1300 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1302 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1303 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1304
1305 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1307 assert_eq!(a, None);
1308 }
1309 }
1310
1311 #[test]
1312 fn from_inner_works() {
1313 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1314 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1315
1316 assert_eq!(max(), $name::from_inner(inner_max));
1317 assert_eq!(min(), $name::from_inner(inner_min));
1318 }
1319
1320 #[test]
1321 #[should_panic(expected = "attempt to divide by zero")]
1322 fn saturating_from_rational_panics_on_zero_divisor() {
1323 let _ = $name::saturating_from_rational(1, 0);
1324 }
1325
1326 #[test]
1327 fn saturating_from_rational_works() {
1328 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1329 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1330 let accuracy = $name::accuracy();
1331
1332 let a = $name::saturating_from_rational(5, 2);
1333
1334 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1336
1337 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1339 assert_eq!(a.into_inner(), inner_max - 1);
1340
1341 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1343 assert_eq!(a.into_inner(), inner_min + 1);
1344
1345 let a = $name::saturating_from_rational(inner_max, accuracy);
1347 assert_eq!(a.into_inner(), inner_max);
1348
1349 let a = $name::saturating_from_rational(inner_min, accuracy);
1351 assert_eq!(a.into_inner(), inner_min);
1352
1353 let a = $name::saturating_from_rational(0, 1);
1355 assert_eq!(a.into_inner(), 0);
1356
1357 if $name::SIGNED {
1358 let a = $name::saturating_from_rational(-5, 2);
1360 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1361
1362 let a = $name::saturating_from_rational(5, -2);
1364 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1365
1366 let a = $name::saturating_from_rational(-5, -2);
1368 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1369
1370 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1372 assert_eq!(a.into_inner(), inner_max);
1373
1374 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1376 assert_eq!(a.into_inner(), inner_min);
1377
1378 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1379 assert_eq!(a.into_inner(), 0 - inner_max);
1380
1381 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1382 assert_eq!(a.into_inner(), inner_max);
1383
1384 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1385 assert_eq!(a.into_inner(), inner_max);
1386
1387 let a = $name::saturating_from_rational(inner_min, 0 - 1);
1388 assert_eq!(a.into_inner(), inner_max);
1389
1390 let a = $name::saturating_from_rational(inner_max, 0 - 1);
1391 assert_eq!(a.into_inner(), inner_min);
1392
1393 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1394 assert_eq!(a.into_inner(), 0 - accuracy);
1395
1396 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1397 assert_eq!(a.into_inner(), 0 - accuracy);
1398
1399 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1400 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1401
1402 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1403 assert_eq!(a.into_inner(), inner_max);
1404
1405 let a = $name::saturating_from_rational(1, 0 - accuracy);
1406 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1407
1408 let a = $name::saturating_from_rational(inner_min, inner_min);
1409 assert_eq!(a.into_inner(), accuracy);
1410
1411 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1413 assert_eq!(a.into_inner(), 0);
1414 }
1415
1416 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1417 assert_eq!(a.into_inner(), inner_max - 1);
1418
1419 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1420 assert_eq!(a.into_inner(), inner_min + 1);
1421
1422 let a = $name::saturating_from_rational(inner_max, 1);
1423 assert_eq!(a.into_inner(), inner_max);
1424
1425 let a = $name::saturating_from_rational(inner_min, 1);
1426 assert_eq!(a.into_inner(), inner_min);
1427
1428 let a = $name::saturating_from_rational(inner_max, inner_max);
1429 assert_eq!(a.into_inner(), accuracy);
1430
1431 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1432 assert_eq!(a.into_inner(), inner_max / 3);
1433
1434 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1435 assert_eq!(a.into_inner(), inner_min / 2);
1436
1437 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1438 assert_eq!(a.into_inner(), inner_min);
1439
1440 let a = $name::saturating_from_rational(1, accuracy);
1441 assert_eq!(a.into_inner(), 1);
1442
1443 let a = $name::saturating_from_rational(1, accuracy + 1);
1445 assert_eq!(a.into_inner(), 0);
1446 }
1447
1448 #[test]
1449 fn checked_from_rational_works() {
1450 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1451 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1452 let accuracy = $name::accuracy();
1453
1454 let a = $name::checked_from_rational(1, 0);
1456 assert_eq!(a, None);
1457
1458 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1460 assert_eq!(a.into_inner(), inner_max - 1);
1461
1462 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1464 assert_eq!(a.into_inner(), inner_min + 1);
1465
1466 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1468 assert_eq!(a.into_inner(), inner_max);
1469
1470 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1472 assert_eq!(a.into_inner(), inner_min);
1473
1474 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1476 assert_eq!(a, None);
1477
1478 if $name::SIGNED {
1479 let a = $name::checked_from_rational(
1481 inner_max as u128 + 2,
1482 0.saturating_sub(accuracy),
1483 );
1484 assert_eq!(a, None);
1485
1486 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1487 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1488
1489 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1490 assert_eq!(a, None);
1491
1492 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1493 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1494
1495 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1496 assert_eq!(a.into_inner(), 0);
1497
1498 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1499 assert_eq!(a, None);
1500 }
1501
1502 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1503 assert_eq!(a.into_inner(), inner_max / 3);
1504
1505 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1506 assert_eq!(a.into_inner(), inner_min / 2);
1507
1508 let a = $name::checked_from_rational(1, accuracy).unwrap();
1509 assert_eq!(a.into_inner(), 1);
1510
1511 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1512 assert_eq!(a.into_inner(), 0);
1513 }
1514
1515 #[test]
1516 fn from_rational_works() {
1517 let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1518 let inner_min: u128 = 0;
1519 let accuracy: u128 = $name::accuracy() as u128;
1520
1521 let a = $name::from_rational(inner_max - 1, accuracy);
1523 assert_eq!(a.into_inner() as u128, inner_max - 1);
1524
1525 let a = $name::from_rational(inner_min + 1, accuracy);
1527 assert_eq!(a.into_inner() as u128, inner_min + 1);
1528
1529 let a = $name::from_rational(inner_max, accuracy);
1531 assert_eq!(a.into_inner() as u128, inner_max);
1532
1533 let a = $name::from_rational(inner_min, accuracy);
1535 assert_eq!(a.into_inner() as u128, inner_min);
1536
1537 let a = $name::from_rational(inner_max, 3 * accuracy);
1538 assert_eq!(a.into_inner() as u128, inner_max / 3);
1539
1540 let a = $name::from_rational(1, accuracy);
1541 assert_eq!(a.into_inner() as u128, 1);
1542
1543 let a = $name::from_rational(1, accuracy + 1);
1544 assert_eq!(a.into_inner() as u128, 1);
1545
1546 let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1547 assert_eq!(a.into_inner() as u128, 0);
1548 }
1549
1550 #[test]
1551 fn checked_mul_int_works() {
1552 let a = $name::saturating_from_integer(2);
1553 assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1555 assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1557 assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1559
1560 if $name::SIGNED {
1561 assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1563 assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1565 assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1567
1568 let b = $name::saturating_from_rational(1, -2);
1569 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1570 assert_eq!(b.checked_mul_int(u128::MAX), None);
1571 assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1572 assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1573 }
1574
1575 let a = $name::saturating_from_rational(1, 2);
1576 assert_eq!(a.checked_mul_int(42i128), Some(21));
1577 assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1578 assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1579
1580 let c = $name::saturating_from_integer(255);
1581 assert_eq!(c.checked_mul_int(2i8), None);
1582 assert_eq!(c.checked_mul_int(2i128), Some(510));
1583 assert_eq!(c.checked_mul_int(i128::MAX), None);
1584 assert_eq!(c.checked_mul_int(i128::MIN), None);
1585 }
1586
1587 #[test]
1588 fn saturating_mul_int_works() {
1589 let a = $name::saturating_from_integer(2);
1590 assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1592 assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1594 assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1596
1597 assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1599 assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1601 assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1603
1604 if $name::SIGNED {
1605 let b = $name::saturating_from_rational(1, -2);
1606 assert_eq!(b.saturating_mul_int(42i32), -21);
1607 assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1608 assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1609 assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1610 }
1611
1612 let a = $name::saturating_from_rational(1, 2);
1613 assert_eq!(a.saturating_mul_int(42i32), 21);
1614 assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1615 assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1616
1617 let c = $name::saturating_from_integer(255);
1618 assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1619 assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1620 assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1621 assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1622 }
1623
1624 #[test]
1625 fn checked_mul_works() {
1626 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1627 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1628
1629 let a = $name::saturating_from_integer(2);
1630
1631 let b = $name::from_inner(inner_max - 1);
1633 assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1634
1635 let c = $name::from_inner(inner_max);
1637 assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1638
1639 let e = $name::from_inner(1);
1641 assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1642
1643 if $name::SIGNED {
1644 let b = $name::from_inner(inner_min + 1) / 2.into();
1646 let c = $name::from_inner(inner_min + 2);
1647 assert_eq!(a.checked_mul(&b), Some(c));
1648
1649 let b = $name::from_inner(inner_min) / 2.into();
1651 let c = $name::from_inner(inner_min);
1652 assert_eq!(a.checked_mul(&b), Some(c));
1653
1654 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1656 assert_eq!(a.checked_mul(&b), None);
1657
1658 let c = $name::saturating_from_integer(255);
1659 let b = $name::saturating_from_rational(1, -2);
1660
1661 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1662 assert_eq!(
1663 b.checked_mul(&$name::max_value()),
1664 $name::max_value().checked_div(&0.saturating_sub(2).into())
1665 );
1666 assert_eq!(
1667 b.checked_mul(&$name::min_value()),
1668 $name::min_value().checked_div(&0.saturating_sub(2).into())
1669 );
1670 assert_eq!(c.checked_mul(&$name::min_value()), None);
1671 }
1672
1673 let a = $name::saturating_from_rational(1, 2);
1674 let c = $name::saturating_from_integer(255);
1675
1676 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1677 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1678 assert_eq!(c.checked_mul(&$name::max_value()), None);
1679 assert_eq!(
1680 a.checked_mul(&$name::max_value()),
1681 $name::max_value().checked_div(&2.into())
1682 );
1683 assert_eq!(
1684 a.checked_mul(&$name::min_value()),
1685 $name::min_value().checked_div(&2.into())
1686 );
1687 }
1688
1689 #[test]
1690 fn const_checked_mul_works() {
1691 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1692 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1693
1694 let a = $name::saturating_from_integer(2u32);
1695
1696 let b = $name::from_inner(inner_max - 1);
1698 assert_eq!(a.const_checked_mul((b / 2.into())), Some(b));
1699
1700 let c = $name::from_inner(inner_max);
1702 assert_eq!(a.const_checked_mul((c / 2.into())), Some(b));
1703
1704 let e = $name::from_inner(1);
1706 assert_eq!(a.const_checked_mul((c / 2.into() + e)), None);
1707
1708 if $name::SIGNED {
1709 let b = $name::from_inner(inner_min + 1) / 2.into();
1711 let c = $name::from_inner(inner_min + 2);
1712 assert_eq!(a.const_checked_mul(b), Some(c));
1713
1714 let b = $name::from_inner(inner_min) / 2.into();
1716 let c = $name::from_inner(inner_min);
1717 assert_eq!(a.const_checked_mul(b), Some(c));
1718
1719 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1721 assert_eq!(a.const_checked_mul(b), None);
1722
1723 let b = $name::saturating_from_rational(1i32, -2i32);
1724 let c = $name::saturating_from_integer(-21i32);
1725 let d = $name::saturating_from_integer(42);
1726
1727 assert_eq!(b.const_checked_mul(d), Some(c));
1728
1729 let minus_two = $name::saturating_from_integer(-2i32);
1730 assert_eq!(
1731 b.const_checked_mul($name::max_value()),
1732 $name::max_value().const_checked_div(minus_two)
1733 );
1734 assert_eq!(
1735 b.const_checked_mul($name::min_value()),
1736 $name::min_value().const_checked_div(minus_two)
1737 );
1738
1739 let c = $name::saturating_from_integer(255u32);
1740 assert_eq!(c.const_checked_mul($name::min_value()), None);
1741 }
1742
1743 let a = $name::saturating_from_rational(1i32, 2i32);
1744 let c = $name::saturating_from_integer(255i32);
1745
1746 assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1747 assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1748 assert_eq!(c.const_checked_mul($name::max_value()), None);
1749 assert_eq!(
1750 a.const_checked_mul($name::max_value()),
1751 $name::max_value().checked_div(&2.into())
1752 );
1753 assert_eq!(
1754 a.const_checked_mul($name::min_value()),
1755 $name::min_value().const_checked_div($name::saturating_from_integer(2))
1756 );
1757 }
1758
1759 #[test]
1760 fn checked_div_int_works() {
1761 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1762 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1763 let accuracy = $name::accuracy();
1764
1765 let a = $name::from_inner(inner_max);
1766 let b = $name::from_inner(inner_min);
1767 let c = $name::zero();
1768 let d = $name::one();
1769 let e = $name::saturating_from_integer(6);
1770 let f = $name::saturating_from_integer(5);
1771
1772 assert_eq!(e.checked_div_int(2.into()), Some(3));
1773 assert_eq!(f.checked_div_int(2.into()), Some(2));
1774
1775 assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1776 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1777 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1778 assert_eq!(a.checked_div_int(1i8), None);
1779
1780 if b < c {
1781 assert_eq!(
1783 a.checked_div_int(0.saturating_sub(2)),
1784 Some(0.saturating_sub(inner_max / (2 * accuracy)))
1785 );
1786 assert_eq!(
1787 a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1788 Some(0.saturating_sub(1))
1789 );
1790 assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1791 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1792 assert_eq!(b.checked_div_int(1i8), None);
1793 assert_eq!(
1794 b.checked_div_int(0.saturating_sub(2)),
1795 Some(0.saturating_sub(inner_min / (2 * accuracy)))
1796 );
1797 assert_eq!(
1798 b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1799 Some(0.saturating_sub(1))
1800 );
1801 assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1802 assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1803 }
1804
1805 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1806
1807 assert_eq!(c.checked_div_int(1), Some(0));
1808 assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1809 assert_eq!(c.checked_div_int(1i8), Some(0));
1810
1811 assert_eq!(d.checked_div_int(1), Some(1));
1812 assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1813 assert_eq!(d.checked_div_int(1i8), Some(1));
1814
1815 assert_eq!(a.checked_div_int(0), None);
1816 assert_eq!(b.checked_div_int(0), None);
1817 assert_eq!(c.checked_div_int(0), None);
1818 assert_eq!(d.checked_div_int(0), None);
1819 }
1820
1821 #[test]
1822 #[should_panic(expected = "attempt to divide by zero")]
1823 fn saturating_div_int_panics_when_divisor_is_zero() {
1824 let _ = $name::one().saturating_div_int(0);
1825 }
1826
1827 #[test]
1828 fn saturating_div_int_works() {
1829 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1830 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1831 let accuracy = $name::accuracy();
1832
1833 let a = $name::saturating_from_integer(5);
1834 assert_eq!(a.saturating_div_int(2), 2);
1835
1836 let a = $name::min_value();
1837 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1838
1839 if $name::SIGNED {
1840 let a = $name::saturating_from_integer(5);
1841 assert_eq!(a.saturating_div_int(-2), -2);
1842
1843 let a = $name::min_value();
1844 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1845 }
1846 }
1847
1848 #[test]
1849 fn saturating_abs_works() {
1850 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1851 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1852
1853 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1854 assert_eq!($name::zero().saturating_abs(), 0.into());
1855
1856 if $name::SIGNED {
1857 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1858 assert_eq!(
1859 $name::saturating_from_rational(-1, 2).saturating_abs(),
1860 (1, 2).into()
1861 );
1862 }
1863 }
1864
1865 #[test]
1866 fn saturating_mul_acc_int_works() {
1867 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1868 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1869
1870 assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1871 assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1872
1873 assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1874 assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1875
1876 if $name::SIGNED {
1877 let a = $name::saturating_from_rational(-1, 2);
1878 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1879 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1880 assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1881 }
1882 }
1883
1884 #[test]
1885 fn saturating_pow_should_work() {
1886 assert_eq!(
1887 $name::saturating_from_integer(2).saturating_pow(0),
1888 $name::saturating_from_integer(1)
1889 );
1890 assert_eq!(
1891 $name::saturating_from_integer(2).saturating_pow(1),
1892 $name::saturating_from_integer(2)
1893 );
1894 assert_eq!(
1895 $name::saturating_from_integer(2).saturating_pow(2),
1896 $name::saturating_from_integer(4)
1897 );
1898 assert_eq!(
1899 $name::saturating_from_integer(2).saturating_pow(3),
1900 $name::saturating_from_integer(8)
1901 );
1902 assert_eq!(
1903 $name::saturating_from_integer(2).saturating_pow(50),
1904 $name::saturating_from_integer(1125899906842624i64)
1905 );
1906
1907 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
1908 assert_eq!(
1909 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1910 (1).into()
1911 );
1912
1913 if $name::SIGNED {
1914 assert_eq!(
1916 $name::saturating_from_integer(2).saturating_pow(68),
1917 $name::max_value()
1918 );
1919
1920 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
1921 assert_eq!(
1922 $name::saturating_from_integer(-1).saturating_pow(1001),
1923 0.saturating_sub(1).into()
1924 );
1925 assert_eq!(
1926 $name::saturating_from_integer(-1).saturating_pow(usize::MAX),
1927 0.saturating_sub(1).into()
1928 );
1929 assert_eq!(
1930 $name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
1931 (1).into()
1932 );
1933 }
1934
1935 assert_eq!(
1936 $name::saturating_from_integer(114209).saturating_pow(5),
1937 $name::max_value()
1938 );
1939
1940 assert_eq!(
1941 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1942 (1).into()
1943 );
1944 assert_eq!(
1945 $name::saturating_from_integer(0).saturating_pow(usize::MAX),
1946 (0).into()
1947 );
1948 assert_eq!(
1949 $name::saturating_from_integer(2).saturating_pow(usize::MAX),
1950 $name::max_value()
1951 );
1952 }
1953
1954 #[test]
1955 fn checked_div_works() {
1956 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1957 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1958
1959 let a = $name::from_inner(inner_max);
1960 let b = $name::from_inner(inner_min);
1961 let c = $name::zero();
1962 let d = $name::one();
1963 let e = $name::saturating_from_integer(6);
1964 let f = $name::saturating_from_integer(5);
1965
1966 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
1967 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
1968
1969 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
1970 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
1971 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
1972 assert_eq!(a.checked_div(&d), Some(a));
1973
1974 if b < c {
1975 assert_eq!(
1977 a.checked_div(&0.saturating_sub(2).into()),
1978 Some($name::from_inner(0.saturating_sub(inner_max / 2)))
1979 );
1980 assert_eq!(
1981 a.checked_div(&-$name::max_value()),
1982 Some(0.saturating_sub(1).into())
1983 );
1984 assert_eq!(
1985 b.checked_div(&0.saturating_sub(2).into()),
1986 Some($name::from_inner(0.saturating_sub(inner_min / 2)))
1987 );
1988 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
1989 assert_eq!(b.checked_div(&b), Some($name::one()));
1990 }
1991
1992 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
1993 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
1994 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
1995 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
1996
1997 assert_eq!(a.checked_div(&$name::one()), Some(a));
1998 assert_eq!(b.checked_div(&$name::one()), Some(b));
1999 assert_eq!(c.checked_div(&$name::one()), Some(c));
2000 assert_eq!(d.checked_div(&$name::one()), Some(d));
2001
2002 assert_eq!(a.checked_div(&$name::zero()), None);
2003 assert_eq!(b.checked_div(&$name::zero()), None);
2004 assert_eq!(c.checked_div(&$name::zero()), None);
2005 assert_eq!(d.checked_div(&$name::zero()), None);
2006 }
2007
2008 #[test]
2009 fn is_positive_negative_works() {
2010 let one = $name::one();
2011 assert!(one.is_positive());
2012 assert!(!one.is_negative());
2013
2014 let zero = $name::zero();
2015 assert!(!zero.is_positive());
2016 assert!(!zero.is_negative());
2017
2018 if $signed {
2019 let minus_one = $name::saturating_from_integer(-1);
2020 assert!(minus_one.is_negative());
2021 assert!(!minus_one.is_positive());
2022 }
2023 }
2024
2025 #[test]
2026 fn trunc_works() {
2027 let n = $name::saturating_from_rational(5, 2).trunc();
2028 assert_eq!(n, $name::saturating_from_integer(2));
2029
2030 if $name::SIGNED {
2031 let n = $name::saturating_from_rational(-5, 2).trunc();
2032 assert_eq!(n, $name::saturating_from_integer(-2));
2033 }
2034 }
2035
2036 #[test]
2037 fn frac_works() {
2038 let n = $name::saturating_from_rational(5, 2);
2039 let i = n.trunc();
2040 let f = n.frac();
2041
2042 assert_eq!(n, i + f);
2043
2044 let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2045 assert_eq!(n, 5.into());
2046
2047 let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2048 assert_eq!(n, 5.into());
2049
2050 if $name::SIGNED {
2051 let n = $name::saturating_from_rational(-5, 2);
2052 let i = n.trunc();
2053 let f = n.frac();
2054 assert_eq!(n, i - f);
2055
2056 let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2058 assert_eq!(n, 5.into());
2059
2060 let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2061 assert_eq!(n, 0.saturating_sub(5).into());
2062 }
2063 }
2064
2065 #[test]
2066 fn ceil_works() {
2067 let n = $name::saturating_from_rational(5, 2);
2068 assert_eq!(n.ceil(), 3.into());
2069
2070 let n = $name::saturating_from_rational(-5, 2);
2071 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2072
2073 let n = $name::max_value();
2075 assert_eq!(n.ceil(), n.trunc());
2076
2077 let n = $name::min_value();
2078 assert_eq!(n.ceil(), n.trunc());
2079 }
2080
2081 #[test]
2082 fn floor_works() {
2083 let n = $name::saturating_from_rational(5, 2);
2084 assert_eq!(n.floor(), 2.into());
2085
2086 let n = $name::saturating_from_rational(-5, 2);
2087 assert_eq!(n.floor(), 0.saturating_sub(3).into());
2088
2089 let n = $name::max_value();
2091 assert_eq!(n.floor(), n.trunc());
2092
2093 let n = $name::min_value();
2094 assert_eq!(n.floor(), n.trunc());
2095 }
2096
2097 #[test]
2098 fn round_works() {
2099 let n = $name::zero();
2100 assert_eq!(n.round(), n);
2101
2102 let n = $name::one();
2103 assert_eq!(n.round(), n);
2104
2105 let n = $name::saturating_from_rational(5, 2);
2106 assert_eq!(n.round(), 3.into());
2107
2108 let n = $name::saturating_from_rational(-5, 2);
2109 assert_eq!(n.round(), 0.saturating_sub(3).into());
2110
2111 let n = $name::max_value();
2113 assert_eq!(n.round(), n.trunc());
2114
2115 let n = $name::min_value();
2116 assert_eq!(n.round(), n.trunc());
2117
2118 let n = $name::max_value()
2122 .saturating_sub(1.into())
2123 .trunc()
2124 .saturating_add((1, 3).into());
2125
2126 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2127
2128 let n = $name::max_value()
2130 .saturating_sub(1.into())
2131 .trunc()
2132 .saturating_add((1, 2).into());
2133
2134 assert_eq!(n.round(), $name::max_value().trunc());
2135
2136 if $name::SIGNED {
2137 let n = $name::min_value()
2139 .saturating_add(1.into())
2140 .trunc()
2141 .saturating_sub((1, 3).into());
2142
2143 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2144
2145 let n = $name::min_value()
2147 .saturating_add(1.into())
2148 .trunc()
2149 .saturating_sub((1, 2).into());
2150
2151 assert_eq!(n.round(), $name::min_value().trunc());
2152 }
2153 }
2154
2155 #[test]
2156 fn perthing_into_works() {
2157 let ten_percent_percent: $name = Percent::from_percent(10).into();
2158 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2159
2160 let ten_percent_permill: $name = Permill::from_percent(10).into();
2161 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2162
2163 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2164 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2165
2166 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2167 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2168 }
2169
2170 #[test]
2171 fn fmt_should_work() {
2172 let zero = $name::zero();
2173 assert_eq!(
2174 format!("{:?}", zero),
2175 format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2176 );
2177
2178 let one = $name::one();
2179 assert_eq!(
2180 format!("{:?}", one),
2181 format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2182 );
2183
2184 let frac = $name::saturating_from_rational(1, 2);
2185 assert_eq!(
2186 format!("{:?}", frac),
2187 format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2188 );
2189
2190 let frac = $name::saturating_from_rational(5, 2);
2191 assert_eq!(
2192 format!("{:?}", frac),
2193 format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2194 );
2195
2196 let frac = $name::saturating_from_rational(314, 100);
2197 assert_eq!(
2198 format!("{:?}", frac),
2199 format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2200 );
2201
2202 if $name::SIGNED {
2203 let neg = -$name::one();
2204 assert_eq!(
2205 format!("{:?}", neg),
2206 format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2207 );
2208
2209 let frac = $name::saturating_from_rational(-314, 100);
2210 assert_eq!(
2211 format!("{:?}", frac),
2212 format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2213 );
2214 }
2215 }
2216 }
2217 };
2218}
2219
2220implement_fixed!(
2221 FixedI64,
2222 test_fixed_i64,
2223 i64,
2224 true,
2225 1_000_000_000,
2226 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2227);
2228
2229implement_fixed!(
2230 FixedU64,
2231 test_fixed_u64,
2232 u64,
2233 false,
2234 1_000_000_000,
2235 "_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2236);
2237
2238implement_fixed!(
2239 FixedI128,
2240 test_fixed_i128,
2241 i128,
2242 true,
2243 1_000_000_000_000_000_000,
2244 "_Fixed Point 128 bits signed, range = \
2245 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2246);
2247
2248implement_fixed!(
2249 FixedU128,
2250 test_fixed_u128,
2251 u128,
2252 false,
2253 1_000_000_000_000_000_000,
2254 "_Fixed Point 128 bits unsigned, range = \
2255 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
2256);