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, 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 CompactAs,
408 Default,
409 Copy,
410 Clone,
411 codec::MaxEncodedLen,
412 PartialEq,
413 Eq,
414 PartialOrd,
415 Ord,
416 scale_info::TypeInfo,
417 )]
418 pub struct $name($inner_type);
419
420 impl From<$inner_type> for $name {
421 fn from(int: $inner_type) -> Self {
422 $name::saturating_from_integer(int)
423 }
424 }
425
426 impl<N: FixedPointOperand, D: FixedPointOperand> From<(N, D)> for $name {
427 fn from(r: (N, D)) -> Self {
428 $name::saturating_from_rational(r.0, r.1)
429 }
430 }
431
432 impl FixedPointNumber for $name {
433 type Inner = $inner_type;
434
435 const DIV: Self::Inner = $div;
436 const SIGNED: bool = $signed;
437
438 fn from_inner(inner: Self::Inner) -> Self {
439 Self(inner)
440 }
441
442 fn into_inner(self) -> Self::Inner {
443 self.0
444 }
445 }
446
447 impl $name {
448 pub const fn from_inner(inner: $inner_type) -> Self {
452 Self(inner)
453 }
454
455 pub const fn into_inner(self) -> $inner_type {
459 self.0
460 }
461
462 pub const fn from_u32(n: u32) -> Self {
467 Self::from_inner((n as $inner_type) * $div)
468 }
469
470 #[cfg(any(feature = "std", test))]
472 pub fn from_float(x: f64) -> Self {
473 Self((x * (<Self as FixedPointNumber>::DIV as f64)) as $inner_type)
474 }
475
476 pub const fn from_perbill(n: Perbill) -> Self {
478 Self::from_rational(n.deconstruct() as u128, 1_000_000_000)
479 }
480
481 pub const fn into_perbill(self) -> Perbill {
483 if self.0 <= 0 {
484 Perbill::zero()
485 } else if self.0 >= $div {
486 Perbill::one()
487 } else {
488 match multiply_by_rational_with_rounding(
489 self.0 as u128,
490 1_000_000_000,
491 Self::DIV as u128,
492 Rounding::NearestPrefDown,
493 ) {
494 Some(value) => {
495 if value > (u32::max_value() as u128) {
496 panic!(
497 "prior logic ensures 0<self.0<DIV; \
498 multiply ensures 0<self.0<1000000000; \
499 qed"
500 );
501 }
502 Perbill::from_parts(value as u32)
503 },
504 None => Perbill::zero(),
505 }
506 }
507 }
508
509 #[cfg(any(feature = "std", test))]
511 pub fn to_float(self) -> f64 {
512 self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
513 }
514
515 pub fn try_into_perthing<P: PerThing>(self) -> Result<P, P> {
519 if self < Self::zero() {
520 Err(P::zero())
521 } else if self > Self::one() {
522 Err(P::one())
523 } else {
524 Ok(P::from_rational(self.0 as u128, $div))
525 }
526 }
527
528 pub fn into_clamped_perthing<P: PerThing>(self) -> P {
531 if self < Self::zero() {
532 P::zero()
533 } else if self > Self::one() {
534 P::one()
535 } else {
536 P::from_rational(self.0 as u128, $div)
537 }
538 }
539
540 pub const fn neg(self) -> Self {
545 Self(0 - self.0)
546 }
547
548 pub const fn sqrt(self) -> Self {
553 match self.try_sqrt() {
554 Some(v) => v,
555 None => panic!("sqrt overflow or negative input"),
556 }
557 }
558
559 pub const fn try_sqrt(self) -> Option<Self> {
562 if self.0 == 0 {
563 return Some(Self(0))
564 }
565 if self.0 < 1 {
566 return None
567 }
568 let v = self.0 as u128;
569
570 let maybe_vd = u128::checked_mul(v, $div);
580 let r = if let Some(vd) = maybe_vd { sqrt(vd) } else { sqrt(v) * sqrt($div) };
581 Some(Self(r as $inner_type))
582 }
583
584 pub const fn add(self, rhs: Self) -> Self {
589 Self(self.0 + rhs.0)
590 }
591
592 pub const fn sub(self, rhs: Self) -> Self {
597 Self(self.0 - rhs.0)
598 }
599
600 pub const fn mul(self, rhs: Self) -> Self {
608 match $name::const_checked_mul(self, rhs) {
609 Some(v) => v,
610 None => panic!("attempt to multiply with overflow"),
611 }
612 }
613
614 pub const fn div(self, rhs: Self) -> Self {
622 match $name::const_checked_div(self, rhs) {
623 Some(v) => v,
624 None => panic!("attempt to divide with overflow or NaN"),
625 }
626 }
627
628 const fn into_i129(self) -> I129 {
633 #[allow(unused_comparisons)]
634 if self.0 < 0 {
635 let value = match self.0.checked_neg() {
636 Some(n) => n as u128,
637 None => u128::saturating_add(<$inner_type>::max_value() as u128, 1),
638 };
639 I129 { value, negative: true }
640 } else {
641 I129 { value: self.0 as u128, negative: false }
642 }
643 }
644
645 const fn from_i129(n: I129) -> Option<Self> {
650 let max_plus_one = u128::saturating_add(<$inner_type>::max_value() as u128, 1);
651 #[allow(unused_comparisons)]
652 let inner = if n.negative && <$inner_type>::min_value() < 0 && n.value == max_plus_one {
653 <$inner_type>::min_value()
654 } else {
655 let unsigned_inner = n.value as $inner_type;
656 if unsigned_inner as u128 != n.value || (unsigned_inner > 0) != (n.value > 0) {
657 return None
658 };
659 if n.negative {
660 match unsigned_inner.checked_neg() {
661 Some(v) => v,
662 None => return None,
663 }
664 } else {
665 unsigned_inner
666 }
667 };
668 Some(Self(inner))
669 }
670
671 pub const fn from_rational(a: u128, b: u128) -> Self {
679 Self::from_rational_with_rounding(a, b, Rounding::NearestPrefDown)
680 }
681
682 pub const fn from_rational_with_rounding(a: u128, b: u128, rounding: Rounding) -> Self {
687 if b == 0 {
688 panic!("attempt to divide by zero in from_rational")
689 }
690 match multiply_by_rational_with_rounding(Self::DIV as u128, a, b, rounding) {
691 Some(value) => match Self::from_i129(I129 { value, negative: false }) {
692 Some(x) => x,
693 None => panic!("overflow in from_rational"),
694 },
695 None => panic!("overflow in from_rational"),
696 }
697 }
698
699 pub const fn const_checked_mul(self, other: Self) -> Option<Self> {
704 self.const_checked_mul_with_rounding(other, SignedRounding::NearestPrefLow)
705 }
706
707 pub const fn const_checked_mul_with_rounding(
713 self,
714 other: Self,
715 rounding: SignedRounding,
716 ) -> Option<Self> {
717 let lhs = self.into_i129();
718 let rhs = other.into_i129();
719 let negative = lhs.negative != rhs.negative;
720
721 match multiply_by_rational_with_rounding(
722 lhs.value,
723 rhs.value,
724 Self::DIV as u128,
725 Rounding::from_signed(rounding, negative),
726 ) {
727 Some(value) => Self::from_i129(I129 { value, negative }),
728 None => None,
729 }
730 }
731
732 pub const fn const_checked_div(self, other: Self) -> Option<Self> {
737 self.checked_rounding_div(other, SignedRounding::NearestPrefLow)
738 }
739
740 pub const fn checked_rounding_div(
746 self,
747 other: Self,
748 rounding: SignedRounding,
749 ) -> Option<Self> {
750 if other.0 == 0 {
751 return None
752 }
753
754 let lhs = self.into_i129();
755 let rhs = other.into_i129();
756 let negative = lhs.negative != rhs.negative;
757
758 match multiply_by_rational_with_rounding(
759 lhs.value,
760 Self::DIV as u128,
761 rhs.value,
762 Rounding::from_signed(rounding, negative),
763 ) {
764 Some(value) => Self::from_i129(I129 { value, negative }),
765 None => None,
766 }
767 }
768 }
769
770 impl Saturating for $name {
771 fn saturating_add(self, rhs: Self) -> Self {
772 Self(self.0.saturating_add(rhs.0))
773 }
774
775 fn saturating_sub(self, rhs: Self) -> Self {
776 Self(self.0.saturating_sub(rhs.0))
777 }
778
779 fn saturating_mul(self, rhs: Self) -> Self {
780 self.checked_mul(&rhs).unwrap_or_else(|| to_bound(self.0, rhs.0))
781 }
782
783 fn saturating_pow(self, exp: usize) -> Self {
784 if exp == 0 {
785 return Self::saturating_from_integer(1)
786 }
787
788 let exp = exp as u32;
789 let msb_pos = 32 - exp.leading_zeros();
790
791 let mut result = Self::saturating_from_integer(1);
792 let mut pow_val = self;
793 for i in 0..msb_pos {
794 if ((1 << i) & exp) > 0 {
795 result = result.saturating_mul(pow_val);
796 }
797 pow_val = pow_val.saturating_mul(pow_val);
798 }
799 result
800 }
801 }
802
803 impl ops::Neg for $name {
804 type Output = Self;
805
806 fn neg(self) -> Self::Output {
807 Self(<Self as FixedPointNumber>::Inner::zero() - self.0)
808 }
809 }
810
811 impl ops::Add for $name {
812 type Output = Self;
813
814 fn add(self, rhs: Self) -> Self::Output {
815 Self(self.0 + rhs.0)
816 }
817 }
818
819 impl ops::Sub for $name {
820 type Output = Self;
821
822 fn sub(self, rhs: Self) -> Self::Output {
823 Self(self.0 - rhs.0)
824 }
825 }
826
827 impl ops::Mul for $name {
828 type Output = Self;
829
830 fn mul(self, rhs: Self) -> Self::Output {
831 self.checked_mul(&rhs)
832 .unwrap_or_else(|| panic!("attempt to multiply with overflow"))
833 }
834 }
835
836 impl ops::Div for $name {
837 type Output = Self;
838
839 fn div(self, rhs: Self) -> Self::Output {
840 if rhs.0 == 0 {
841 panic!("attempt to divide by zero")
842 }
843 self.checked_div(&rhs)
844 .unwrap_or_else(|| panic!("attempt to divide with overflow"))
845 }
846 }
847
848 impl CheckedSub for $name {
849 fn checked_sub(&self, rhs: &Self) -> Option<Self> {
850 self.0.checked_sub(rhs.0).map(Self)
851 }
852 }
853
854 impl CheckedAdd for $name {
855 fn checked_add(&self, rhs: &Self) -> Option<Self> {
856 self.0.checked_add(rhs.0).map(Self)
857 }
858 }
859
860 impl CheckedDiv for $name {
861 fn checked_div(&self, other: &Self) -> Option<Self> {
862 if other.0 == 0 {
863 return None
864 }
865
866 let lhs: I129 = self.0.into();
867 let rhs: I129 = other.0.into();
868 let negative = lhs.negative != rhs.negative;
869
870 multiply_by_rational_with_rounding(
875 lhs.value,
876 Self::DIV as u128,
877 rhs.value,
878 Rounding::from_signed(SignedRounding::Minor, negative),
879 )
880 .and_then(|value| from_i129(I129 { value, negative }))
881 .map(Self)
882 }
883 }
884
885 impl CheckedMul for $name {
886 fn checked_mul(&self, other: &Self) -> Option<Self> {
887 let lhs: I129 = self.0.into();
888 let rhs: I129 = other.0.into();
889 let negative = lhs.negative != rhs.negative;
890
891 multiply_by_rational_with_rounding(
892 lhs.value,
893 rhs.value,
894 Self::DIV as u128,
895 Rounding::from_signed(SignedRounding::Minor, negative),
896 )
897 .and_then(|value| from_i129(I129 { value, negative }))
898 .map(Self)
899 }
900 }
901
902 impl Bounded for $name {
903 fn min_value() -> Self {
904 Self(<Self as FixedPointNumber>::Inner::min_value())
905 }
906
907 fn max_value() -> Self {
908 Self(<Self as FixedPointNumber>::Inner::max_value())
909 }
910 }
911
912 impl Zero for $name {
913 fn zero() -> Self {
914 Self::from_inner(<Self as FixedPointNumber>::Inner::zero())
915 }
916
917 fn is_zero(&self) -> bool {
918 self.into_inner() == <Self as FixedPointNumber>::Inner::zero()
919 }
920 }
921
922 impl One for $name {
923 fn one() -> Self {
924 Self::from_inner(Self::DIV)
925 }
926 }
927
928 impl ::core::fmt::Debug for $name {
929 #[cfg(feature = "std")]
930 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
931 let integral = {
932 let int = self.0 / Self::accuracy();
933 let signum_for_zero = if int == 0 && self.is_negative() { "-" } else { "" };
934 format!("{}{}", signum_for_zero, int)
935 };
936 let precision = (Self::accuracy() as f64).log10() as usize;
937 let fractional = format!(
938 "{:0>weight$}",
939 ((self.0 % Self::accuracy()) as i128).abs(),
940 weight = precision
941 );
942 write!(f, "{}({}.{})", stringify!($name), integral, fractional)
943 }
944
945 #[cfg(not(feature = "std"))]
946 fn fmt(&self, _: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
947 Ok(())
948 }
949 }
950
951 impl<P: PerThing> From<P> for $name
952 where
953 P::Inner: FixedPointOperand,
954 {
955 fn from(p: P) -> Self {
956 let accuracy = P::ACCURACY;
957 let value = p.deconstruct();
958 $name::saturating_from_rational(value, accuracy)
959 }
960 }
961
962 impl ::core::fmt::Display for $name {
963 fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
964 write!(f, "{}", self.0)
965 }
966 }
967
968 impl ::core::str::FromStr for $name {
969 type Err = &'static str;
970
971 fn from_str(s: &str) -> Result<Self, Self::Err> {
972 let inner: <Self as FixedPointNumber>::Inner =
973 s.parse().map_err(|_| "invalid string input for fixed point number")?;
974 Ok(Self::from_inner(inner))
975 }
976 }
977
978 #[cfg(feature = "serde")]
981 impl Serialize for $name {
982 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
983 where
984 S: Serializer,
985 {
986 serializer.serialize_str(&self.to_string())
987 }
988 }
989
990 #[cfg(feature = "serde")]
993 impl<'de> Deserialize<'de> for $name {
994 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
995 where
996 D: Deserializer<'de>,
997 {
998 use ::core::str::FromStr;
999 let s = String::deserialize(deserializer)?;
1000 $name::from_str(&s).map_err(de::Error::custom)
1001 }
1002 }
1003
1004 #[cfg(test)]
1005 mod $test_mod {
1006 use super::*;
1007 use crate::{Perbill, Percent, Permill, Perquintill};
1008
1009 fn max() -> $name {
1010 $name::max_value()
1011 }
1012
1013 fn min() -> $name {
1014 $name::min_value()
1015 }
1016
1017 fn precision() -> usize {
1018 ($name::accuracy() as f64).log10() as usize
1019 }
1020
1021 #[test]
1022 fn macro_preconditions() {
1023 assert!($name::DIV > 0);
1024 }
1025
1026 #[test]
1027 fn has_max_encoded_len() {
1028 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1029 _data: T,
1030 }
1031
1032 let _ = AsMaxEncodedLen { _data: $name::min_value() };
1033 }
1034
1035 #[test]
1036 fn from_i129_works() {
1037 let a = I129 { value: 1, negative: true };
1038
1039 assert_eq!(from_i129::<u128>(a), None);
1041
1042 let a = I129 { value: u128::MAX - 1, negative: false };
1043
1044 assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
1046
1047 let a = I129 { value: u128::MAX, negative: false };
1048
1049 assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
1051
1052 let a = I129 { value: i128::MAX as u128 + 1, negative: true };
1053
1054 assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
1056
1057 let a = I129 { value: i128::MAX as u128 + 1, negative: false };
1058
1059 assert_eq!(from_i129::<i128>(a), None);
1061
1062 let a = I129 { value: i128::MAX as u128, negative: false };
1063
1064 assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
1066 }
1067
1068 #[test]
1069 fn to_bound_works() {
1070 let a = 1i32;
1071 let b = 1i32;
1072
1073 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1075
1076 let a = -1i32;
1077 let b = -1i32;
1078
1079 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MAX);
1081
1082 let a = 1i32;
1083 let b = -1i32;
1084
1085 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1087
1088 let a = -1i32;
1089 let b = 1i32;
1090
1091 assert_eq!(to_bound::<_, _, i32>(a, b), i32::MIN);
1093
1094 let a = 1i32;
1095 let b = -1i32;
1096
1097 assert_eq!(to_bound::<_, _, u32>(a, b), 0);
1099 }
1100
1101 #[test]
1102 fn op_neg_works() {
1103 let a = $name::zero();
1104 let b = -a;
1105
1106 assert_eq!(a, b);
1108
1109 if $name::SIGNED {
1110 let a = $name::saturating_from_integer(5);
1111 let b = -a;
1112
1113 assert_eq!($name::saturating_from_integer(-5), b);
1115
1116 let a = $name::saturating_from_integer(-5);
1117 let b = -a;
1118
1119 assert_eq!($name::saturating_from_integer(5), b);
1121
1122 let a = $name::max_value();
1123 let b = -a;
1124
1125 assert_eq!($name::min_value() + $name::from_inner(1), b);
1127
1128 let a = $name::min_value() + $name::from_inner(1);
1129 let b = -a;
1130
1131 assert_eq!($name::max_value(), b);
1133 }
1134 }
1135
1136 #[test]
1137 fn op_checked_add_overflow_works() {
1138 let a = $name::max_value();
1139 let b = 1.into();
1140 assert!(a.checked_add(&b).is_none());
1141 }
1142
1143 #[test]
1144 fn op_add_works() {
1145 let a = $name::saturating_from_rational(5, 2);
1146 let b = $name::saturating_from_rational(1, 2);
1147
1148 assert_eq!($name::saturating_from_integer(3), a + b);
1150
1151 if $name::SIGNED {
1152 let b = $name::saturating_from_rational(1, -2);
1154 assert_eq!($name::saturating_from_integer(2), a + b);
1155 }
1156 }
1157
1158 #[test]
1159 fn op_checked_sub_underflow_works() {
1160 let a = $name::min_value();
1161 let b = 1.into();
1162 assert!(a.checked_sub(&b).is_none());
1163 }
1164
1165 #[test]
1166 fn op_sub_works() {
1167 let a = $name::saturating_from_rational(5, 2);
1168 let b = $name::saturating_from_rational(1, 2);
1169
1170 assert_eq!($name::saturating_from_integer(2), a - b);
1171 assert_eq!($name::saturating_from_integer(-2), b.saturating_sub(a));
1172 }
1173
1174 #[test]
1175 fn op_checked_mul_overflow_works() {
1176 let a = $name::max_value();
1177 let b = 2.into();
1178 assert!(a.checked_mul(&b).is_none());
1179 }
1180
1181 #[test]
1182 fn op_mul_works() {
1183 let a = $name::saturating_from_integer(42);
1184 let b = $name::saturating_from_integer(2);
1185 assert_eq!($name::saturating_from_integer(84), a * b);
1186
1187 let a = $name::saturating_from_integer(42);
1188 let b = $name::saturating_from_integer(-2);
1189 assert_eq!($name::saturating_from_integer(-84), a * b);
1190 }
1191
1192 #[test]
1193 #[should_panic(expected = "attempt to divide by zero")]
1194 fn op_div_panics_on_zero_divisor() {
1195 let a = $name::saturating_from_integer(1);
1196 let b = 0.into();
1197 let _c = a / b;
1198 }
1199
1200 #[test]
1201 fn op_checked_div_overflow_works() {
1202 if $name::SIGNED {
1203 let a = $name::min_value();
1204 let b = $name::zero().saturating_sub($name::one());
1205 assert!(a.checked_div(&b).is_none());
1206 }
1207 }
1208
1209 #[test]
1210 fn op_sqrt_works() {
1211 for i in 1..1_000i64 {
1212 let x = $name::saturating_from_rational(i, 1_000i64);
1213 assert_eq!((x * x).try_sqrt(), Some(x));
1214 let x = $name::saturating_from_rational(i, 1i64);
1215 assert_eq!((x * x).try_sqrt(), Some(x));
1216 }
1217 }
1218
1219 #[test]
1220 fn op_div_works() {
1221 let a = $name::saturating_from_integer(42);
1222 let b = $name::saturating_from_integer(2);
1223 assert_eq!($name::saturating_from_integer(21), a / b);
1224
1225 if $name::SIGNED {
1226 let a = $name::saturating_from_integer(42);
1227 let b = $name::saturating_from_integer(-2);
1228 assert_eq!($name::saturating_from_integer(-21), a / b);
1229 }
1230 }
1231
1232 #[test]
1233 fn saturating_from_integer_works() {
1234 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1235 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1236 let accuracy = $name::accuracy();
1237
1238 let a = $name::saturating_from_integer(42);
1240 assert_eq!(a.into_inner(), 42 * accuracy);
1241
1242 let a = $name::saturating_from_integer(-42);
1243 assert_eq!(a.into_inner(), 0.saturating_sub(42 * accuracy));
1244
1245 let a = $name::saturating_from_integer(inner_max / accuracy);
1247 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1248
1249 let a = $name::saturating_from_integer(inner_min / accuracy);
1250 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1251
1252 let a = $name::saturating_from_integer(inner_max / accuracy + 1);
1254 assert_eq!(a.into_inner(), inner_max);
1255
1256 let a = $name::saturating_from_integer((inner_min / accuracy).saturating_sub(1));
1257 assert_eq!(a.into_inner(), inner_min);
1258 }
1259
1260 #[test]
1261 fn checked_from_integer_works() {
1262 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1263 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1264 let accuracy = $name::accuracy();
1265
1266 let a = $name::checked_from_integer::<$inner_type>(42)
1268 .expect("42 * accuracy <= inner_max; qed");
1269 assert_eq!(a.into_inner(), 42 * accuracy);
1270
1271 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy)
1273 .expect("(inner_max / accuracy) * accuracy <= inner_max; qed");
1274 assert_eq!(a.into_inner(), (inner_max / accuracy) * accuracy);
1275
1276 let a = $name::checked_from_integer::<$inner_type>(inner_max / accuracy + 1);
1278 assert_eq!(a, None);
1279
1280 if $name::SIGNED {
1281 let a = $name::checked_from_integer::<$inner_type>(0.saturating_sub(42))
1283 .expect("-42 * accuracy >= inner_min; qed");
1284 assert_eq!(a.into_inner(), 0 - 42 * accuracy);
1285
1286 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy)
1288 .expect("(inner_min / accuracy) * accuracy <= inner_min; qed");
1289 assert_eq!(a.into_inner(), (inner_min / accuracy) * accuracy);
1290
1291 let a = $name::checked_from_integer::<$inner_type>(inner_min / accuracy - 1);
1293 assert_eq!(a, None);
1294 }
1295 }
1296
1297 #[test]
1298 fn from_inner_works() {
1299 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1300 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1301
1302 assert_eq!(max(), $name::from_inner(inner_max));
1303 assert_eq!(min(), $name::from_inner(inner_min));
1304 }
1305
1306 #[test]
1307 #[should_panic(expected = "attempt to divide by zero")]
1308 fn saturating_from_rational_panics_on_zero_divisor() {
1309 let _ = $name::saturating_from_rational(1, 0);
1310 }
1311
1312 #[test]
1313 fn saturating_from_rational_works() {
1314 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1315 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1316 let accuracy = $name::accuracy();
1317
1318 let a = $name::saturating_from_rational(5, 2);
1319
1320 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1322
1323 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1325 assert_eq!(a.into_inner(), inner_max - 1);
1326
1327 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1329 assert_eq!(a.into_inner(), inner_min + 1);
1330
1331 let a = $name::saturating_from_rational(inner_max, accuracy);
1333 assert_eq!(a.into_inner(), inner_max);
1334
1335 let a = $name::saturating_from_rational(inner_min, accuracy);
1337 assert_eq!(a.into_inner(), inner_min);
1338
1339 let a = $name::saturating_from_rational(0, 1);
1341 assert_eq!(a.into_inner(), 0);
1342
1343 if $name::SIGNED {
1344 let a = $name::saturating_from_rational(-5, 2);
1346 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1347
1348 let a = $name::saturating_from_rational(5, -2);
1350 assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
1351
1352 let a = $name::saturating_from_rational(-5, -2);
1354 assert_eq!(a.into_inner(), 25 * accuracy / 10);
1355
1356 let a = $name::saturating_from_rational(inner_max as u128 + 1, accuracy);
1358 assert_eq!(a.into_inner(), inner_max);
1359
1360 let a = $name::saturating_from_rational(inner_max as u128 + 2, 0 - accuracy);
1362 assert_eq!(a.into_inner(), inner_min);
1363
1364 let a = $name::saturating_from_rational(inner_max, 0 - accuracy);
1365 assert_eq!(a.into_inner(), 0 - inner_max);
1366
1367 let a = $name::saturating_from_rational(inner_min, 0 - accuracy);
1368 assert_eq!(a.into_inner(), inner_max);
1369
1370 let a = $name::saturating_from_rational(inner_min + 1, 0 - accuracy);
1371 assert_eq!(a.into_inner(), inner_max);
1372
1373 let a = $name::saturating_from_rational(inner_min, 0 - 1);
1374 assert_eq!(a.into_inner(), inner_max);
1375
1376 let a = $name::saturating_from_rational(inner_max, 0 - 1);
1377 assert_eq!(a.into_inner(), inner_min);
1378
1379 let a = $name::saturating_from_rational(inner_max, 0 - inner_max);
1380 assert_eq!(a.into_inner(), 0 - accuracy);
1381
1382 let a = $name::saturating_from_rational(0 - inner_max, inner_max);
1383 assert_eq!(a.into_inner(), 0 - accuracy);
1384
1385 let a = $name::saturating_from_rational(inner_max, 0 - 3 * accuracy);
1386 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1387
1388 let a = $name::saturating_from_rational(inner_min, 0 - accuracy / 3);
1389 assert_eq!(a.into_inner(), inner_max);
1390
1391 let a = $name::saturating_from_rational(1, 0 - accuracy);
1392 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1393
1394 let a = $name::saturating_from_rational(inner_min, inner_min);
1395 assert_eq!(a.into_inner(), accuracy);
1396
1397 let a = $name::saturating_from_rational(1, 0 - accuracy - 1);
1399 assert_eq!(a.into_inner(), 0);
1400 }
1401
1402 let a = $name::saturating_from_rational(inner_max - 1, accuracy);
1403 assert_eq!(a.into_inner(), inner_max - 1);
1404
1405 let a = $name::saturating_from_rational(inner_min + 1, accuracy);
1406 assert_eq!(a.into_inner(), inner_min + 1);
1407
1408 let a = $name::saturating_from_rational(inner_max, 1);
1409 assert_eq!(a.into_inner(), inner_max);
1410
1411 let a = $name::saturating_from_rational(inner_min, 1);
1412 assert_eq!(a.into_inner(), inner_min);
1413
1414 let a = $name::saturating_from_rational(inner_max, inner_max);
1415 assert_eq!(a.into_inner(), accuracy);
1416
1417 let a = $name::saturating_from_rational(inner_max, 3 * accuracy);
1418 assert_eq!(a.into_inner(), inner_max / 3);
1419
1420 let a = $name::saturating_from_rational(inner_min, 2 * accuracy);
1421 assert_eq!(a.into_inner(), inner_min / 2);
1422
1423 let a = $name::saturating_from_rational(inner_min, accuracy / 3);
1424 assert_eq!(a.into_inner(), inner_min);
1425
1426 let a = $name::saturating_from_rational(1, accuracy);
1427 assert_eq!(a.into_inner(), 1);
1428
1429 let a = $name::saturating_from_rational(1, accuracy + 1);
1431 assert_eq!(a.into_inner(), 0);
1432 }
1433
1434 #[test]
1435 fn checked_from_rational_works() {
1436 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1437 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1438 let accuracy = $name::accuracy();
1439
1440 let a = $name::checked_from_rational(1, 0);
1442 assert_eq!(a, None);
1443
1444 let a = $name::checked_from_rational(inner_max - 1, accuracy).unwrap();
1446 assert_eq!(a.into_inner(), inner_max - 1);
1447
1448 let a = $name::checked_from_rational(inner_min + 1, accuracy).unwrap();
1450 assert_eq!(a.into_inner(), inner_min + 1);
1451
1452 let a = $name::checked_from_rational(inner_max, accuracy).unwrap();
1454 assert_eq!(a.into_inner(), inner_max);
1455
1456 let a = $name::checked_from_rational(inner_min, accuracy).unwrap();
1458 assert_eq!(a.into_inner(), inner_min);
1459
1460 let a = $name::checked_from_rational(inner_min, 0.saturating_sub(accuracy));
1462 assert_eq!(a, None);
1463
1464 if $name::SIGNED {
1465 let a = $name::checked_from_rational(
1467 inner_max as u128 + 2,
1468 0.saturating_sub(accuracy),
1469 );
1470 assert_eq!(a, None);
1471
1472 let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
1473 assert_eq!(a.into_inner(), 0 - inner_max / 3);
1474
1475 let a = $name::checked_from_rational(inner_min, 0 - accuracy / 3);
1476 assert_eq!(a, None);
1477
1478 let a = $name::checked_from_rational(1, 0 - accuracy).unwrap();
1479 assert_eq!(a.into_inner(), 0.saturating_sub(1));
1480
1481 let a = $name::checked_from_rational(1, 0 - accuracy - 1).unwrap();
1482 assert_eq!(a.into_inner(), 0);
1483
1484 let a = $name::checked_from_rational(inner_min, accuracy / 3);
1485 assert_eq!(a, None);
1486 }
1487
1488 let a = $name::checked_from_rational(inner_max, 3 * accuracy).unwrap();
1489 assert_eq!(a.into_inner(), inner_max / 3);
1490
1491 let a = $name::checked_from_rational(inner_min, 2 * accuracy).unwrap();
1492 assert_eq!(a.into_inner(), inner_min / 2);
1493
1494 let a = $name::checked_from_rational(1, accuracy).unwrap();
1495 assert_eq!(a.into_inner(), 1);
1496
1497 let a = $name::checked_from_rational(1, accuracy + 1).unwrap();
1498 assert_eq!(a.into_inner(), 0);
1499 }
1500
1501 #[test]
1502 fn from_rational_works() {
1503 let inner_max: u128 = <$name as FixedPointNumber>::Inner::max_value() as u128;
1504 let inner_min: u128 = 0;
1505 let accuracy: u128 = $name::accuracy() as u128;
1506
1507 let a = $name::from_rational(inner_max - 1, accuracy);
1509 assert_eq!(a.into_inner() as u128, inner_max - 1);
1510
1511 let a = $name::from_rational(inner_min + 1, accuracy);
1513 assert_eq!(a.into_inner() as u128, inner_min + 1);
1514
1515 let a = $name::from_rational(inner_max, accuracy);
1517 assert_eq!(a.into_inner() as u128, inner_max);
1518
1519 let a = $name::from_rational(inner_min, accuracy);
1521 assert_eq!(a.into_inner() as u128, inner_min);
1522
1523 let a = $name::from_rational(inner_max, 3 * accuracy);
1524 assert_eq!(a.into_inner() as u128, inner_max / 3);
1525
1526 let a = $name::from_rational(1, accuracy);
1527 assert_eq!(a.into_inner() as u128, 1);
1528
1529 let a = $name::from_rational(1, accuracy + 1);
1530 assert_eq!(a.into_inner() as u128, 1);
1531
1532 let a = $name::from_rational_with_rounding(1, accuracy + 1, Rounding::Down);
1533 assert_eq!(a.into_inner() as u128, 0);
1534 }
1535
1536 #[test]
1537 fn checked_mul_int_works() {
1538 let a = $name::saturating_from_integer(2);
1539 assert_eq!(a.checked_mul_int((i128::MAX - 1) / 2), Some(i128::MAX - 1));
1541 assert_eq!(a.checked_mul_int(i128::MAX / 2), Some(i128::MAX - 1));
1543 assert_eq!(a.checked_mul_int(i128::MAX / 2 + 1), None);
1545
1546 if $name::SIGNED {
1547 assert_eq!(a.checked_mul_int((i128::MIN + 1) / 2), Some(i128::MIN + 2));
1549 assert_eq!(a.checked_mul_int(i128::MIN / 2), Some(i128::MIN));
1551 assert_eq!(a.checked_mul_int(i128::MIN / 2 - 1), None);
1553
1554 let b = $name::saturating_from_rational(1, -2);
1555 assert_eq!(b.checked_mul_int(42i128), Some(-21));
1556 assert_eq!(b.checked_mul_int(u128::MAX), None);
1557 assert_eq!(b.checked_mul_int(i128::MAX), Some(i128::MAX / -2));
1558 assert_eq!(b.checked_mul_int(i128::MIN), Some(i128::MIN / -2));
1559 }
1560
1561 let a = $name::saturating_from_rational(1, 2);
1562 assert_eq!(a.checked_mul_int(42i128), Some(21));
1563 assert_eq!(a.checked_mul_int(i128::MAX), Some(i128::MAX / 2));
1564 assert_eq!(a.checked_mul_int(i128::MIN), Some(i128::MIN / 2));
1565
1566 let c = $name::saturating_from_integer(255);
1567 assert_eq!(c.checked_mul_int(2i8), None);
1568 assert_eq!(c.checked_mul_int(2i128), Some(510));
1569 assert_eq!(c.checked_mul_int(i128::MAX), None);
1570 assert_eq!(c.checked_mul_int(i128::MIN), None);
1571 }
1572
1573 #[test]
1574 fn saturating_mul_int_works() {
1575 let a = $name::saturating_from_integer(2);
1576 assert_eq!(a.saturating_mul_int((i128::MAX - 1) / 2), i128::MAX - 1);
1578 assert_eq!(a.saturating_mul_int(i128::MAX / 2), i128::MAX - 1);
1580 assert_eq!(a.saturating_mul_int(i128::MAX / 2 + 1), i128::MAX);
1582
1583 assert_eq!(a.saturating_mul_int((i128::MIN + 1) / 2), i128::MIN + 2);
1585 assert_eq!(a.saturating_mul_int(i128::MIN / 2), i128::MIN);
1587 assert_eq!(a.saturating_mul_int(i128::MIN / 2 - 1), i128::MIN);
1589
1590 if $name::SIGNED {
1591 let b = $name::saturating_from_rational(1, -2);
1592 assert_eq!(b.saturating_mul_int(42i32), -21);
1593 assert_eq!(b.saturating_mul_int(i128::MAX), i128::MAX / -2);
1594 assert_eq!(b.saturating_mul_int(i128::MIN), i128::MIN / -2);
1595 assert_eq!(b.saturating_mul_int(u128::MAX), u128::MIN);
1596 }
1597
1598 let a = $name::saturating_from_rational(1, 2);
1599 assert_eq!(a.saturating_mul_int(42i32), 21);
1600 assert_eq!(a.saturating_mul_int(i128::MAX), i128::MAX / 2);
1601 assert_eq!(a.saturating_mul_int(i128::MIN), i128::MIN / 2);
1602
1603 let c = $name::saturating_from_integer(255);
1604 assert_eq!(c.saturating_mul_int(2i8), i8::MAX);
1605 assert_eq!(c.saturating_mul_int(-2i8), i8::MIN);
1606 assert_eq!(c.saturating_mul_int(i128::MAX), i128::MAX);
1607 assert_eq!(c.saturating_mul_int(i128::MIN), i128::MIN);
1608 }
1609
1610 #[test]
1611 fn checked_mul_works() {
1612 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1613 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1614
1615 let a = $name::saturating_from_integer(2);
1616
1617 let b = $name::from_inner(inner_max - 1);
1619 assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
1620
1621 let c = $name::from_inner(inner_max);
1623 assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
1624
1625 let e = $name::from_inner(1);
1627 assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
1628
1629 if $name::SIGNED {
1630 let b = $name::from_inner(inner_min + 1) / 2.into();
1632 let c = $name::from_inner(inner_min + 2);
1633 assert_eq!(a.checked_mul(&b), Some(c));
1634
1635 let b = $name::from_inner(inner_min) / 2.into();
1637 let c = $name::from_inner(inner_min);
1638 assert_eq!(a.checked_mul(&b), Some(c));
1639
1640 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1642 assert_eq!(a.checked_mul(&b), None);
1643
1644 let c = $name::saturating_from_integer(255);
1645 let b = $name::saturating_from_rational(1, -2);
1646
1647 assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
1648 assert_eq!(
1649 b.checked_mul(&$name::max_value()),
1650 $name::max_value().checked_div(&0.saturating_sub(2).into())
1651 );
1652 assert_eq!(
1653 b.checked_mul(&$name::min_value()),
1654 $name::min_value().checked_div(&0.saturating_sub(2).into())
1655 );
1656 assert_eq!(c.checked_mul(&$name::min_value()), None);
1657 }
1658
1659 let a = $name::saturating_from_rational(1, 2);
1660 let c = $name::saturating_from_integer(255);
1661
1662 assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
1663 assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
1664 assert_eq!(c.checked_mul(&$name::max_value()), None);
1665 assert_eq!(
1666 a.checked_mul(&$name::max_value()),
1667 $name::max_value().checked_div(&2.into())
1668 );
1669 assert_eq!(
1670 a.checked_mul(&$name::min_value()),
1671 $name::min_value().checked_div(&2.into())
1672 );
1673 }
1674
1675 #[test]
1676 fn const_checked_mul_works() {
1677 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1678 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1679
1680 let a = $name::saturating_from_integer(2u32);
1681
1682 let b = $name::from_inner(inner_max - 1);
1684 assert_eq!(a.const_checked_mul((b / 2.into())), Some(b));
1685
1686 let c = $name::from_inner(inner_max);
1688 assert_eq!(a.const_checked_mul((c / 2.into())), Some(b));
1689
1690 let e = $name::from_inner(1);
1692 assert_eq!(a.const_checked_mul((c / 2.into() + e)), None);
1693
1694 if $name::SIGNED {
1695 let b = $name::from_inner(inner_min + 1) / 2.into();
1697 let c = $name::from_inner(inner_min + 2);
1698 assert_eq!(a.const_checked_mul(b), Some(c));
1699
1700 let b = $name::from_inner(inner_min) / 2.into();
1702 let c = $name::from_inner(inner_min);
1703 assert_eq!(a.const_checked_mul(b), Some(c));
1704
1705 let b = $name::from_inner(inner_min) / 2.into() - $name::from_inner(1);
1707 assert_eq!(a.const_checked_mul(b), None);
1708
1709 let b = $name::saturating_from_rational(1i32, -2i32);
1710 let c = $name::saturating_from_integer(-21i32);
1711 let d = $name::saturating_from_integer(42);
1712
1713 assert_eq!(b.const_checked_mul(d), Some(c));
1714
1715 let minus_two = $name::saturating_from_integer(-2i32);
1716 assert_eq!(
1717 b.const_checked_mul($name::max_value()),
1718 $name::max_value().const_checked_div(minus_two)
1719 );
1720 assert_eq!(
1721 b.const_checked_mul($name::min_value()),
1722 $name::min_value().const_checked_div(minus_two)
1723 );
1724
1725 let c = $name::saturating_from_integer(255u32);
1726 assert_eq!(c.const_checked_mul($name::min_value()), None);
1727 }
1728
1729 let a = $name::saturating_from_rational(1i32, 2i32);
1730 let c = $name::saturating_from_integer(255i32);
1731
1732 assert_eq!(a.const_checked_mul(42.into()), Some(21.into()));
1733 assert_eq!(c.const_checked_mul(2.into()), Some(510.into()));
1734 assert_eq!(c.const_checked_mul($name::max_value()), None);
1735 assert_eq!(
1736 a.const_checked_mul($name::max_value()),
1737 $name::max_value().checked_div(&2.into())
1738 );
1739 assert_eq!(
1740 a.const_checked_mul($name::min_value()),
1741 $name::min_value().const_checked_div($name::saturating_from_integer(2))
1742 );
1743 }
1744
1745 #[test]
1746 fn checked_div_int_works() {
1747 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1748 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1749 let accuracy = $name::accuracy();
1750
1751 let a = $name::from_inner(inner_max);
1752 let b = $name::from_inner(inner_min);
1753 let c = $name::zero();
1754 let d = $name::one();
1755 let e = $name::saturating_from_integer(6);
1756 let f = $name::saturating_from_integer(5);
1757
1758 assert_eq!(e.checked_div_int(2.into()), Some(3));
1759 assert_eq!(f.checked_div_int(2.into()), Some(2));
1760
1761 assert_eq!(a.checked_div_int(i128::MAX), Some(0));
1762 assert_eq!(a.checked_div_int(2), Some(inner_max / (2 * accuracy)));
1763 assert_eq!(a.checked_div_int(inner_max / accuracy), Some(1));
1764 assert_eq!(a.checked_div_int(1i8), None);
1765
1766 if b < c {
1767 assert_eq!(
1769 a.checked_div_int(0.saturating_sub(2)),
1770 Some(0.saturating_sub(inner_max / (2 * accuracy)))
1771 );
1772 assert_eq!(
1773 a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
1774 Some(0.saturating_sub(1))
1775 );
1776 assert_eq!(b.checked_div_int(i128::MIN), Some(0));
1777 assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
1778 assert_eq!(b.checked_div_int(1i8), None);
1779 assert_eq!(
1780 b.checked_div_int(0.saturating_sub(2)),
1781 Some(0.saturating_sub(inner_min / (2 * accuracy)))
1782 );
1783 assert_eq!(
1784 b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
1785 Some(0.saturating_sub(1))
1786 );
1787 assert_eq!(c.checked_div_int(i128::MIN), Some(0));
1788 assert_eq!(d.checked_div_int(i32::MIN), Some(0));
1789 }
1790
1791 assert_eq!(b.checked_div_int(2), Some(inner_min / (2 * accuracy)));
1792
1793 assert_eq!(c.checked_div_int(1), Some(0));
1794 assert_eq!(c.checked_div_int(i128::MAX), Some(0));
1795 assert_eq!(c.checked_div_int(1i8), Some(0));
1796
1797 assert_eq!(d.checked_div_int(1), Some(1));
1798 assert_eq!(d.checked_div_int(i32::MAX), Some(0));
1799 assert_eq!(d.checked_div_int(1i8), Some(1));
1800
1801 assert_eq!(a.checked_div_int(0), None);
1802 assert_eq!(b.checked_div_int(0), None);
1803 assert_eq!(c.checked_div_int(0), None);
1804 assert_eq!(d.checked_div_int(0), None);
1805 }
1806
1807 #[test]
1808 #[should_panic(expected = "attempt to divide by zero")]
1809 fn saturating_div_int_panics_when_divisor_is_zero() {
1810 let _ = $name::one().saturating_div_int(0);
1811 }
1812
1813 #[test]
1814 fn saturating_div_int_works() {
1815 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1816 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1817 let accuracy = $name::accuracy();
1818
1819 let a = $name::saturating_from_integer(5);
1820 assert_eq!(a.saturating_div_int(2), 2);
1821
1822 let a = $name::min_value();
1823 assert_eq!(a.saturating_div_int(1i128), (inner_min / accuracy) as i128);
1824
1825 if $name::SIGNED {
1826 let a = $name::saturating_from_integer(5);
1827 assert_eq!(a.saturating_div_int(-2), -2);
1828
1829 let a = $name::min_value();
1830 assert_eq!(a.saturating_div_int(-1i128), (inner_max / accuracy) as i128);
1831 }
1832 }
1833
1834 #[test]
1835 fn saturating_abs_works() {
1836 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1837 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1838
1839 assert_eq!($name::from_inner(inner_max).saturating_abs(), $name::max_value());
1840 assert_eq!($name::zero().saturating_abs(), 0.into());
1841
1842 if $name::SIGNED {
1843 assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
1844 assert_eq!(
1845 $name::saturating_from_rational(-1, 2).saturating_abs(),
1846 (1, 2).into()
1847 );
1848 }
1849 }
1850
1851 #[test]
1852 fn saturating_mul_acc_int_works() {
1853 assert_eq!($name::zero().saturating_mul_acc_int(42i8), 42i8);
1854 assert_eq!($name::one().saturating_mul_acc_int(42i8), 2 * 42i8);
1855
1856 assert_eq!($name::one().saturating_mul_acc_int(i128::MAX), i128::MAX);
1857 assert_eq!($name::one().saturating_mul_acc_int(i128::MIN), i128::MIN);
1858
1859 assert_eq!($name::one().saturating_mul_acc_int(u128::MAX / 2), u128::MAX - 1);
1860 assert_eq!($name::one().saturating_mul_acc_int(u128::MIN), u128::MIN);
1861
1862 if $name::SIGNED {
1863 let a = $name::saturating_from_rational(-1, 2);
1864 assert_eq!(a.saturating_mul_acc_int(42i8), 21i8);
1865 assert_eq!(a.saturating_mul_acc_int(42u8), 21u8);
1866 assert_eq!(a.saturating_mul_acc_int(u128::MAX - 1), u128::MAX / 2);
1867 }
1868 }
1869
1870 #[test]
1871 fn saturating_pow_should_work() {
1872 assert_eq!(
1873 $name::saturating_from_integer(2).saturating_pow(0),
1874 $name::saturating_from_integer(1)
1875 );
1876 assert_eq!(
1877 $name::saturating_from_integer(2).saturating_pow(1),
1878 $name::saturating_from_integer(2)
1879 );
1880 assert_eq!(
1881 $name::saturating_from_integer(2).saturating_pow(2),
1882 $name::saturating_from_integer(4)
1883 );
1884 assert_eq!(
1885 $name::saturating_from_integer(2).saturating_pow(3),
1886 $name::saturating_from_integer(8)
1887 );
1888 assert_eq!(
1889 $name::saturating_from_integer(2).saturating_pow(50),
1890 $name::saturating_from_integer(1125899906842624i64)
1891 );
1892
1893 assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
1894 assert_eq!(
1895 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1896 (1).into()
1897 );
1898
1899 if $name::SIGNED {
1900 assert_eq!(
1902 $name::saturating_from_integer(2).saturating_pow(68),
1903 $name::max_value()
1904 );
1905
1906 assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
1907 assert_eq!(
1908 $name::saturating_from_integer(-1).saturating_pow(1001),
1909 0.saturating_sub(1).into()
1910 );
1911 assert_eq!(
1912 $name::saturating_from_integer(-1).saturating_pow(usize::MAX),
1913 0.saturating_sub(1).into()
1914 );
1915 assert_eq!(
1916 $name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
1917 (1).into()
1918 );
1919 }
1920
1921 assert_eq!(
1922 $name::saturating_from_integer(114209).saturating_pow(5),
1923 $name::max_value()
1924 );
1925
1926 assert_eq!(
1927 $name::saturating_from_integer(1).saturating_pow(usize::MAX),
1928 (1).into()
1929 );
1930 assert_eq!(
1931 $name::saturating_from_integer(0).saturating_pow(usize::MAX),
1932 (0).into()
1933 );
1934 assert_eq!(
1935 $name::saturating_from_integer(2).saturating_pow(usize::MAX),
1936 $name::max_value()
1937 );
1938 }
1939
1940 #[test]
1941 fn checked_div_works() {
1942 let inner_max = <$name as FixedPointNumber>::Inner::max_value();
1943 let inner_min = <$name as FixedPointNumber>::Inner::min_value();
1944
1945 let a = $name::from_inner(inner_max);
1946 let b = $name::from_inner(inner_min);
1947 let c = $name::zero();
1948 let d = $name::one();
1949 let e = $name::saturating_from_integer(6);
1950 let f = $name::saturating_from_integer(5);
1951
1952 assert_eq!(e.checked_div(&2.into()), Some(3.into()));
1953 assert_eq!(f.checked_div(&2.into()), Some((5, 2).into()));
1954
1955 assert_eq!(a.checked_div(&inner_max.into()), Some(1.into()));
1956 assert_eq!(a.checked_div(&2.into()), Some($name::from_inner(inner_max / 2)));
1957 assert_eq!(a.checked_div(&$name::max_value()), Some(1.into()));
1958 assert_eq!(a.checked_div(&d), Some(a));
1959
1960 if b < c {
1961 assert_eq!(
1963 a.checked_div(&0.saturating_sub(2).into()),
1964 Some($name::from_inner(0.saturating_sub(inner_max / 2)))
1965 );
1966 assert_eq!(
1967 a.checked_div(&-$name::max_value()),
1968 Some(0.saturating_sub(1).into())
1969 );
1970 assert_eq!(
1971 b.checked_div(&0.saturating_sub(2).into()),
1972 Some($name::from_inner(0.saturating_sub(inner_min / 2)))
1973 );
1974 assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
1975 assert_eq!(b.checked_div(&b), Some($name::one()));
1976 }
1977
1978 assert_eq!(b.checked_div(&2.into()), Some($name::from_inner(inner_min / 2)));
1979 assert_eq!(b.checked_div(&a), Some(0.saturating_sub(1).into()));
1980 assert_eq!(c.checked_div(&1.into()), Some(0.into()));
1981 assert_eq!(d.checked_div(&1.into()), Some(1.into()));
1982
1983 assert_eq!(a.checked_div(&$name::one()), Some(a));
1984 assert_eq!(b.checked_div(&$name::one()), Some(b));
1985 assert_eq!(c.checked_div(&$name::one()), Some(c));
1986 assert_eq!(d.checked_div(&$name::one()), Some(d));
1987
1988 assert_eq!(a.checked_div(&$name::zero()), None);
1989 assert_eq!(b.checked_div(&$name::zero()), None);
1990 assert_eq!(c.checked_div(&$name::zero()), None);
1991 assert_eq!(d.checked_div(&$name::zero()), None);
1992 }
1993
1994 #[test]
1995 fn is_positive_negative_works() {
1996 let one = $name::one();
1997 assert!(one.is_positive());
1998 assert!(!one.is_negative());
1999
2000 let zero = $name::zero();
2001 assert!(!zero.is_positive());
2002 assert!(!zero.is_negative());
2003
2004 if $signed {
2005 let minus_one = $name::saturating_from_integer(-1);
2006 assert!(minus_one.is_negative());
2007 assert!(!minus_one.is_positive());
2008 }
2009 }
2010
2011 #[test]
2012 fn trunc_works() {
2013 let n = $name::saturating_from_rational(5, 2).trunc();
2014 assert_eq!(n, $name::saturating_from_integer(2));
2015
2016 if $name::SIGNED {
2017 let n = $name::saturating_from_rational(-5, 2).trunc();
2018 assert_eq!(n, $name::saturating_from_integer(-2));
2019 }
2020 }
2021
2022 #[test]
2023 fn frac_works() {
2024 let n = $name::saturating_from_rational(5, 2);
2025 let i = n.trunc();
2026 let f = n.frac();
2027
2028 assert_eq!(n, i + f);
2029
2030 let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
2031 assert_eq!(n, 5.into());
2032
2033 let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
2034 assert_eq!(n, 5.into());
2035
2036 if $name::SIGNED {
2037 let n = $name::saturating_from_rational(-5, 2);
2038 let i = n.trunc();
2039 let f = n.frac();
2040 assert_eq!(n, i - f);
2041
2042 let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
2044 assert_eq!(n, 5.into());
2045
2046 let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
2047 assert_eq!(n, 0.saturating_sub(5).into());
2048 }
2049 }
2050
2051 #[test]
2052 fn ceil_works() {
2053 let n = $name::saturating_from_rational(5, 2);
2054 assert_eq!(n.ceil(), 3.into());
2055
2056 let n = $name::saturating_from_rational(-5, 2);
2057 assert_eq!(n.ceil(), 0.saturating_sub(2).into());
2058
2059 let n = $name::max_value();
2061 assert_eq!(n.ceil(), n.trunc());
2062
2063 let n = $name::min_value();
2064 assert_eq!(n.ceil(), n.trunc());
2065 }
2066
2067 #[test]
2068 fn floor_works() {
2069 let n = $name::saturating_from_rational(5, 2);
2070 assert_eq!(n.floor(), 2.into());
2071
2072 let n = $name::saturating_from_rational(-5, 2);
2073 assert_eq!(n.floor(), 0.saturating_sub(3).into());
2074
2075 let n = $name::max_value();
2077 assert_eq!(n.floor(), n.trunc());
2078
2079 let n = $name::min_value();
2080 assert_eq!(n.floor(), n.trunc());
2081 }
2082
2083 #[test]
2084 fn round_works() {
2085 let n = $name::zero();
2086 assert_eq!(n.round(), n);
2087
2088 let n = $name::one();
2089 assert_eq!(n.round(), n);
2090
2091 let n = $name::saturating_from_rational(5, 2);
2092 assert_eq!(n.round(), 3.into());
2093
2094 let n = $name::saturating_from_rational(-5, 2);
2095 assert_eq!(n.round(), 0.saturating_sub(3).into());
2096
2097 let n = $name::max_value();
2099 assert_eq!(n.round(), n.trunc());
2100
2101 let n = $name::min_value();
2102 assert_eq!(n.round(), n.trunc());
2103
2104 let n = $name::max_value()
2108 .saturating_sub(1.into())
2109 .trunc()
2110 .saturating_add((1, 3).into());
2111
2112 assert_eq!(n.round(), ($name::max_value() - 1.into()).trunc());
2113
2114 let n = $name::max_value()
2116 .saturating_sub(1.into())
2117 .trunc()
2118 .saturating_add((1, 2).into());
2119
2120 assert_eq!(n.round(), $name::max_value().trunc());
2121
2122 if $name::SIGNED {
2123 let n = $name::min_value()
2125 .saturating_add(1.into())
2126 .trunc()
2127 .saturating_sub((1, 3).into());
2128
2129 assert_eq!(n.round(), ($name::min_value() + 1.into()).trunc());
2130
2131 let n = $name::min_value()
2133 .saturating_add(1.into())
2134 .trunc()
2135 .saturating_sub((1, 2).into());
2136
2137 assert_eq!(n.round(), $name::min_value().trunc());
2138 }
2139 }
2140
2141 #[test]
2142 fn perthing_into_works() {
2143 let ten_percent_percent: $name = Percent::from_percent(10).into();
2144 assert_eq!(ten_percent_percent.into_inner(), $name::accuracy() / 10);
2145
2146 let ten_percent_permill: $name = Permill::from_percent(10).into();
2147 assert_eq!(ten_percent_permill.into_inner(), $name::accuracy() / 10);
2148
2149 let ten_percent_perbill: $name = Perbill::from_percent(10).into();
2150 assert_eq!(ten_percent_perbill.into_inner(), $name::accuracy() / 10);
2151
2152 let ten_percent_perquintill: $name = Perquintill::from_percent(10).into();
2153 assert_eq!(ten_percent_perquintill.into_inner(), $name::accuracy() / 10);
2154 }
2155
2156 #[test]
2157 fn fmt_should_work() {
2158 let zero = $name::zero();
2159 assert_eq!(
2160 format!("{:?}", zero),
2161 format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
2162 );
2163
2164 let one = $name::one();
2165 assert_eq!(
2166 format!("{:?}", one),
2167 format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
2168 );
2169
2170 let frac = $name::saturating_from_rational(1, 2);
2171 assert_eq!(
2172 format!("{:?}", frac),
2173 format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
2174 );
2175
2176 let frac = $name::saturating_from_rational(5, 2);
2177 assert_eq!(
2178 format!("{:?}", frac),
2179 format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
2180 );
2181
2182 let frac = $name::saturating_from_rational(314, 100);
2183 assert_eq!(
2184 format!("{:?}", frac),
2185 format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
2186 );
2187
2188 if $name::SIGNED {
2189 let neg = -$name::one();
2190 assert_eq!(
2191 format!("{:?}", neg),
2192 format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
2193 );
2194
2195 let frac = $name::saturating_from_rational(-314, 100);
2196 assert_eq!(
2197 format!("{:?}", frac),
2198 format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
2199 );
2200 }
2201 }
2202 }
2203 };
2204}
2205
2206implement_fixed!(
2207 FixedI64,
2208 test_fixed_i64,
2209 i64,
2210 true,
2211 1_000_000_000,
2212 "_Fixed Point 64 bits signed, range = [-9223372036.854775808, 9223372036.854775807]_",
2213);
2214
2215implement_fixed!(
2216 FixedU64,
2217 test_fixed_u64,
2218 u64,
2219 false,
2220 1_000_000_000,
2221 "_Fixed Point 64 bits unsigned, range = [0.000000000, 18446744073.709551615]_",
2222);
2223
2224implement_fixed!(
2225 FixedI128,
2226 test_fixed_i128,
2227 i128,
2228 true,
2229 1_000_000_000_000_000_000,
2230 "_Fixed Point 128 bits signed, range = \
2231 [-170141183460469231731.687303715884105728, 170141183460469231731.687303715884105727]_",
2232);
2233
2234implement_fixed!(
2235 FixedU128,
2236 test_fixed_u128,
2237 u128,
2238 false,
2239 1_000_000_000_000_000_000,
2240 "_Fixed Point 128 bits unsigned, range = \
2241 [0.000000000000000000, 340282366920938463463.374607431768211455]_",
2242);