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