1#![doc = docify::embed!("./src/lib.rs", perbill_example)]
29#![doc = docify::embed!("./src/lib.rs", percent_example)]
31#![doc = docify::embed!("./src/lib.rs", percent_mult)]
53
54#[cfg(feature = "serde")]
55use serde::{Deserialize, Serialize};
56
57use crate::traits::{
58 BaseArithmetic, Bounded, CheckedAdd, CheckedMul, CheckedSub, One, SaturatedConversion,
59 Saturating, UniqueSaturatedInto, Unsigned, Zero,
60};
61use codec::{CompactAs, DecodeWithMemTracking, Encode};
62use core::{
63 fmt, ops,
64 ops::{Add, Sub},
65};
66use num_traits::{Pow, SaturatingAdd, SaturatingSub};
67
68pub type InnerOf<P> = <P as PerThing>::Inner;
70
71pub type UpperOf<P> = <P as PerThing>::Upper;
73
74pub trait RationalArg:
75 Clone
76 + Ord
77 + ops::Div<Self, Output = Self>
78 + ops::Rem<Self, Output = Self>
79 + ops::Add<Self, Output = Self>
80 + ops::AddAssign<Self>
81 + Unsigned
82 + Zero
83 + One
84 + crate::MultiplyRational
85{
86}
87
88impl<
89 T: Clone
90 + Ord
91 + ops::Div<Self, Output = Self>
92 + ops::Rem<Self, Output = Self>
93 + ops::Add<Self, Output = Self>
94 + ops::AddAssign<Self>
95 + Unsigned
96 + Zero
97 + One
98 + crate::MultiplyRational,
99 > RationalArg for T
100{
101}
102
103pub trait MultiplyArg:
104 Clone
105 + ops::Rem<Self, Output = Self>
106 + ops::Div<Self, Output = Self>
107 + ops::Mul<Self, Output = Self>
108 + ops::Add<Self, Output = Self>
109 + Unsigned
110{
111}
112
113impl<
114 T: Clone
115 + ops::Rem<Self, Output = Self>
116 + ops::Div<Self, Output = Self>
117 + ops::Mul<Self, Output = Self>
118 + ops::Add<Self, Output = Self>
119 + Unsigned,
120 > MultiplyArg for T
121{
122}
123
124pub trait ReciprocalArg: MultiplyArg + Saturating {}
125impl<T: MultiplyArg + Saturating> ReciprocalArg for T {}
126
127pub trait PerThing:
130 Sized
131 + Saturating
132 + Copy
133 + Default
134 + Eq
135 + PartialEq
136 + Ord
137 + PartialOrd
138 + Bounded
139 + fmt::Debug
140 + ops::Div<Output = Self>
141 + ops::Mul<Output = Self>
142 + Pow<usize, Output = Self>
143{
144 type Inner: BaseArithmetic + Unsigned + Copy + Into<u128> + fmt::Debug + crate::MultiplyRational;
146
147 type Upper: BaseArithmetic
150 + Copy
151 + From<Self::Inner>
152 + TryInto<Self::Inner>
153 + UniqueSaturatedInto<Self::Inner>
154 + Unsigned
155 + fmt::Debug
156 + crate::MultiplyRational;
157
158 const ACCURACY: Self::Inner;
160
161 fn zero() -> Self {
163 Self::from_parts(Self::Inner::zero())
164 }
165
166 fn is_zero(&self) -> bool {
168 self.deconstruct() == Self::Inner::zero()
169 }
170
171 fn one() -> Self {
173 Self::from_parts(Self::ACCURACY)
174 }
175
176 fn is_one(&self) -> bool {
178 self.deconstruct() == Self::ACCURACY
179 }
180
181 fn less_epsilon(self) -> Self {
183 if self.is_zero() {
184 return self;
185 }
186 Self::from_parts(self.deconstruct() - One::one())
187 }
188
189 fn try_less_epsilon(self) -> Result<Self, Self> {
192 if self.is_zero() {
193 return Err(self);
194 }
195 Ok(Self::from_parts(self.deconstruct() - One::one()))
196 }
197
198 fn plus_epsilon(self) -> Self {
200 if self.is_one() {
201 return self;
202 }
203 Self::from_parts(self.deconstruct() + One::one())
204 }
205
206 fn try_plus_epsilon(self) -> Result<Self, Self> {
209 if self.is_one() {
210 return Err(self);
211 }
212 Ok(Self::from_parts(self.deconstruct() + One::one()))
213 }
214
215 fn from_percent(x: Self::Inner) -> Self {
218 let a: Self::Inner = x.min(100.into());
219 let b: Self::Inner = 100.into();
220 Self::from_rational::<Self::Inner>(a, b)
221 }
222
223 fn square(self) -> Self {
225 let p = Self::Upper::from(self.deconstruct());
226 let q = Self::Upper::from(Self::ACCURACY);
227 Self::from_rational::<Self::Upper>(p * p, q * q)
228 }
229
230 fn left_from_one(self) -> Self {
232 Self::one().saturating_sub(self)
233 }
234
235 fn mul_floor<N>(self, b: N) -> N
251 where
252 N: MultiplyArg + UniqueSaturatedInto<Self::Inner>,
253 Self::Inner: Into<N>,
254 {
255 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
256 }
257
258 fn mul_ceil<N>(self, b: N) -> N
274 where
275 N: MultiplyArg + UniqueSaturatedInto<Self::Inner>,
276 Self::Inner: Into<N>,
277 {
278 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
279 }
280
281 fn saturating_reciprocal_mul<N>(self, b: N) -> N
291 where
292 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
293 Self::Inner: Into<N>,
294 {
295 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::NearestPrefUp)
296 }
297
298 fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
311 where
312 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
313 Self::Inner: Into<N>,
314 {
315 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
316 }
317
318 fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
331 where
332 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
333 Self::Inner: Into<N>,
334 {
335 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
336 }
337
338 fn deconstruct(self) -> Self::Inner;
340
341 fn from_parts(parts: Self::Inner) -> Self;
343
344 #[cfg(feature = "std")]
346 fn from_float(x: f64) -> Self;
347
348 #[deprecated = "Use from_float instead"]
350 #[cfg(feature = "std")]
351 fn from_fraction(x: f64) -> Self {
352 Self::from_float(x)
353 }
354
355 fn from_rational<N>(p: N, q: N) -> Self
374 where
375 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
376 Self::Inner: Into<N>,
377 {
378 Self::from_rational_with_rounding(p, q, Rounding::Down).unwrap_or_else(|_| Self::one())
379 }
380
381 fn from_rational_with_rounding<N>(p: N, q: N, rounding: Rounding) -> Result<Self, ()>
436 where
437 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
438 Self::Inner: Into<N>;
439
440 #[deprecated = "Use from_rational instead"]
442 fn from_rational_approximation<N>(p: N, q: N) -> Self
443 where
444 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
445 Self::Inner: Into<N>,
446 {
447 Self::from_rational(p, q)
448 }
449}
450
451#[derive(Copy, Clone, core::fmt::Debug)]
453pub enum Rounding {
454 Up,
456 Down,
458 NearestPrefUp,
460 NearestPrefDown,
462}
463
464#[derive(Copy, Clone, core::fmt::Debug)]
466pub enum SignedRounding {
467 High,
469 Low,
471 NearestPrefHigh,
473 NearestPrefLow,
475 Major,
477 Minor,
479 NearestPrefMajor,
481 NearestPrefMinor,
483}
484
485impl Rounding {
486 pub const fn from_signed(rounding: SignedRounding, negative: bool) -> Self {
488 use Rounding::*;
489 use SignedRounding::*;
490 match (rounding, negative) {
491 (Low, true) | (Major, _) | (High, false) => Up,
492 (High, true) | (Minor, _) | (Low, false) => Down,
493 (NearestPrefMajor, _) | (NearestPrefHigh, false) | (NearestPrefLow, true) => {
494 NearestPrefUp
495 },
496 (NearestPrefMinor, _) | (NearestPrefLow, false) | (NearestPrefHigh, true) => {
497 NearestPrefDown
498 },
499 }
500 }
501}
502
503fn saturating_reciprocal_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
506where
507 N: Clone
508 + UniqueSaturatedInto<P::Inner>
509 + ops::Div<N, Output = N>
510 + ops::Mul<N, Output = N>
511 + ops::Add<N, Output = N>
512 + ops::Rem<N, Output = N>
513 + Saturating
514 + Unsigned,
515 P: PerThing,
516 P::Inner: Into<N>,
517{
518 let maximum: N = P::ACCURACY.into();
519 let c = rational_mul_correction::<N, P>(x.clone(), P::ACCURACY, part, rounding);
520 (x / part.into()).saturating_mul(maximum).saturating_add(c)
521}
522
523fn overflow_prune_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
525where
526 N: MultiplyArg + UniqueSaturatedInto<P::Inner>,
527 P: PerThing,
528 P::Inner: Into<N>,
529{
530 let maximum: N = P::ACCURACY.into();
531 let part_n: N = part.into();
532 let c = rational_mul_correction::<N, P>(x.clone(), part, P::ACCURACY, rounding);
533 (x / maximum) * part_n + c
534}
535
536fn rational_mul_correction<N, P>(x: N, numer: P::Inner, denom: P::Inner, rounding: Rounding) -> N
541where
542 N: MultiplyArg + UniqueSaturatedInto<P::Inner>,
543 P: PerThing,
544 P::Inner: Into<N>,
545{
546 let numer_upper = P::Upper::from(numer);
547 let denom_n: N = denom.into();
548 let denom_upper = P::Upper::from(denom);
549 let rem = x.rem(denom_n);
550 let rem_inner = rem.saturated_into::<P::Inner>();
552 let rem_mul_upper = P::Upper::from(rem_inner) * numer_upper;
554 let mut rem_mul_div_inner = (rem_mul_upper / denom_upper).saturated_into::<P::Inner>();
557 match rounding {
558 Rounding::Down => {},
560 Rounding::Up => {
562 if rem_mul_upper % denom_upper > 0.into() {
563 rem_mul_div_inner += 1.into();
565 }
566 },
567 Rounding::NearestPrefDown => {
568 if rem_mul_upper % denom_upper > denom_upper / 2.into() {
569 rem_mul_div_inner += 1.into();
571 }
572 },
573 Rounding::NearestPrefUp => {
574 if rem_mul_upper % denom_upper >= denom_upper / 2.into() + denom_upper % 2.into() {
575 rem_mul_div_inner += 1.into();
577 }
578 },
579 }
580 rem_mul_div_inner.into()
581}
582
583macro_rules! implement_per_thing {
584 (
585 $name:ident,
586 $test_mod:ident,
587 [$($test_units:tt),+],
588 $max:tt,
589 $type:ty,
590 $upper_type:ty,
591 $title:expr $(,)?
592 ) => {
593 #[doc = $title]
596 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
597 #[derive(Encode, DecodeWithMemTracking, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, scale_info::TypeInfo)]
598 pub struct $name($type);
599
600 impl CompactAs for $name {
603 type As = $type;
604 fn encode_as(&self) -> &Self::As {
605 &self.0
606 }
607 fn decode_from(x: Self::As) -> Result<Self, codec::Error> {
608 Ok(Self::from_parts(x))
610 }
611 }
612
613 impl From<codec::Compact<$name>> for $name {
614 fn from(x: codec::Compact<$name>) -> $name {
615 x.0
616 }
617 }
618
619 #[cfg(feature = "std")]
620 impl core::fmt::Debug for $name {
621 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
622 if $max == <$type>::max_value() {
623 let pc = (self.0 as f64) / (self.0 as f64) * 100f64;
625 write!(fmt, "{:.2}% ({}/{})", pc, self.0, $max)
626 } else {
627 let divisor = $max / 100;
629 let units = self.0 / divisor;
630 let rest = self.0 % divisor;
631 write!(fmt, "{}", units)?;
632 if rest > 0 {
633 write!(fmt, ".")?;
634 let mut m = $max / 100;
635 while rest % m > 0 {
636 m /= 10;
637 write!(fmt, "{:01}", rest / m % 10)?;
638 }
639 }
640 write!(fmt, "%")
641 }
642 }
643 }
644
645 #[cfg(not(feature = "std"))]
646 impl core::fmt::Debug for $name {
647 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
648 if $max == <$type>::max_value() {
649 write!(fmt, "{}/{}", self.0, $max)
651 } else {
652 let units = self.0 / ($max / 100);
654 let rest = self.0 % ($max / 100);
655 write!(fmt, "{}", units)?;
656 if rest > 0 {
657 write!(fmt, ".")?;
658 let mut m = $max / 100;
659 while rest % m > 0 {
660 m /= 10;
661 write!(fmt, "{:01}", rest / m % 10)?;
662 }
663 }
664 write!(fmt, "%")
665 }
666 }
667 }
668
669 impl PerThing for $name {
670 type Inner = $type;
671 type Upper = $upper_type;
672
673 const ACCURACY: Self::Inner = $max;
674
675 fn deconstruct(self) -> Self::Inner { self.0 }
677
678 fn from_parts(parts: Self::Inner) -> Self { Self(parts.min($max)) }
680
681 #[cfg(feature = "std")]
683 fn from_float(x: f64) -> Self {
684 Self::from_parts((x.max(0.).min(1.) * $max as f64) as Self::Inner)
685 }
686
687 fn from_rational_with_rounding<N>(p: N, q: N, r: Rounding) -> Result<Self, ()>
688 where
689 N: Clone
690 + Ord
691 + TryInto<Self::Inner>
692 + TryInto<Self::Upper>
693 + ops::Div<N, Output = N>
694 + ops::Rem<N, Output = N>
695 + ops::Add<N, Output = N>
696 + ops::AddAssign<N>
697 + Unsigned
698 + Zero
699 + One
700 + $crate::MultiplyRational,
701 Self::Inner: Into<N>
702 {
703 if q.is_zero() { return Err(()) }
705 if p > q { return Err(()) }
707
708 let max: N = $max.into();
709 max.multiply_rational(p, q, r).ok_or(())?.try_into().map(|x| $name(x)).map_err(|_| ())
710 }
711 }
712
713 impl $name {
714 #[allow(unused_comparisons)]
720 pub const fn from_parts(parts: $type) -> Self {
721 Self([parts, $max][(parts > $max) as usize])
722 }
723
724 pub const fn from_percent(x: $type) -> Self {
728 Self(([x, 100][(x > 100) as usize] as $upper_type * $max as $upper_type / 100) as $type)
729 }
730
731 pub const fn one() -> Self {
733 Self::from_parts($max)
734 }
735
736 pub fn is_one(&self) -> bool {
738 PerThing::is_one(self)
739 }
740
741 pub const fn zero() -> Self {
743 Self::from_parts(0)
744 }
745
746 pub fn is_zero(&self) -> bool {
748 PerThing::is_zero(self)
749 }
750
751 pub const fn deconstruct(self) -> $type {
753 self.0
754 }
755
756 pub fn square(self) -> Self {
758 PerThing::square(self)
759 }
760
761 #[cfg(feature = "std")]
763 pub fn from_float(x: f64) -> Self {
764 <Self as PerThing>::from_float(x)
765 }
766
767 #[deprecated = "Use `PerThing::from_rational` instead"]
769 pub fn from_rational_approximation<N>(p: N, q: N) -> Self
770 where
771 N: RationalArg+ TryInto<$type> + TryInto<$upper_type>,
772 $type: Into<N>
773 {
774 <Self as PerThing>::from_rational(p, q)
775 }
776
777 pub fn from_rational<N>(p: N, q: N) -> Self
779 where
780 N: RationalArg+ TryInto<$type> + TryInto<$upper_type>,
781 $type: Into<N>
782 {
783 <Self as PerThing>::from_rational(p, q)
784 }
785
786 pub fn int_mul(self, b: $type) -> Self {
788 PerThing::from_parts(self.0.saturating_mul(b))
789 }
790
791 pub fn int_div(self, b: Self) -> $type {
793 self.0 / b.0
794 }
795
796 pub fn mul_floor<N>(self, b: N) -> N
798 where
799 N: MultiplyArg + UniqueSaturatedInto<$type>,
800 $type: Into<N>,
801
802 {
803 PerThing::mul_floor(self, b)
804 }
805
806 pub fn mul_ceil<N>(self, b: N) -> N
808 where
809 N: MultiplyArg + UniqueSaturatedInto<$type>,
810 $type: Into<N>,
811 {
812 PerThing::mul_ceil(self, b)
813 }
814
815 pub fn saturating_reciprocal_mul<N>(self, b: N) -> N
817 where
818 N: ReciprocalArg + UniqueSaturatedInto<$type>,
819 $type: Into<N>,
820 {
821 PerThing::saturating_reciprocal_mul(self, b)
822 }
823
824 pub fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
826 where
827 N: ReciprocalArg + UniqueSaturatedInto<$type>,
828 $type: Into<N>,
829 {
830 PerThing::saturating_reciprocal_mul_floor(self, b)
831 }
832
833 pub fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
835 where
836 N: ReciprocalArg + UniqueSaturatedInto<$type>,
837 $type: Into<N>,
838 {
839 PerThing::saturating_reciprocal_mul_ceil(self, b)
840 }
841
842 pub fn saturating_div(self, rhs: Self, r: Rounding) -> Self {
869 let p = self.0;
870 let q = rhs.0;
871 Self::from_rational_with_rounding(p, q, r).unwrap_or_else(|_| Self::one())
872 }
873 }
874
875 impl Saturating for $name {
876 fn saturating_add(self, rhs: Self) -> Self {
879 Self::from_parts(self.0.saturating_add(rhs.0))
881 }
882
883 fn saturating_sub(self, rhs: Self) -> Self {
886 Self::from_parts(self.0.saturating_sub(rhs.0))
887 }
888
889 fn saturating_mul(self, rhs: Self) -> Self {
892 self * rhs
893 }
894
895 fn saturating_pow(self, exp: usize) -> Self {
898 self.pow(exp)
899 }
900 }
901
902 impl codec::Decode for $name {
903 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
904 let inner = <$type as codec::Decode>::decode(input)?;
905
906 if inner <= <Self as PerThing>::ACCURACY {
907 Ok(Self(inner))
908 } else {
909 Err("Value is greater than allowed maximum!".into())
910 }
911 }
912 }
913
914 impl Bounded for $name {
915 fn min_value() -> Self {
916 <Self as PerThing>::zero()
917 }
918
919 fn max_value() -> Self {
920 <Self as PerThing>::one()
921 }
922 }
923
924 impl ops::Mul for $name {
925 type Output = Self;
926
927 fn mul(self, rhs: Self) -> Self::Output {
928 let a = self.0 as $upper_type;
929 let b = rhs.0 as $upper_type;
930 let m = <$upper_type>::from($max);
931 let parts = a * b / m;
932 Self::from_parts(parts as $type)
934 }
935 }
936
937 impl Pow<usize> for $name {
938 type Output = Self;
939
940 fn pow(mut self, exp: usize) -> Self::Output {
941 if exp == 0 || self.is_one() {
942 return Self::one()
943 }
944
945 let mut result = self;
946 let mut exp = exp - 1;
947 while exp > 0 && !result.is_zero() {
948 if !exp.is_multiple_of(2) {
949 result = result * self;
950 exp -= 1;
951 }
952 self = self.square();
953 exp /= 2;
954 }
955 result
956 }
957 }
958
959 impl ops::Div for $name {
960 type Output = Self;
961
962 fn div(self, rhs: Self) -> Self::Output {
963 let p = self.0;
964 let q = rhs.0;
965 Self::from_rational(p, q)
966 }
967 }
968
969 impl Default for $name {
970 fn default() -> Self {
971 <Self as PerThing>::zero()
972 }
973 }
974
975 impl<N> ops::Mul<N> for $name
979 where
980 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
981 + ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
982 $type: Into<N>,
983 {
984 type Output = N;
985 fn mul(self, b: N) -> Self::Output {
986 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::NearestPrefDown)
987 }
988 }
989
990 impl<N> ops::Div<N> for $name where $type: TryFrom<N> {
991 type Output = Self;
992 fn div(self, b: N) -> Self::Output {
993 <$type>::try_from(b).map_or(Self::zero(), |d| Self::from_parts(self.0 / d))
994 }
995 }
996
997 impl Add<Self> for $name {
998 type Output = $name;
999
1000 #[allow(unused_comparisons)]
1002 #[inline]
1003 fn add(self, rhs: Self) -> Self::Output {
1004 let inner = self.deconstruct().add(rhs.deconstruct());
1005 debug_assert!(inner <= $max);
1006 $name::from_parts(inner)
1007 }
1008 }
1009
1010 impl CheckedAdd for $name {
1011 #[allow(unused_comparisons)]
1013 #[inline]
1014 fn checked_add(&self, rhs: &Self) -> Option<Self> {
1015 self.deconstruct()
1016 .checked_add(rhs.deconstruct())
1017 .map(|inner| if inner > $max { None } else { Some($name::from_parts(inner)) })
1018 .flatten()
1019 }
1020 }
1021
1022 impl Sub<Self> for $name {
1023 type Output = $name;
1024
1025 #[inline]
1026 fn sub(self, rhs: Self) -> Self::Output {
1027 $name::from_parts(self.deconstruct().sub(rhs.deconstruct()))
1028 }
1029 }
1030
1031 impl CheckedSub for $name {
1032 #[inline]
1033 fn checked_sub(&self, v: &Self) -> Option<Self> {
1034 self.deconstruct().checked_sub(v.deconstruct()).map($name::from_parts)
1035 }
1036 }
1037
1038 impl SaturatingAdd for $name {
1039 #[inline]
1040 fn saturating_add(&self, v: &Self) -> Self {
1041 $name::from_parts(self.deconstruct().saturating_add(v.deconstruct()))
1042 }
1043 }
1044
1045 impl SaturatingSub for $name {
1046 #[inline]
1047 fn saturating_sub(&self, v: &Self) -> Self {
1048 $name::from_parts(self.deconstruct().saturating_sub(v.deconstruct()))
1049 }
1050 }
1051
1052 impl CheckedMul for $name {
1055 #[inline]
1056 fn checked_mul(&self, rhs: &Self) -> Option<Self> {
1057 Some(*self * *rhs)
1058 }
1059 }
1060
1061 impl $crate::traits::Zero for $name {
1062 fn zero() -> Self {
1063 Self::zero()
1064 }
1065
1066 fn is_zero(&self) -> bool {
1067 self == &Self::zero()
1068 }
1069 }
1070
1071 impl $crate::traits::One for $name {
1072 fn one() -> Self {
1073 Self::one()
1074 }
1075 }
1076
1077 #[cfg(test)]
1078 mod $test_mod {
1079 use codec::{Encode, Decode};
1080 use super::{$name, Saturating, PerThing};
1081 use crate::traits::Zero;
1082
1083 #[test]
1084 fn macro_expanded_correctly() {
1085 assert!(2 * ($max as $upper_type) < <$upper_type>::max_value());
1094 assert!(<$upper_type>::from($max) < <$upper_type>::max_value());
1095
1096 assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value());
1098 assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some());
1099
1100 assert!(<$upper_type>::from($max) * <$upper_type>::from($max) < <$upper_type>::max_value());
1102 }
1103
1104 #[derive(Encode, Decode, PartialEq, Eq, Debug)]
1105 struct WithCompact<T: codec::HasCompact> {
1106 data: T,
1107 }
1108
1109 #[test]
1110 fn has_compact() {
1111 let data = WithCompact { data: $name(1) };
1112 let encoded = data.encode();
1113 assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap());
1114 }
1115
1116 #[test]
1117 fn compact_encoding() {
1118 let tests = [
1119 (0 as $type, 1usize),
1121 (1 as $type, 1usize),
1122 (63, 1),
1123 (64, 2),
1124 (65, 2),
1125 ];
1127 for &(n, l) in &tests {
1128 let compact: codec::Compact<$name> = $name(n).into();
1129 let encoded = compact.encode();
1130 assert_eq!(encoded.len(), l);
1131 let decoded = <codec::Compact<$name>>::decode(&mut & encoded[..])
1132 .unwrap();
1133 let per_thingy: $name = decoded.into();
1134 assert_eq!(per_thingy, $name(n));
1135 }
1136 }
1137
1138 #[test]
1139 fn from_parts_cannot_overflow() {
1140 assert_eq!(<$name>::from_parts($max.saturating_add(1)), <$name>::one());
1141 }
1142
1143 #[test]
1144 fn has_max_encoded_len() {
1145 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1146 _data: T,
1147 }
1148
1149 let _ = AsMaxEncodedLen { _data: $name(1) };
1150 }
1151
1152 #[test]
1153 fn fail_on_invalid_encoded_value() {
1154 let value = <$upper_type>::from($max) * 2;
1155 let casted = value as $type;
1156 let encoded = casted.encode();
1157
1158 if <$upper_type>::from(casted) == value {
1160 assert_eq!(
1161 $name::decode(&mut &encoded[..]),
1162 Err("Value is greater than allowed maximum!".into()),
1163 );
1164 }
1165 }
1166
1167 #[test]
1168 fn per_thing_api_works() {
1169 assert_eq!($name::zero(), $name::from_parts(Zero::zero()));
1171 assert_eq!($name::one(), $name::from_parts($max));
1172 assert_eq!($name::ACCURACY, $max);
1173
1174 assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero()));
1175 assert_eq!($name::from_percent(10), $name::from_parts($max / 10));
1176 assert_eq!($name::from_percent(50), $name::from_parts($max / 2));
1177 assert_eq!($name::from_percent(100), $name::from_parts($max));
1178 assert_eq!($name::from_percent(200), $name::from_parts($max));
1179
1180 assert_eq!($name::from_float(0.0), $name::from_parts(Zero::zero()));
1181 assert_eq!($name::from_float(0.1), $name::from_parts($max / 10));
1182 assert_eq!($name::from_float(1.0), $name::from_parts($max));
1183 assert_eq!($name::from_float(2.0), $name::from_parts($max));
1184 assert_eq!($name::from_float(-1.0), $name::from_parts(Zero::zero()));
1185 }
1186
1187 #[test]
1188 fn percent_trait_impl_works() {
1189 assert_eq!(<$name as PerThing>::from_percent(0), $name::from_parts(Zero::zero()));
1190 assert_eq!(<$name as PerThing>::from_percent(10), $name::from_parts($max / 10));
1191 assert_eq!(<$name as PerThing>::from_percent(50), $name::from_parts($max / 2));
1192 assert_eq!(<$name as PerThing>::from_percent(100), $name::from_parts($max));
1193 assert_eq!(<$name as PerThing>::from_percent(200), $name::from_parts($max));
1194 }
1195
1196 macro_rules! u256ify {
1197 ($val:expr) => {
1198 Into::<U256>::into($val)
1199 };
1200 }
1201
1202 macro_rules! per_thing_mul_test {
1203 ($num_type:tt) => {
1204 assert_eq!(
1206 $name::from_float(1.0) * $num_type::max_value(),
1207 $num_type::max_value()
1208 );
1209 if $max % 100 == 0 {
1210 assert_eq_error_rate!(
1211 $name::from_percent(99) * $num_type::max_value(),
1212 ((Into::<U256>::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type,
1213 1,
1214 );
1215 assert_eq!(
1216 $name::from_float(0.5) * $num_type::max_value(),
1217 $num_type::max_value() / 2,
1218 );
1219 assert_eq_error_rate!(
1220 $name::from_percent(1) * $num_type::max_value(),
1221 $num_type::max_value() / 100,
1222 1,
1223 );
1224 } else {
1225 assert_eq!(
1226 $name::from_float(0.99) * <$num_type>::max_value(),
1227 (
1228 (
1229 u256ify!($name::from_float(0.99).0) *
1230 u256ify!(<$num_type>::max_value()) /
1231 u256ify!($max)
1232 ).as_u128()
1233 ) as $num_type,
1234 );
1235 assert_eq!(
1236 $name::from_float(0.50) * <$num_type>::max_value(),
1237 (
1238 (
1239 u256ify!($name::from_float(0.50).0) *
1240 u256ify!(<$num_type>::max_value()) /
1241 u256ify!($max)
1242 ).as_u128()
1243 ) as $num_type,
1244 );
1245 assert_eq!(
1246 $name::from_float(0.01) * <$num_type>::max_value(),
1247 (
1248 (
1249 u256ify!($name::from_float(0.01).0) *
1250 u256ify!(<$num_type>::max_value()) /
1251 u256ify!($max)
1252 ).as_u128()
1253 ) as $num_type,
1254 );
1255 }
1256
1257 assert_eq!($name::from_float(0.0) * $num_type::max_value(), 0);
1258
1259 assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value());
1261 assert_eq!($name::zero() * $num_type::max_value(), 0);
1262 }
1263 }
1264
1265 #[test]
1266 fn per_thing_mul_works() {
1267 use primitive_types::U256;
1268
1269 assert_eq!(
1271 $name::from_rational(1 as $type, 3) * 30 as $type,
1272 10,
1273 );
1274
1275 $(per_thing_mul_test!($test_units);)*
1276 }
1277
1278 #[test]
1279 fn per_thing_mul_rounds_to_nearest_number() {
1280 assert_eq!($name::from_percent(33) * 10u64, 3);
1281 assert_eq!($name::from_percent(34) * 10u64, 3);
1282 assert_eq!($name::from_percent(35) * 10u64, 3);
1283 assert_eq!($name::from_percent(36) * 10u64, 4);
1284 }
1285
1286 #[test]
1287 fn per_thing_multiplication_with_large_number() {
1288 use primitive_types::U256;
1289 let max_minus_one = $max - 1;
1290 assert_eq_error_rate!(
1291 $name::from_parts(max_minus_one) * std::u128::MAX,
1292 ((Into::<U256>::into(std::u128::MAX) * max_minus_one) / $max).as_u128(),
1293 1,
1294 );
1295 }
1296
1297 macro_rules! per_thing_from_rationale_approx_test {
1298 ($num_type:tt) => {
1299 assert_eq!(
1301 $name::from_rational(1 as $num_type, 0),
1302 $name::one(),
1303 );
1304 assert_eq!(
1305 $name::from_rational(1 as $num_type, 1),
1306 $name::one(),
1307 );
1308 assert_eq_error_rate!(
1309 $name::from_rational(1 as $num_type, 3).0,
1310 $name::from_parts($max / 3).0,
1311 2
1312 );
1313 assert_eq!(
1314 $name::from_rational(1 as $num_type, 10),
1315 $name::from_float(0.10),
1316 );
1317 assert_eq!(
1318 $name::from_rational(1 as $num_type, 4),
1319 $name::from_float(0.25),
1320 );
1321 assert_eq!(
1322 $name::from_rational(1 as $num_type, 4),
1323 $name::from_rational(2 as $num_type, 8),
1324 );
1325 assert_eq_error_rate!(
1327 $name::from_rational(
1328 $num_type::max_value() - 1,
1329 $num_type::max_value()
1330 ).0 as $upper_type,
1331 $name::one().0 as $upper_type,
1332 2,
1333 );
1334 assert_eq_error_rate!(
1335 $name::from_rational(
1336 $num_type::max_value() / 3,
1337 $num_type::max_value()
1338 ).0 as $upper_type,
1339 $name::from_parts($max / 3).0 as $upper_type,
1340 2,
1341 );
1342 assert_eq!(
1343 $name::from_rational(1, $num_type::max_value()),
1344 $name::zero(),
1345 );
1346 };
1347 }
1348
1349 #[test]
1350 fn per_thing_from_rationale_approx_works() {
1351 let max_value = <$upper_type>::from($max);
1354
1355 assert_eq!(
1357 $name::from_rational(max_value - 1, max_value + 1),
1358 $name::from_parts($max - 2),
1359 );
1360 assert_eq!(
1361 $name::from_rational(1, $max - 1),
1362 $name::from_parts(1),
1363 );
1364 assert_eq!(
1365 $name::from_rational(1, $max),
1366 $name::from_parts(1),
1367 );
1368 assert_eq!(
1369 $name::from_rational(2, 2 * max_value - 1),
1370 $name::from_parts(1),
1371 );
1372 assert_eq!(
1373 $name::from_rational(1, max_value + 1),
1374 $name::zero(),
1375 );
1376 assert_eq!(
1377 $name::from_rational(3 * max_value / 2, 3 * max_value),
1378 $name::from_float(0.5),
1379 );
1380
1381 $(per_thing_from_rationale_approx_test!($test_units);)*
1382 }
1383
1384 #[test]
1385 fn per_things_mul_operates_in_output_type() {
1386 assert_eq!($name::from_float(0.5) * 100u64, 50u64);
1388 assert_eq!($name::from_float(0.5) * 100u128, 50u128);
1389 }
1390
1391 #[test]
1392 fn per_thing_saturating_op_works() {
1393 assert_eq_error_rate!(
1394 $name::from_float(0.5).saturating_add($name::from_float(0.4)).0 as $upper_type,
1395 $name::from_float(0.9).0 as $upper_type,
1396 2,
1397 );
1398 assert_eq_error_rate!(
1399 $name::from_float(0.5).saturating_add($name::from_float(0.5)).0 as $upper_type,
1400 $name::one().0 as $upper_type,
1401 2,
1402 );
1403 assert_eq!(
1404 $name::from_float(0.6).saturating_add($name::from_float(0.5)),
1405 $name::one(),
1406 );
1407
1408 assert_eq_error_rate!(
1409 $name::from_float(0.6).saturating_sub($name::from_float(0.5)).0 as $upper_type,
1410 $name::from_float(0.1).0 as $upper_type,
1411 2,
1412 );
1413 assert_eq!(
1414 $name::from_float(0.6).saturating_sub($name::from_float(0.6)),
1415 $name::from_float(0.0),
1416 );
1417 assert_eq!(
1418 $name::from_float(0.6).saturating_sub($name::from_float(0.7)),
1419 $name::from_float(0.0),
1420 );
1421
1422 assert_eq_error_rate!(
1423 $name::from_float(0.5).saturating_mul($name::from_float(0.5)).0 as $upper_type,
1424 $name::from_float(0.25).0 as $upper_type,
1425 2,
1426 );
1427 assert_eq_error_rate!(
1428 $name::from_float(0.2).saturating_mul($name::from_float(0.2)).0 as $upper_type,
1429 $name::from_float(0.04).0 as $upper_type,
1430 2,
1431 );
1432 assert_eq_error_rate!(
1433 $name::from_float(0.1).saturating_mul($name::from_float(0.1)).0 as $upper_type,
1434 $name::from_float(0.01).0 as $upper_type,
1435 1,
1436 );
1437 }
1438
1439 #[test]
1440 fn per_thing_square_works() {
1441 assert_eq!($name::from_float(1.0).square(), $name::from_float(1.0));
1442 assert_eq!($name::from_float(0.5).square(), $name::from_float(0.25));
1443 assert_eq!($name::from_float(0.1).square(), $name::from_float(0.01));
1444 assert_eq!(
1445 $name::from_float(0.02).square(),
1446 $name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type)
1447 );
1448 }
1449
1450 #[test]
1451 fn per_things_div_works() {
1452 assert_eq_error_rate!(
1454 ($name::from_float(0.1) / $name::from_float(0.20)).0 as $upper_type,
1455 $name::from_float(0.50).0 as $upper_type,
1456 2,
1457 );
1458 assert_eq_error_rate!(
1459 ($name::from_float(0.1) / $name::from_float(0.10)).0 as $upper_type,
1460 $name::from_float(1.0).0 as $upper_type,
1461 2,
1462 );
1463 assert_eq_error_rate!(
1464 ($name::from_float(0.1) / $name::from_float(0.0)).0 as $upper_type,
1465 $name::from_float(1.0).0 as $upper_type,
1466 2,
1467 );
1468
1469 assert_eq_error_rate!(
1471 ($name::from_float(0.10) / $name::from_float(0.05)).0 as $upper_type,
1472 $name::from_float(1.0).0 as $upper_type,
1473 2,
1474 );
1475 assert_eq_error_rate!(
1476 ($name::from_float(1.0) / $name::from_float(0.5)).0 as $upper_type,
1477 $name::from_float(1.0).0 as $upper_type,
1478 2,
1479 );
1480 }
1481
1482 #[test]
1483 fn saturating_pow_works() {
1484 assert_eq!(
1486 $name::from_parts($max / 2).saturating_pow(0),
1487 $name::from_parts($max),
1488 );
1489
1490 assert_eq!(
1492 $name::from_parts($max / 2).saturating_pow(1),
1493 $name::from_parts($max / 2),
1494 );
1495
1496 assert_eq!(
1498 $name::from_parts($max / 2).saturating_pow(2),
1499 $name::from_parts($max / 2).square(),
1500 );
1501
1502 for n in 1..=16 {
1504 assert_eq!(
1505 $name::from_parts($max / 2).saturating_pow(n),
1506 $name::from_parts(($max as u128 / 2u128.pow(n as u32)) as $type),
1507 );
1508 }
1509
1510 assert_eq!(
1512 $name::from_parts(0).saturating_pow(3),
1513 $name::from_parts(0),
1514 );
1515
1516 assert_eq!(
1518 $name::from_parts($max).saturating_pow(3),
1519 $name::from_parts($max),
1520 );
1521
1522 assert_eq!(
1524 $name::from_parts($max / 2).saturating_pow(2usize.pow(31)),
1525 $name::from_parts(0),
1526 );
1527 }
1528
1529 #[test]
1530 fn saturating_reciprocal_mul_works() {
1531 assert_eq!(
1533 $name::from_parts($max).saturating_reciprocal_mul(<$type>::from(10u8)),
1534 10,
1535 );
1536 assert_eq!(
1538 $name::from_parts($max / 2).saturating_reciprocal_mul(<$type>::from(10u8)),
1539 20,
1540 );
1541 assert_eq!(
1543 $name::from_parts(1).saturating_reciprocal_mul($max),
1544 <$type>::max_value(),
1545 );
1546 assert_eq!(
1548 $name::from_percent(60).saturating_reciprocal_mul(<$type>::from(10u8)),
1549 17,
1550 );
1551 assert_eq!(
1553 $name::from_percent(60).saturating_reciprocal_mul_floor(<$type>::from(10u8)),
1554 16,
1555 );
1556 assert_eq!(
1558 $name::from_percent(61).saturating_reciprocal_mul(<$type>::from(10u8)),
1559 16,
1560 );
1561 assert_eq!(
1563 $name::from_percent(61).saturating_reciprocal_mul_ceil(<$type>::from(10u8)),
1564 17,
1565 );
1566 }
1567
1568 #[test]
1569 fn saturating_truncating_mul_works() {
1570 assert_eq!(
1571 $name::from_percent(49).mul_floor(10 as $type),
1572 4,
1573 );
1574 let a: $upper_type = $name::from_percent(50).mul_floor(($max as $upper_type).pow(2));
1575 let b: $upper_type = ($max as $upper_type).pow(2) / 2;
1576 if $max % 2 == 0 {
1577 assert_eq!(a, b);
1578 } else {
1579 assert!(b - a < ($max as $upper_type).pow(2) / 100 as $upper_type);
1581 }
1582 }
1583
1584 #[test]
1585 fn rational_mul_correction_works() {
1586 assert_eq!(
1587 super::rational_mul_correction::<$type, $name>(
1588 <$type>::max_value(),
1589 <$type>::max_value(),
1590 <$type>::max_value(),
1591 super::Rounding::NearestPrefDown,
1592 ),
1593 0,
1594 );
1595 assert_eq!(
1596 super::rational_mul_correction::<$type, $name>(
1597 <$type>::max_value() - 1,
1598 <$type>::max_value(),
1599 <$type>::max_value(),
1600 super::Rounding::NearestPrefDown,
1601 ),
1602 <$type>::max_value() - 1,
1603 );
1604 assert_eq!(
1605 super::rational_mul_correction::<$upper_type, $name>(
1606 ((<$type>::max_value() - 1) as $upper_type).pow(2),
1607 <$type>::max_value(),
1608 <$type>::max_value(),
1609 super::Rounding::NearestPrefDown,
1610 ),
1611 1,
1612 );
1613 assert_eq!(
1615 super::rational_mul_correction::<$upper_type, $name>(
1616 (<$type>::max_value() as $upper_type).pow(2) - 1,
1617 <$type>::max_value(),
1618 <$type>::max_value(),
1619 super::Rounding::NearestPrefDown,
1620 ),
1621 <$upper_type>::from(<$type>::max_value() - 1),
1622 );
1623 assert_eq!(
1625 super::rational_mul_correction::<$upper_type, $name>(
1626 (<$type>::max_value() as $upper_type).pow(2),
1627 <$type>::max_value(),
1628 2 as $type,
1629 super::Rounding::NearestPrefDown,
1630 ),
1631 <$type>::max_value() as $upper_type / 2,
1632 );
1633 assert_eq!(
1635 super::rational_mul_correction::<$upper_type, $name>(
1636 (<$type>::max_value() as $upper_type).pow(2) - 1,
1637 2 as $type,
1638 <$type>::max_value(),
1639 super::Rounding::NearestPrefDown,
1640 ),
1641 2,
1642 );
1643 assert_eq!(
1645 super::rational_mul_correction::<$upper_type, $name>(
1646 (<$type>::max_value() as $upper_type).pow(2) - 1,
1647 2 as $type,
1648 <$type>::max_value(),
1649 super::Rounding::Down,
1650 ),
1651 1,
1652 );
1653 }
1654
1655 #[test]
1656 #[allow(unused)]
1657 fn const_fns_work() {
1658 const C1: $name = $name::from_percent(50);
1659 const C2: $name = $name::one();
1660 const C3: $name = $name::zero();
1661 const C4: $name = $name::from_parts(1);
1662
1663 const C5: bool = C1.deconstruct() == 0;
1665 }
1666
1667 #[test]
1668 fn compact_decoding_saturate_when_beyond_accuracy() {
1669 use num_traits::Bounded;
1670 use codec::Compact;
1671
1672 let p = Compact::<$name>::decode(&mut &Compact(<$type>::max_value()).encode()[..])
1673 .unwrap();
1674 assert_eq!((p.0).0, $max);
1675 assert_eq!($name::from(p), $name::max_value());
1676 }
1677
1678 #[allow(unused_imports)]
1679 use super::*;
1680
1681 #[test]
1682 fn test_add_basic() {
1683 assert_eq!($name::from_parts(1) + $name::from_parts(1), $name::from_parts(2));
1684 assert_eq!($name::from_parts(10) + $name::from_parts(10), $name::from_parts(20));
1685 }
1686
1687 #[test]
1688 fn test_basic_checked_add() {
1689 assert_eq!(
1690 $name::from_parts(1).checked_add(&$name::from_parts(1)),
1691 Some($name::from_parts(2))
1692 );
1693 assert_eq!(
1694 $name::from_parts(10).checked_add(&$name::from_parts(10)),
1695 Some($name::from_parts(20))
1696 );
1697 assert_eq!(
1698 $name::from_parts(<$type>::MAX).checked_add(&$name::from_parts(<$type>::MAX)),
1699 None
1700 );
1701 assert_eq!(
1702 $name::from_parts($max).checked_add(&$name::from_parts(1)),
1703 None
1704 );
1705 }
1706
1707 #[test]
1708 fn test_basic_saturating_add() {
1709 assert_eq!(
1710 $name::from_parts(1).saturating_add($name::from_parts(1)),
1711 $name::from_parts(2)
1712 );
1713 assert_eq!(
1714 $name::from_parts(10).saturating_add($name::from_parts(10)),
1715 $name::from_parts(20)
1716 );
1717 assert_eq!(
1718 $name::from_parts(<$type>::MAX).saturating_add($name::from_parts(<$type>::MAX)),
1719 $name::from_parts(<$type>::MAX)
1720 );
1721 }
1722
1723 #[test]
1724 fn test_basic_sub() {
1725 assert_eq!($name::from_parts(2) - $name::from_parts(1), $name::from_parts(1));
1726 assert_eq!($name::from_parts(20) - $name::from_parts(10), $name::from_parts(10));
1727 }
1728
1729 #[test]
1730 fn test_basic_checked_sub() {
1731 assert_eq!(
1732 $name::from_parts(2).checked_sub(&$name::from_parts(1)),
1733 Some($name::from_parts(1))
1734 );
1735 assert_eq!(
1736 $name::from_parts(20).checked_sub(&$name::from_parts(10)),
1737 Some($name::from_parts(10))
1738 );
1739 assert_eq!($name::from_parts(0).checked_sub(&$name::from_parts(1)), None);
1740 }
1741
1742 #[test]
1743 fn test_basic_saturating_sub() {
1744 assert_eq!(
1745 $name::from_parts(2).saturating_sub($name::from_parts(1)),
1746 $name::from_parts(1)
1747 );
1748 assert_eq!(
1749 $name::from_parts(20).saturating_sub($name::from_parts(10)),
1750 $name::from_parts(10)
1751 );
1752 assert_eq!(
1753 $name::from_parts(0).saturating_sub($name::from_parts(1)),
1754 $name::from_parts(0)
1755 );
1756 }
1757
1758 #[test]
1759 fn test_basic_checked_mul() {
1760 assert_eq!(
1761 $name::from_parts($max).checked_mul(&$name::from_parts($max)),
1762 Some($name::from_percent(100))
1763 );
1764 assert_eq!(
1765 $name::from_percent(100).checked_mul(&$name::from_percent(100)),
1766 Some($name::from_percent(100))
1767 );
1768 assert_eq!(
1769 $name::from_percent(50).checked_mul(&$name::from_percent(26)),
1770 Some($name::from_percent(13))
1771 );
1772 assert_eq!(
1773 $name::from_percent(0).checked_mul(&$name::from_percent(0)),
1774 Some($name::from_percent(0))
1775 );
1776 }
1777 }
1778 };
1779}
1780
1781macro_rules! implement_per_thing_with_perthousand {
1782 (
1783 $name:ident,
1784 $test_mod:ident,
1785 $pt_test_mod:ident,
1786 [$($test_units:tt),+],
1787 $max:tt,
1788 $type:ty,
1789 $upper_type:ty,
1790 $title:expr $(,)?
1791 ) => {
1792 implement_per_thing! {
1793 $name, $test_mod, [ $( $test_units ),+ ], $max, $type, $upper_type, $title,
1794 }
1795 impl $name {
1796 pub const fn from_perthousand(x: $type) -> Self {
1800 Self(([x, 1000][(x > 1000) as usize] as $upper_type * $max as $upper_type / 1000) as $type)
1801 }
1802 }
1803 #[cfg(test)]
1804 mod $pt_test_mod {
1805 use super::$name;
1806 use crate::traits::Zero;
1807
1808 #[test]
1809 fn from_perthousand_works() {
1810 assert_eq!($name::from_perthousand(00), $name::from_parts(Zero::zero()));
1812 assert_eq!($name::from_perthousand(100), $name::from_parts($max / 10));
1813 assert_eq!($name::from_perthousand(1000), $name::from_parts($max));
1814 assert_eq!($name::from_perthousand(2000), $name::from_parts($max));
1815 }
1816
1817 #[test]
1818 #[allow(unused)]
1819 fn const_fns_work() {
1820 const C1: $name = $name::from_perthousand(500);
1821 }
1822 }
1823 }
1824}
1825
1826#[test]
1827fn from_rational_with_rounding_works_in_extreme_case() {
1828 use Rounding::*;
1829 for &r in [Down, NearestPrefDown, NearestPrefUp, Up].iter() {
1830 Percent::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1831 Percent::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1832 Percent::from_rational_with_rounding(1, u16::max_value(), r).unwrap();
1833 Percent::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1834 Percent::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1835 Percent::from_rational_with_rounding(u16::max_value() - 1, u16::max_value(), r).unwrap();
1836 PerU16::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1837 PerU16::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1838 PerU16::from_rational_with_rounding(1, u16::max_value(), r).unwrap();
1839 PerU16::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1840 PerU16::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1841 PerU16::from_rational_with_rounding(u16::max_value() - 1, u16::max_value(), r).unwrap();
1842 Permill::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1843 Permill::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1844 Permill::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1845 Permill::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1846 Perbill::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1847 Perbill::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1848 Perbill::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1849 Perbill::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1850 }
1851}
1852
1853#[test]
1854fn from_rational_with_rounding_breakage() {
1855 let n = 372633774963620730670986667244911905u128;
1856 let d = 512593663333074177468745541591173060u128;
1857 let q = Perquintill::from_rational_with_rounding(n, d, Rounding::Down).unwrap();
1858 assert!(q * d <= n);
1859}
1860
1861#[test]
1862fn from_rational_with_rounding_breakage_2() {
1863 let n = 36893488147419103230u128;
1864 let d = 36893488147419103630u128;
1865 let q = Perquintill::from_rational_with_rounding(n, d, Rounding::Up).unwrap();
1866 assert!(q * d >= n);
1867}
1868
1869implement_per_thing!(Percent, test_per_cent, [u32, u64, u128], 100u8, u8, u16, "_Percent_",);
1870implement_per_thing_with_perthousand!(
1871 PerU16,
1872 test_peru16,
1873 test_peru16_extra,
1874 [u32, u64, u128],
1875 65535_u16,
1876 u16,
1877 u32,
1878 "_Parts per 65535_",
1879);
1880implement_per_thing_with_perthousand!(
1881 Permill,
1882 test_permill,
1883 test_permill_extra,
1884 [u32, u64, u128],
1885 1_000_000u32,
1886 u32,
1887 u64,
1888 "_Parts per Million_",
1889);
1890implement_per_thing_with_perthousand!(
1891 Perbill,
1892 test_perbill,
1893 test_perbill_extra,
1894 [u32, u64, u128],
1895 1_000_000_000u32,
1896 u32,
1897 u64,
1898 "_Parts per Billion_",
1899);
1900implement_per_thing_with_perthousand!(
1901 Perquintill,
1902 test_perquintill,
1903 test_perquintill_extra,
1904 [u64, u128],
1905 1_000_000_000_000_000_000u64,
1906 u64,
1907 u128,
1908 "_Parts per Quintillion_",
1909);