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)]
52
53#[cfg(feature = "serde")]
54use serde::{Deserialize, Serialize};
55
56use crate::traits::{
57 BaseArithmetic, Bounded, CheckedAdd, CheckedMul, CheckedSub, One, SaturatedConversion,
58 Saturating, UniqueSaturatedInto, Unsigned, Zero,
59};
60use codec::{CompactAs, DecodeWithMemTracking, Encode};
61use core::{
62 fmt, ops,
63 ops::{Add, Sub},
64};
65use num_traits::{Pow, SaturatingAdd, SaturatingSub};
66
67pub type InnerOf<P> = <P as PerThing>::Inner;
69
70pub type UpperOf<P> = <P as PerThing>::Upper;
72
73pub trait RationalArg:
74 Clone
75 + Ord
76 + ops::Div<Self, Output = Self>
77 + ops::Rem<Self, Output = Self>
78 + ops::Add<Self, Output = Self>
79 + ops::AddAssign<Self>
80 + Unsigned
81 + Zero
82 + One
83 + crate::MultiplyRational
84{
85}
86
87impl<
88 T: Clone
89 + Ord
90 + ops::Div<Self, Output = Self>
91 + ops::Rem<Self, Output = Self>
92 + ops::Add<Self, Output = Self>
93 + ops::AddAssign<Self>
94 + Unsigned
95 + Zero
96 + One
97 + crate::MultiplyRational,
98 > RationalArg for T
99{
100}
101
102pub trait MultiplyArg:
103 Clone
104 + ops::Rem<Self, Output = Self>
105 + ops::Div<Self, Output = Self>
106 + ops::Mul<Self, Output = Self>
107 + ops::Add<Self, Output = Self>
108 + Unsigned
109{
110}
111
112impl<
113 T: Clone
114 + ops::Rem<Self, Output = Self>
115 + ops::Div<Self, Output = Self>
116 + ops::Mul<Self, Output = Self>
117 + ops::Add<Self, Output = Self>
118 + Unsigned,
119 > MultiplyArg for T
120{
121}
122
123pub trait ReciprocalArg: MultiplyArg + Saturating {}
124impl<T: MultiplyArg + Saturating> ReciprocalArg for T {}
125
126pub trait PerThing:
129 Sized
130 + Saturating
131 + Copy
132 + Default
133 + Eq
134 + PartialEq
135 + Ord
136 + PartialOrd
137 + Bounded
138 + fmt::Debug
139 + ops::Div<Output = Self>
140 + ops::Mul<Output = Self>
141 + Pow<usize, Output = Self>
142{
143 type Inner: BaseArithmetic + Unsigned + Copy + Into<u128> + fmt::Debug + crate::MultiplyRational;
145
146 type Upper: BaseArithmetic
149 + Copy
150 + From<Self::Inner>
151 + TryInto<Self::Inner>
152 + UniqueSaturatedInto<Self::Inner>
153 + Unsigned
154 + fmt::Debug
155 + crate::MultiplyRational;
156
157 const ACCURACY: Self::Inner;
159
160 fn zero() -> Self {
162 Self::from_parts(Self::Inner::zero())
163 }
164
165 fn is_zero(&self) -> bool {
167 self.deconstruct() == Self::Inner::zero()
168 }
169
170 fn one() -> Self {
172 Self::from_parts(Self::ACCURACY)
173 }
174
175 fn is_one(&self) -> bool {
177 self.deconstruct() == Self::ACCURACY
178 }
179
180 #[must_use]
182 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 #[must_use]
200 fn plus_epsilon(self) -> Self {
201 if self.is_one() {
202 return self;
203 }
204 Self::from_parts(self.deconstruct() + One::one())
205 }
206
207 fn try_plus_epsilon(self) -> Result<Self, Self> {
210 if self.is_one() {
211 return Err(self);
212 }
213 Ok(Self::from_parts(self.deconstruct() + One::one()))
214 }
215
216 #[must_use]
219 fn from_percent(x: Self::Inner) -> Self {
220 let a: Self::Inner = x.min(100.into());
221 let b: Self::Inner = 100.into();
222 Self::from_rational::<Self::Inner>(a, b)
223 }
224
225 #[must_use]
227 fn square(self) -> Self {
228 let p = Self::Upper::from(self.deconstruct());
229 let q = Self::Upper::from(Self::ACCURACY);
230 Self::from_rational::<Self::Upper>(p * p, q * q)
231 }
232
233 #[must_use]
235 fn left_from_one(self) -> Self {
236 Self::one().saturating_sub(self)
237 }
238
239 #[must_use]
255 fn mul_floor<N>(self, b: N) -> N
256 where
257 N: MultiplyArg + UniqueSaturatedInto<Self::Inner>,
258 Self::Inner: Into<N>,
259 {
260 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
261 }
262
263 #[must_use]
279 fn mul_ceil<N>(self, b: N) -> N
280 where
281 N: MultiplyArg + UniqueSaturatedInto<Self::Inner>,
282 Self::Inner: Into<N>,
283 {
284 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
285 }
286
287 #[must_use]
297 fn saturating_reciprocal_mul<N>(self, b: N) -> N
298 where
299 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
300 Self::Inner: Into<N>,
301 {
302 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::NearestPrefUp)
303 }
304
305 #[must_use]
318 fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
319 where
320 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
321 Self::Inner: Into<N>,
322 {
323 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
324 }
325
326 #[must_use]
339 fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
340 where
341 N: ReciprocalArg + UniqueSaturatedInto<Self::Inner>,
342 Self::Inner: Into<N>,
343 {
344 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
345 }
346
347 fn deconstruct(self) -> Self::Inner;
349
350 #[must_use]
352 fn from_parts(parts: Self::Inner) -> Self;
353
354 #[must_use]
356 #[cfg(feature = "std")]
357 fn from_float(x: f64) -> Self;
358
359 #[deprecated = "Use from_float instead"]
361 #[cfg(feature = "std")]
362 fn from_fraction(x: f64) -> Self {
363 Self::from_float(x)
364 }
365
366 #[must_use]
385 fn from_rational<N>(p: N, q: N) -> Self
386 where
387 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
388 Self::Inner: Into<N>,
389 {
390 Self::from_rational_with_rounding(p, q, Rounding::Down).unwrap_or_else(|_| Self::one())
391 }
392
393 fn from_rational_with_rounding<N>(p: N, q: N, rounding: Rounding) -> Result<Self, ()>
448 where
449 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
450 Self::Inner: Into<N>;
451
452 #[deprecated = "Use from_rational instead"]
454 fn from_rational_approximation<N>(p: N, q: N) -> Self
455 where
456 N: RationalArg + TryInto<Self::Inner> + TryInto<Self::Upper>,
457 Self::Inner: Into<N>,
458 {
459 Self::from_rational(p, q)
460 }
461}
462
463#[derive(Copy, Clone, core::fmt::Debug)]
465pub enum Rounding {
466 Up,
468 Down,
470 NearestPrefUp,
472 NearestPrefDown,
474}
475
476#[derive(Copy, Clone, core::fmt::Debug)]
478pub enum SignedRounding {
479 High,
481 Low,
483 NearestPrefHigh,
485 NearestPrefLow,
487 Major,
489 Minor,
491 NearestPrefMajor,
493 NearestPrefMinor,
495}
496
497impl Rounding {
498 pub const fn from_signed(rounding: SignedRounding, negative: bool) -> Self {
500 use Rounding::*;
501 use SignedRounding::*;
502 match (rounding, negative) {
503 (Low, true) | (Major, _) | (High, false) => Up,
504 (High, true) | (Minor, _) | (Low, false) => Down,
505 (NearestPrefMajor, _) | (NearestPrefHigh, false) | (NearestPrefLow, true) => {
506 NearestPrefUp
507 },
508 (NearestPrefMinor, _) | (NearestPrefLow, false) | (NearestPrefHigh, true) => {
509 NearestPrefDown
510 },
511 }
512 }
513}
514
515fn saturating_reciprocal_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
518where
519 N: Clone
520 + UniqueSaturatedInto<P::Inner>
521 + ops::Div<N, Output = N>
522 + ops::Mul<N, Output = N>
523 + ops::Add<N, Output = N>
524 + ops::Rem<N, Output = N>
525 + Saturating
526 + Unsigned,
527 P: PerThing,
528 P::Inner: Into<N>,
529{
530 let maximum: N = P::ACCURACY.into();
531 let c = rational_mul_correction::<N, P>(x.clone(), P::ACCURACY, part, rounding);
532 (x / part.into()).saturating_mul(maximum).saturating_add(c)
533}
534
535fn overflow_prune_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
537where
538 N: MultiplyArg + UniqueSaturatedInto<P::Inner>,
539 P: PerThing,
540 P::Inner: Into<N>,
541{
542 let maximum: N = P::ACCURACY.into();
543 let part_n: N = part.into();
544 let c = rational_mul_correction::<N, P>(x.clone(), part, P::ACCURACY, rounding);
545 (x / maximum) * part_n + c
546}
547
548fn rational_mul_correction<N, P>(x: N, numer: P::Inner, denom: P::Inner, rounding: Rounding) -> N
553where
554 N: MultiplyArg + UniqueSaturatedInto<P::Inner>,
555 P: PerThing,
556 P::Inner: Into<N>,
557{
558 let numer_upper = P::Upper::from(numer);
559 let denom_n: N = denom.into();
560 let denom_upper = P::Upper::from(denom);
561 let rem = x.rem(denom_n);
562 let rem_inner = rem.saturated_into::<P::Inner>();
564 let rem_mul_upper = P::Upper::from(rem_inner) * numer_upper;
566 let mut rem_mul_div_inner = (rem_mul_upper / denom_upper).saturated_into::<P::Inner>();
569 match rounding {
570 Rounding::Down => {},
572 Rounding::Up => {
574 if rem_mul_upper % denom_upper > 0.into() {
575 rem_mul_div_inner += 1.into();
577 }
578 },
579 Rounding::NearestPrefDown => {
580 if rem_mul_upper % denom_upper > denom_upper / 2.into() {
581 rem_mul_div_inner += 1.into();
583 }
584 },
585 Rounding::NearestPrefUp => {
586 if rem_mul_upper % denom_upper >= denom_upper / 2.into() + denom_upper % 2.into() {
587 rem_mul_div_inner += 1.into();
589 }
590 },
591 }
592 rem_mul_div_inner.into()
593}
594
595macro_rules! implement_per_thing {
596 (
597 $name:ident,
598 $test_mod:ident,
599 [$($test_units:tt),+],
600 $max:tt,
601 $type:ty,
602 $upper_type:ty,
603 $title:expr $(,)?
604 ) => {
605 #[doc = $title]
608 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
609 #[derive(Encode, DecodeWithMemTracking, Copy, Clone, PartialEq, Eq, codec::MaxEncodedLen, PartialOrd, Ord, scale_info::TypeInfo)]
610 pub struct $name($type);
611
612 impl CompactAs for $name {
615 type As = $type;
616 fn encode_as(&self) -> &Self::As {
617 &self.0
618 }
619 fn decode_from(x: Self::As) -> Result<Self, codec::Error> {
620 Ok(Self::from_parts(x))
622 }
623 }
624
625 impl From<codec::Compact<$name>> for $name {
626 fn from(x: codec::Compact<$name>) -> $name {
627 x.0
628 }
629 }
630
631 #[cfg(feature = "std")]
632 impl core::fmt::Debug for $name {
633 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
634 if $max == <$type>::max_value() {
635 let pc = (self.0 as f64) / (self.0 as f64) * 100f64;
637 write!(fmt, "{:.2}% ({}/{})", pc, self.0, $max)
638 } else {
639 let divisor = $max / 100;
641 let units = self.0 / divisor;
642 let rest = self.0 % divisor;
643 write!(fmt, "{}", units)?;
644 if rest > 0 {
645 write!(fmt, ".")?;
646 let mut m = $max / 100;
647 while rest % m > 0 {
648 m /= 10;
649 write!(fmt, "{:01}", rest / m % 10)?;
650 }
651 }
652 write!(fmt, "%")
653 }
654 }
655 }
656
657 #[cfg(not(feature = "std"))]
658 impl core::fmt::Debug for $name {
659 fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
660 if $max == <$type>::max_value() {
661 write!(fmt, "{}/{}", self.0, $max)
663 } else {
664 let units = self.0 / ($max / 100);
666 let rest = self.0 % ($max / 100);
667 write!(fmt, "{}", units)?;
668 if rest > 0 {
669 write!(fmt, ".")?;
670 let mut m = $max / 100;
671 while rest % m > 0 {
672 m /= 10;
673 write!(fmt, "{:01}", rest / m % 10)?;
674 }
675 }
676 write!(fmt, "%")
677 }
678 }
679 }
680
681 impl PerThing for $name {
682 type Inner = $type;
683 type Upper = $upper_type;
684
685 const ACCURACY: Self::Inner = $max;
686
687 fn deconstruct(self) -> Self::Inner { self.0 }
689
690 fn from_parts(parts: Self::Inner) -> Self { Self(parts.min($max)) }
692
693 #[cfg(feature = "std")]
695 fn from_float(x: f64) -> Self {
696 Self::from_parts((x.max(0.).min(1.) * $max as f64) as Self::Inner)
697 }
698
699 fn from_rational_with_rounding<N>(p: N, q: N, r: Rounding) -> Result<Self, ()>
700 where
701 N: Clone
702 + Ord
703 + TryInto<Self::Inner>
704 + TryInto<Self::Upper>
705 + ops::Div<N, Output = N>
706 + ops::Rem<N, Output = N>
707 + ops::Add<N, Output = N>
708 + ops::AddAssign<N>
709 + Unsigned
710 + Zero
711 + One
712 + $crate::MultiplyRational,
713 Self::Inner: Into<N>
714 {
715 if q.is_zero() { return Err(()) }
717 if p > q { return Err(()) }
719
720 let max: N = $max.into();
721 max.multiply_rational(p, q, r).ok_or(())?.try_into().map(|x| $name(x)).map_err(|_| ())
722 }
723 }
724
725 impl $name {
726 #[allow(unused_comparisons)]
732 pub const fn from_parts(parts: $type) -> Self {
733 Self([parts, $max][(parts > $max) as usize])
734 }
735
736 pub const fn from_percent(x: $type) -> Self {
740 Self(([x, 100][(x > 100) as usize] as $upper_type * $max as $upper_type / 100) as $type)
741 }
742
743 pub const fn one() -> Self {
745 Self::from_parts($max)
746 }
747
748 pub fn is_one(&self) -> bool {
750 PerThing::is_one(self)
751 }
752
753 pub const fn zero() -> Self {
755 Self::from_parts(0)
756 }
757
758 pub fn is_zero(&self) -> bool {
760 PerThing::is_zero(self)
761 }
762
763 pub const fn deconstruct(self) -> $type {
765 self.0
766 }
767
768 pub fn square(self) -> Self {
770 PerThing::square(self)
771 }
772
773 #[cfg(feature = "std")]
775 pub fn from_float(x: f64) -> Self {
776 <Self as PerThing>::from_float(x)
777 }
778
779 #[deprecated = "Use `PerThing::from_rational` instead"]
781 pub fn from_rational_approximation<N>(p: N, q: N) -> Self
782 where
783 N: RationalArg+ TryInto<$type> + TryInto<$upper_type>,
784 $type: Into<N>
785 {
786 <Self as PerThing>::from_rational(p, q)
787 }
788
789 pub fn from_rational<N>(p: N, q: N) -> Self
791 where
792 N: RationalArg+ TryInto<$type> + TryInto<$upper_type>,
793 $type: Into<N>
794 {
795 <Self as PerThing>::from_rational(p, q)
796 }
797
798 pub fn int_mul(self, b: $type) -> Self {
800 PerThing::from_parts(self.0.saturating_mul(b))
801 }
802
803 pub fn int_div(self, b: Self) -> $type {
805 self.0 / b.0
806 }
807
808 pub fn mul_floor<N>(self, b: N) -> N
810 where
811 N: MultiplyArg + UniqueSaturatedInto<$type>,
812 $type: Into<N>,
813
814 {
815 PerThing::mul_floor(self, b)
816 }
817
818 pub fn mul_ceil<N>(self, b: N) -> N
820 where
821 N: MultiplyArg + UniqueSaturatedInto<$type>,
822 $type: Into<N>,
823 {
824 PerThing::mul_ceil(self, b)
825 }
826
827 pub fn saturating_reciprocal_mul<N>(self, b: N) -> N
829 where
830 N: ReciprocalArg + UniqueSaturatedInto<$type>,
831 $type: Into<N>,
832 {
833 PerThing::saturating_reciprocal_mul(self, b)
834 }
835
836 pub fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
838 where
839 N: ReciprocalArg + UniqueSaturatedInto<$type>,
840 $type: Into<N>,
841 {
842 PerThing::saturating_reciprocal_mul_floor(self, b)
843 }
844
845 pub fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
847 where
848 N: ReciprocalArg + UniqueSaturatedInto<$type>,
849 $type: Into<N>,
850 {
851 PerThing::saturating_reciprocal_mul_ceil(self, b)
852 }
853
854 pub fn saturating_div(self, rhs: Self, r: Rounding) -> Self {
881 let p = self.0;
882 let q = rhs.0;
883 Self::from_rational_with_rounding(p, q, r).unwrap_or_else(|_| Self::one())
884 }
885 }
886
887 impl Saturating for $name {
888 fn saturating_add(self, rhs: Self) -> Self {
891 Self::from_parts(self.0.saturating_add(rhs.0))
893 }
894
895 fn saturating_sub(self, rhs: Self) -> Self {
898 Self::from_parts(self.0.saturating_sub(rhs.0))
899 }
900
901 fn saturating_mul(self, rhs: Self) -> Self {
904 self * rhs
905 }
906
907 fn saturating_pow(self, exp: usize) -> Self {
910 self.pow(exp)
911 }
912 }
913
914 impl codec::Decode for $name {
915 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
916 let inner = <$type as codec::Decode>::decode(input)?;
917
918 if inner <= <Self as PerThing>::ACCURACY {
919 Ok(Self(inner))
920 } else {
921 Err("Value is greater than allowed maximum!".into())
922 }
923 }
924 }
925
926 impl Bounded for $name {
927 fn min_value() -> Self {
928 <Self as PerThing>::zero()
929 }
930
931 fn max_value() -> Self {
932 <Self as PerThing>::one()
933 }
934 }
935
936 impl ops::Mul for $name {
937 type Output = Self;
938
939 fn mul(self, rhs: Self) -> Self::Output {
940 let a = self.0 as $upper_type;
941 let b = rhs.0 as $upper_type;
942 let m = <$upper_type>::from($max);
943 let parts = a * b / m;
944 Self::from_parts(parts as $type)
946 }
947 }
948
949 impl Pow<usize> for $name {
950 type Output = Self;
951
952 fn pow(mut self, exp: usize) -> Self::Output {
953 if exp == 0 || self.is_one() {
954 return Self::one()
955 }
956
957 let mut result = self;
958 let mut exp = exp - 1;
959 while exp > 0 && !result.is_zero() {
960 if exp % 2 != 0 {
961 result = result * self;
962 exp -= 1;
963 }
964 self = self.square();
965 exp /= 2;
966 }
967 result
968 }
969 }
970
971 impl ops::Div for $name {
972 type Output = Self;
973
974 fn div(self, rhs: Self) -> Self::Output {
975 let p = self.0;
976 let q = rhs.0;
977 Self::from_rational(p, q)
978 }
979 }
980
981 impl Default for $name {
982 fn default() -> Self {
983 <Self as PerThing>::zero()
984 }
985 }
986
987 impl<N> ops::Mul<N> for $name
991 where
992 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
993 + ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
994 $type: Into<N>,
995 {
996 type Output = N;
997 fn mul(self, b: N) -> Self::Output {
998 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::NearestPrefDown)
999 }
1000 }
1001
1002 impl<N> ops::Div<N> for $name where $type: TryFrom<N> {
1003 type Output = Self;
1004 fn div(self, b: N) -> Self::Output {
1005 <$type>::try_from(b).map_or(Self::zero(), |d| Self::from_parts(self.0 / d))
1006 }
1007 }
1008
1009 impl Add<Self> for $name {
1010 type Output = $name;
1011
1012 #[allow(unused_comparisons)]
1014 #[inline]
1015 fn add(self, rhs: Self) -> Self::Output {
1016 let inner = self.deconstruct().add(rhs.deconstruct());
1017 debug_assert!(inner <= $max);
1018 $name::from_parts(inner)
1019 }
1020 }
1021
1022 impl CheckedAdd for $name {
1023 #[allow(unused_comparisons)]
1025 #[inline]
1026 fn checked_add(&self, rhs: &Self) -> Option<Self> {
1027 self.deconstruct()
1028 .checked_add(rhs.deconstruct())
1029 .map(|inner| if inner > $max { None } else { Some($name::from_parts(inner)) })
1030 .flatten()
1031 }
1032 }
1033
1034 impl Sub<Self> for $name {
1035 type Output = $name;
1036
1037 #[inline]
1038 fn sub(self, rhs: Self) -> Self::Output {
1039 $name::from_parts(self.deconstruct().sub(rhs.deconstruct()))
1040 }
1041 }
1042
1043 impl CheckedSub for $name {
1044 #[inline]
1045 fn checked_sub(&self, v: &Self) -> Option<Self> {
1046 self.deconstruct().checked_sub(v.deconstruct()).map($name::from_parts)
1047 }
1048 }
1049
1050 impl SaturatingAdd for $name {
1051 #[inline]
1052 fn saturating_add(&self, v: &Self) -> Self {
1053 $name::from_parts(self.deconstruct().saturating_add(v.deconstruct()))
1054 }
1055 }
1056
1057 impl SaturatingSub for $name {
1058 #[inline]
1059 fn saturating_sub(&self, v: &Self) -> Self {
1060 $name::from_parts(self.deconstruct().saturating_sub(v.deconstruct()))
1061 }
1062 }
1063
1064 impl CheckedMul for $name {
1067 #[inline]
1068 fn checked_mul(&self, rhs: &Self) -> Option<Self> {
1069 Some(*self * *rhs)
1070 }
1071 }
1072
1073 impl $crate::traits::Zero for $name {
1074 fn zero() -> Self {
1075 Self::zero()
1076 }
1077
1078 fn is_zero(&self) -> bool {
1079 self == &Self::zero()
1080 }
1081 }
1082
1083 impl $crate::traits::One for $name {
1084 fn one() -> Self {
1085 Self::one()
1086 }
1087 }
1088
1089 #[cfg(test)]
1090 mod $test_mod {
1091 use codec::{Encode, Decode};
1092 use super::{$name, Saturating, PerThing};
1093 use crate::traits::Zero;
1094
1095 #[test]
1096 fn macro_expanded_correctly() {
1097 assert!(2 * ($max as $upper_type) < <$upper_type>::max_value());
1106 assert!(<$upper_type>::from($max) < <$upper_type>::max_value());
1107
1108 assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value());
1110 assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some());
1111
1112 assert!(<$upper_type>::from($max) * <$upper_type>::from($max) < <$upper_type>::max_value());
1114 }
1115
1116 #[derive(Encode, Decode, PartialEq, Eq, Debug)]
1117 struct WithCompact<T: codec::HasCompact> {
1118 data: T,
1119 }
1120
1121 #[test]
1122 fn has_compact() {
1123 let data = WithCompact { data: $name(1) };
1124 let encoded = data.encode();
1125 assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap());
1126 }
1127
1128 #[test]
1129 fn compact_encoding() {
1130 let tests = [
1131 (0 as $type, 1usize),
1133 (1 as $type, 1usize),
1134 (63, 1),
1135 (64, 2),
1136 (65, 2),
1137 ];
1139 for &(n, l) in &tests {
1140 let compact: codec::Compact<$name> = $name(n).into();
1141 let encoded = compact.encode();
1142 assert_eq!(encoded.len(), l);
1143 let decoded = <codec::Compact<$name>>::decode(&mut & encoded[..])
1144 .unwrap();
1145 let per_thingy: $name = decoded.into();
1146 assert_eq!(per_thingy, $name(n));
1147 }
1148 }
1149
1150 #[test]
1151 fn from_parts_cannot_overflow() {
1152 assert_eq!(<$name>::from_parts($max.saturating_add(1)), <$name>::one());
1153 }
1154
1155 #[test]
1156 fn has_max_encoded_len() {
1157 struct AsMaxEncodedLen<T: codec::MaxEncodedLen> {
1158 _data: T,
1159 }
1160
1161 let _ = AsMaxEncodedLen { _data: $name(1) };
1162 }
1163
1164 #[test]
1165 fn fail_on_invalid_encoded_value() {
1166 let value = <$upper_type>::from($max) * 2;
1167 let casted = value as $type;
1168 let encoded = casted.encode();
1169
1170 if <$upper_type>::from(casted) == value {
1172 assert_eq!(
1173 $name::decode(&mut &encoded[..]),
1174 Err("Value is greater than allowed maximum!".into()),
1175 );
1176 }
1177 }
1178
1179 #[test]
1180 fn per_thing_api_works() {
1181 assert_eq!($name::zero(), $name::from_parts(Zero::zero()));
1183 assert_eq!($name::one(), $name::from_parts($max));
1184 assert_eq!($name::ACCURACY, $max);
1185
1186 assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero()));
1187 assert_eq!($name::from_percent(10), $name::from_parts($max / 10));
1188 assert_eq!($name::from_percent(50), $name::from_parts($max / 2));
1189 assert_eq!($name::from_percent(100), $name::from_parts($max));
1190 assert_eq!($name::from_percent(200), $name::from_parts($max));
1191
1192 assert_eq!($name::from_float(0.0), $name::from_parts(Zero::zero()));
1193 assert_eq!($name::from_float(0.1), $name::from_parts($max / 10));
1194 assert_eq!($name::from_float(1.0), $name::from_parts($max));
1195 assert_eq!($name::from_float(2.0), $name::from_parts($max));
1196 assert_eq!($name::from_float(-1.0), $name::from_parts(Zero::zero()));
1197 }
1198
1199 #[test]
1200 fn percent_trait_impl_works() {
1201 assert_eq!(<$name as PerThing>::from_percent(0), $name::from_parts(Zero::zero()));
1202 assert_eq!(<$name as PerThing>::from_percent(10), $name::from_parts($max / 10));
1203 assert_eq!(<$name as PerThing>::from_percent(50), $name::from_parts($max / 2));
1204 assert_eq!(<$name as PerThing>::from_percent(100), $name::from_parts($max));
1205 assert_eq!(<$name as PerThing>::from_percent(200), $name::from_parts($max));
1206 }
1207
1208 macro_rules! u256ify {
1209 ($val:expr) => {
1210 Into::<U256>::into($val)
1211 };
1212 }
1213
1214 macro_rules! per_thing_mul_test {
1215 ($num_type:tt) => {
1216 assert_eq!(
1218 $name::from_float(1.0) * $num_type::max_value(),
1219 $num_type::max_value()
1220 );
1221 if $max % 100 == 0 {
1222 assert_eq_error_rate!(
1223 $name::from_percent(99) * $num_type::max_value(),
1224 ((Into::<U256>::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type,
1225 1,
1226 );
1227 assert_eq!(
1228 $name::from_float(0.5) * $num_type::max_value(),
1229 $num_type::max_value() / 2,
1230 );
1231 assert_eq_error_rate!(
1232 $name::from_percent(1) * $num_type::max_value(),
1233 $num_type::max_value() / 100,
1234 1,
1235 );
1236 } else {
1237 assert_eq!(
1238 $name::from_float(0.99) * <$num_type>::max_value(),
1239 (
1240 (
1241 u256ify!($name::from_float(0.99).0) *
1242 u256ify!(<$num_type>::max_value()) /
1243 u256ify!($max)
1244 ).as_u128()
1245 ) as $num_type,
1246 );
1247 assert_eq!(
1248 $name::from_float(0.50) * <$num_type>::max_value(),
1249 (
1250 (
1251 u256ify!($name::from_float(0.50).0) *
1252 u256ify!(<$num_type>::max_value()) /
1253 u256ify!($max)
1254 ).as_u128()
1255 ) as $num_type,
1256 );
1257 assert_eq!(
1258 $name::from_float(0.01) * <$num_type>::max_value(),
1259 (
1260 (
1261 u256ify!($name::from_float(0.01).0) *
1262 u256ify!(<$num_type>::max_value()) /
1263 u256ify!($max)
1264 ).as_u128()
1265 ) as $num_type,
1266 );
1267 }
1268
1269 assert_eq!($name::from_float(0.0) * $num_type::max_value(), 0);
1270
1271 assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value());
1273 assert_eq!($name::zero() * $num_type::max_value(), 0);
1274 }
1275 }
1276
1277 #[test]
1278 fn per_thing_mul_works() {
1279 use primitive_types::U256;
1280
1281 assert_eq!(
1283 $name::from_rational(1 as $type, 3) * 30 as $type,
1284 10,
1285 );
1286
1287 $(per_thing_mul_test!($test_units);)*
1288 }
1289
1290 #[test]
1291 fn per_thing_mul_rounds_to_nearest_number() {
1292 assert_eq!($name::from_percent(33) * 10u64, 3);
1293 assert_eq!($name::from_percent(34) * 10u64, 3);
1294 assert_eq!($name::from_percent(35) * 10u64, 3);
1295 assert_eq!($name::from_percent(36) * 10u64, 4);
1296 }
1297
1298 #[test]
1299 fn per_thing_multiplication_with_large_number() {
1300 use primitive_types::U256;
1301 let max_minus_one = $max - 1;
1302 assert_eq_error_rate!(
1303 $name::from_parts(max_minus_one) * std::u128::MAX,
1304 ((Into::<U256>::into(std::u128::MAX) * max_minus_one) / $max).as_u128(),
1305 1,
1306 );
1307 }
1308
1309 macro_rules! per_thing_from_rationale_approx_test {
1310 ($num_type:tt) => {
1311 assert_eq!(
1313 $name::from_rational(1 as $num_type, 0),
1314 $name::one(),
1315 );
1316 assert_eq!(
1317 $name::from_rational(1 as $num_type, 1),
1318 $name::one(),
1319 );
1320 assert_eq_error_rate!(
1321 $name::from_rational(1 as $num_type, 3).0,
1322 $name::from_parts($max / 3).0,
1323 2
1324 );
1325 assert_eq!(
1326 $name::from_rational(1 as $num_type, 10),
1327 $name::from_float(0.10),
1328 );
1329 assert_eq!(
1330 $name::from_rational(1 as $num_type, 4),
1331 $name::from_float(0.25),
1332 );
1333 assert_eq!(
1334 $name::from_rational(1 as $num_type, 4),
1335 $name::from_rational(2 as $num_type, 8),
1336 );
1337 assert_eq_error_rate!(
1339 $name::from_rational(
1340 $num_type::max_value() - 1,
1341 $num_type::max_value()
1342 ).0 as $upper_type,
1343 $name::one().0 as $upper_type,
1344 2,
1345 );
1346 assert_eq_error_rate!(
1347 $name::from_rational(
1348 $num_type::max_value() / 3,
1349 $num_type::max_value()
1350 ).0 as $upper_type,
1351 $name::from_parts($max / 3).0 as $upper_type,
1352 2,
1353 );
1354 assert_eq!(
1355 $name::from_rational(1, $num_type::max_value()),
1356 $name::zero(),
1357 );
1358 };
1359 }
1360
1361 #[test]
1362 fn per_thing_from_rationale_approx_works() {
1363 let max_value = <$upper_type>::from($max);
1366
1367 assert_eq!(
1369 $name::from_rational(max_value - 1, max_value + 1),
1370 $name::from_parts($max - 2),
1371 );
1372 assert_eq!(
1373 $name::from_rational(1, $max - 1),
1374 $name::from_parts(1),
1375 );
1376 assert_eq!(
1377 $name::from_rational(1, $max),
1378 $name::from_parts(1),
1379 );
1380 assert_eq!(
1381 $name::from_rational(2, 2 * max_value - 1),
1382 $name::from_parts(1),
1383 );
1384 assert_eq!(
1385 $name::from_rational(1, max_value + 1),
1386 $name::zero(),
1387 );
1388 assert_eq!(
1389 $name::from_rational(3 * max_value / 2, 3 * max_value),
1390 $name::from_float(0.5),
1391 );
1392
1393 $(per_thing_from_rationale_approx_test!($test_units);)*
1394 }
1395
1396 #[test]
1397 fn per_things_mul_operates_in_output_type() {
1398 assert_eq!($name::from_float(0.5) * 100u64, 50u64);
1400 assert_eq!($name::from_float(0.5) * 100u128, 50u128);
1401 }
1402
1403 #[test]
1404 fn per_thing_saturating_op_works() {
1405 assert_eq_error_rate!(
1406 $name::from_float(0.5).saturating_add($name::from_float(0.4)).0 as $upper_type,
1407 $name::from_float(0.9).0 as $upper_type,
1408 2,
1409 );
1410 assert_eq_error_rate!(
1411 $name::from_float(0.5).saturating_add($name::from_float(0.5)).0 as $upper_type,
1412 $name::one().0 as $upper_type,
1413 2,
1414 );
1415 assert_eq!(
1416 $name::from_float(0.6).saturating_add($name::from_float(0.5)),
1417 $name::one(),
1418 );
1419
1420 assert_eq_error_rate!(
1421 $name::from_float(0.6).saturating_sub($name::from_float(0.5)).0 as $upper_type,
1422 $name::from_float(0.1).0 as $upper_type,
1423 2,
1424 );
1425 assert_eq!(
1426 $name::from_float(0.6).saturating_sub($name::from_float(0.6)),
1427 $name::from_float(0.0),
1428 );
1429 assert_eq!(
1430 $name::from_float(0.6).saturating_sub($name::from_float(0.7)),
1431 $name::from_float(0.0),
1432 );
1433
1434 assert_eq_error_rate!(
1435 $name::from_float(0.5).saturating_mul($name::from_float(0.5)).0 as $upper_type,
1436 $name::from_float(0.25).0 as $upper_type,
1437 2,
1438 );
1439 assert_eq_error_rate!(
1440 $name::from_float(0.2).saturating_mul($name::from_float(0.2)).0 as $upper_type,
1441 $name::from_float(0.04).0 as $upper_type,
1442 2,
1443 );
1444 assert_eq_error_rate!(
1445 $name::from_float(0.1).saturating_mul($name::from_float(0.1)).0 as $upper_type,
1446 $name::from_float(0.01).0 as $upper_type,
1447 1,
1448 );
1449 }
1450
1451 #[test]
1452 fn per_thing_square_works() {
1453 assert_eq!($name::from_float(1.0).square(), $name::from_float(1.0));
1454 assert_eq!($name::from_float(0.5).square(), $name::from_float(0.25));
1455 assert_eq!($name::from_float(0.1).square(), $name::from_float(0.01));
1456 assert_eq!(
1457 $name::from_float(0.02).square(),
1458 $name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type)
1459 );
1460 }
1461
1462 #[test]
1463 fn per_things_div_works() {
1464 assert_eq_error_rate!(
1466 ($name::from_float(0.1) / $name::from_float(0.20)).0 as $upper_type,
1467 $name::from_float(0.50).0 as $upper_type,
1468 2,
1469 );
1470 assert_eq_error_rate!(
1471 ($name::from_float(0.1) / $name::from_float(0.10)).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(0.1) / $name::from_float(0.0)).0 as $upper_type,
1477 $name::from_float(1.0).0 as $upper_type,
1478 2,
1479 );
1480
1481 assert_eq_error_rate!(
1483 ($name::from_float(0.10) / $name::from_float(0.05)).0 as $upper_type,
1484 $name::from_float(1.0).0 as $upper_type,
1485 2,
1486 );
1487 assert_eq_error_rate!(
1488 ($name::from_float(1.0) / $name::from_float(0.5)).0 as $upper_type,
1489 $name::from_float(1.0).0 as $upper_type,
1490 2,
1491 );
1492 }
1493
1494 #[test]
1495 fn saturating_pow_works() {
1496 assert_eq!(
1498 $name::from_parts($max / 2).saturating_pow(0),
1499 $name::from_parts($max),
1500 );
1501
1502 assert_eq!(
1504 $name::from_parts($max / 2).saturating_pow(1),
1505 $name::from_parts($max / 2),
1506 );
1507
1508 assert_eq!(
1510 $name::from_parts($max / 2).saturating_pow(2),
1511 $name::from_parts($max / 2).square(),
1512 );
1513
1514 for n in 1..=16 {
1516 assert_eq!(
1517 $name::from_parts($max / 2).saturating_pow(n),
1518 $name::from_parts(($max as u128 / 2u128.pow(n as u32)) as $type),
1519 );
1520 }
1521
1522 assert_eq!(
1524 $name::from_parts(0).saturating_pow(3),
1525 $name::from_parts(0),
1526 );
1527
1528 assert_eq!(
1530 $name::from_parts($max).saturating_pow(3),
1531 $name::from_parts($max),
1532 );
1533
1534 assert_eq!(
1536 $name::from_parts($max / 2).saturating_pow(2usize.pow(31)),
1537 $name::from_parts(0),
1538 );
1539 }
1540
1541 #[test]
1542 fn saturating_reciprocal_mul_works() {
1543 assert_eq!(
1545 $name::from_parts($max).saturating_reciprocal_mul(<$type>::from(10u8)),
1546 10,
1547 );
1548 assert_eq!(
1550 $name::from_parts($max / 2).saturating_reciprocal_mul(<$type>::from(10u8)),
1551 20,
1552 );
1553 assert_eq!(
1555 $name::from_parts(1).saturating_reciprocal_mul($max),
1556 <$type>::max_value(),
1557 );
1558 assert_eq!(
1560 $name::from_percent(60).saturating_reciprocal_mul(<$type>::from(10u8)),
1561 17,
1562 );
1563 assert_eq!(
1565 $name::from_percent(60).saturating_reciprocal_mul_floor(<$type>::from(10u8)),
1566 16,
1567 );
1568 assert_eq!(
1570 $name::from_percent(61).saturating_reciprocal_mul(<$type>::from(10u8)),
1571 16,
1572 );
1573 assert_eq!(
1575 $name::from_percent(61).saturating_reciprocal_mul_ceil(<$type>::from(10u8)),
1576 17,
1577 );
1578 }
1579
1580 #[test]
1581 fn saturating_truncating_mul_works() {
1582 assert_eq!(
1583 $name::from_percent(49).mul_floor(10 as $type),
1584 4,
1585 );
1586 let a: $upper_type = $name::from_percent(50).mul_floor(($max as $upper_type).pow(2));
1587 let b: $upper_type = ($max as $upper_type).pow(2) / 2;
1588 if $max % 2 == 0 {
1589 assert_eq!(a, b);
1590 } else {
1591 assert!(b - a < ($max as $upper_type).pow(2) / 100 as $upper_type);
1593 }
1594 }
1595
1596 #[test]
1597 fn rational_mul_correction_works() {
1598 assert_eq!(
1599 super::rational_mul_correction::<$type, $name>(
1600 <$type>::max_value(),
1601 <$type>::max_value(),
1602 <$type>::max_value(),
1603 super::Rounding::NearestPrefDown,
1604 ),
1605 0,
1606 );
1607 assert_eq!(
1608 super::rational_mul_correction::<$type, $name>(
1609 <$type>::max_value() - 1,
1610 <$type>::max_value(),
1611 <$type>::max_value(),
1612 super::Rounding::NearestPrefDown,
1613 ),
1614 <$type>::max_value() - 1,
1615 );
1616 assert_eq!(
1617 super::rational_mul_correction::<$upper_type, $name>(
1618 ((<$type>::max_value() - 1) as $upper_type).pow(2),
1619 <$type>::max_value(),
1620 <$type>::max_value(),
1621 super::Rounding::NearestPrefDown,
1622 ),
1623 1,
1624 );
1625 assert_eq!(
1627 super::rational_mul_correction::<$upper_type, $name>(
1628 (<$type>::max_value() as $upper_type).pow(2) - 1,
1629 <$type>::max_value(),
1630 <$type>::max_value(),
1631 super::Rounding::NearestPrefDown,
1632 ),
1633 <$upper_type>::from(<$type>::max_value() - 1),
1634 );
1635 assert_eq!(
1637 super::rational_mul_correction::<$upper_type, $name>(
1638 (<$type>::max_value() as $upper_type).pow(2),
1639 <$type>::max_value(),
1640 2 as $type,
1641 super::Rounding::NearestPrefDown,
1642 ),
1643 <$type>::max_value() as $upper_type / 2,
1644 );
1645 assert_eq!(
1647 super::rational_mul_correction::<$upper_type, $name>(
1648 (<$type>::max_value() as $upper_type).pow(2) - 1,
1649 2 as $type,
1650 <$type>::max_value(),
1651 super::Rounding::NearestPrefDown,
1652 ),
1653 2,
1654 );
1655 assert_eq!(
1657 super::rational_mul_correction::<$upper_type, $name>(
1658 (<$type>::max_value() as $upper_type).pow(2) - 1,
1659 2 as $type,
1660 <$type>::max_value(),
1661 super::Rounding::Down,
1662 ),
1663 1,
1664 );
1665 }
1666
1667 #[test]
1668 #[allow(unused)]
1669 fn const_fns_work() {
1670 const C1: $name = $name::from_percent(50);
1671 const C2: $name = $name::one();
1672 const C3: $name = $name::zero();
1673 const C4: $name = $name::from_parts(1);
1674
1675 const C5: bool = C1.deconstruct() == 0;
1677 }
1678
1679 #[test]
1680 fn compact_decoding_saturate_when_beyond_accuracy() {
1681 use num_traits::Bounded;
1682 use codec::Compact;
1683
1684 let p = Compact::<$name>::decode(&mut &Compact(<$type>::max_value()).encode()[..])
1685 .unwrap();
1686 assert_eq!((p.0).0, $max);
1687 assert_eq!($name::from(p), $name::max_value());
1688 }
1689
1690 #[allow(unused_imports)]
1691 use super::*;
1692
1693 #[test]
1694 fn test_add_basic() {
1695 assert_eq!($name::from_parts(1) + $name::from_parts(1), $name::from_parts(2));
1696 assert_eq!($name::from_parts(10) + $name::from_parts(10), $name::from_parts(20));
1697 }
1698
1699 #[test]
1700 fn test_basic_checked_add() {
1701 assert_eq!(
1702 $name::from_parts(1).checked_add(&$name::from_parts(1)),
1703 Some($name::from_parts(2))
1704 );
1705 assert_eq!(
1706 $name::from_parts(10).checked_add(&$name::from_parts(10)),
1707 Some($name::from_parts(20))
1708 );
1709 assert_eq!(
1710 $name::from_parts(<$type>::MAX).checked_add(&$name::from_parts(<$type>::MAX)),
1711 None
1712 );
1713 assert_eq!(
1714 $name::from_parts($max).checked_add(&$name::from_parts(1)),
1715 None
1716 );
1717 }
1718
1719 #[test]
1720 fn test_basic_saturating_add() {
1721 assert_eq!(
1722 $name::from_parts(1).saturating_add($name::from_parts(1)),
1723 $name::from_parts(2)
1724 );
1725 assert_eq!(
1726 $name::from_parts(10).saturating_add($name::from_parts(10)),
1727 $name::from_parts(20)
1728 );
1729 assert_eq!(
1730 $name::from_parts(<$type>::MAX).saturating_add($name::from_parts(<$type>::MAX)),
1731 $name::from_parts(<$type>::MAX)
1732 );
1733 }
1734
1735 #[test]
1736 fn test_basic_sub() {
1737 assert_eq!($name::from_parts(2) - $name::from_parts(1), $name::from_parts(1));
1738 assert_eq!($name::from_parts(20) - $name::from_parts(10), $name::from_parts(10));
1739 }
1740
1741 #[test]
1742 fn test_basic_checked_sub() {
1743 assert_eq!(
1744 $name::from_parts(2).checked_sub(&$name::from_parts(1)),
1745 Some($name::from_parts(1))
1746 );
1747 assert_eq!(
1748 $name::from_parts(20).checked_sub(&$name::from_parts(10)),
1749 Some($name::from_parts(10))
1750 );
1751 assert_eq!($name::from_parts(0).checked_sub(&$name::from_parts(1)), None);
1752 }
1753
1754 #[test]
1755 fn test_basic_saturating_sub() {
1756 assert_eq!(
1757 $name::from_parts(2).saturating_sub($name::from_parts(1)),
1758 $name::from_parts(1)
1759 );
1760 assert_eq!(
1761 $name::from_parts(20).saturating_sub($name::from_parts(10)),
1762 $name::from_parts(10)
1763 );
1764 assert_eq!(
1765 $name::from_parts(0).saturating_sub($name::from_parts(1)),
1766 $name::from_parts(0)
1767 );
1768 }
1769
1770 #[test]
1771 fn test_basic_checked_mul() {
1772 assert_eq!(
1773 $name::from_parts($max).checked_mul(&$name::from_parts($max)),
1774 Some($name::from_percent(100))
1775 );
1776 assert_eq!(
1777 $name::from_percent(100).checked_mul(&$name::from_percent(100)),
1778 Some($name::from_percent(100))
1779 );
1780 assert_eq!(
1781 $name::from_percent(50).checked_mul(&$name::from_percent(26)),
1782 Some($name::from_percent(13))
1783 );
1784 assert_eq!(
1785 $name::from_percent(0).checked_mul(&$name::from_percent(0)),
1786 Some($name::from_percent(0))
1787 );
1788 }
1789 }
1790 };
1791}
1792
1793macro_rules! implement_per_thing_with_perthousand {
1794 (
1795 $name:ident,
1796 $test_mod:ident,
1797 $pt_test_mod:ident,
1798 [$($test_units:tt),+],
1799 $max:tt,
1800 $type:ty,
1801 $upper_type:ty,
1802 $title:expr $(,)?
1803 ) => {
1804 implement_per_thing! {
1805 $name, $test_mod, [ $( $test_units ),+ ], $max, $type, $upper_type, $title,
1806 }
1807 impl $name {
1808 pub const fn from_perthousand(x: $type) -> Self {
1812 Self(([x, 1000][(x > 1000) as usize] as $upper_type * $max as $upper_type / 1000) as $type)
1813 }
1814 }
1815 #[cfg(test)]
1816 mod $pt_test_mod {
1817 use super::$name;
1818 use crate::traits::Zero;
1819
1820 #[test]
1821 fn from_perthousand_works() {
1822 assert_eq!($name::from_perthousand(00), $name::from_parts(Zero::zero()));
1824 assert_eq!($name::from_perthousand(100), $name::from_parts($max / 10));
1825 assert_eq!($name::from_perthousand(1000), $name::from_parts($max));
1826 assert_eq!($name::from_perthousand(2000), $name::from_parts($max));
1827 }
1828
1829 #[test]
1830 #[allow(unused)]
1831 fn const_fns_work() {
1832 const C1: $name = $name::from_perthousand(500);
1833 }
1834 }
1835 }
1836}
1837
1838#[test]
1839fn from_rational_with_rounding_works_in_extreme_case() {
1840 use Rounding::*;
1841 for &r in [Down, NearestPrefDown, NearestPrefUp, Up].iter() {
1842 Percent::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1843 Percent::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1844 Percent::from_rational_with_rounding(1, u16::max_value(), r).unwrap();
1845 Percent::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1846 Percent::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1847 Percent::from_rational_with_rounding(u16::max_value() - 1, u16::max_value(), r).unwrap();
1848 PerU16::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1849 PerU16::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1850 PerU16::from_rational_with_rounding(1, u16::max_value(), r).unwrap();
1851 PerU16::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1852 PerU16::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1853 PerU16::from_rational_with_rounding(u16::max_value() - 1, u16::max_value(), r).unwrap();
1854 Permill::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1855 Permill::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1856 Permill::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1857 Permill::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1858 Perbill::from_rational_with_rounding(1, u64::max_value(), r).unwrap();
1859 Perbill::from_rational_with_rounding(1, u32::max_value(), r).unwrap();
1860 Perbill::from_rational_with_rounding(u64::max_value() - 1, u64::max_value(), r).unwrap();
1861 Perbill::from_rational_with_rounding(u32::max_value() - 1, u32::max_value(), r).unwrap();
1862 }
1863}
1864
1865#[test]
1866fn from_rational_with_rounding_breakage() {
1867 let n = 372633774963620730670986667244911905u128;
1868 let d = 512593663333074177468745541591173060u128;
1869 let q = Perquintill::from_rational_with_rounding(n, d, Rounding::Down).unwrap();
1870 assert!(q * d <= n);
1871}
1872
1873#[test]
1874fn from_rational_with_rounding_breakage_2() {
1875 let n = 36893488147419103230u128;
1876 let d = 36893488147419103630u128;
1877 let q = Perquintill::from_rational_with_rounding(n, d, Rounding::Up).unwrap();
1878 assert!(q * d >= n);
1879}
1880
1881implement_per_thing!(Percent, test_per_cent, [u32, u64, u128], 100u8, u8, u16, "_Percent_",);
1882implement_per_thing_with_perthousand!(
1883 PerU16,
1884 test_peru16,
1885 test_peru16_extra,
1886 [u32, u64, u128],
1887 65535_u16,
1888 u16,
1889 u32,
1890 "_Parts per 65535_",
1891);
1892implement_per_thing_with_perthousand!(
1893 Permill,
1894 test_permill,
1895 test_permill_extra,
1896 [u32, u64, u128],
1897 1_000_000u32,
1898 u32,
1899 u64,
1900 "_Parts per Million_",
1901);
1902implement_per_thing_with_perthousand!(
1903 Perbill,
1904 test_perbill,
1905 test_perbill_extra,
1906 [u32, u64, u128],
1907 1_000_000_000u32,
1908 u32,
1909 u64,
1910 "_Parts per Billion_",
1911);
1912implement_per_thing_with_perthousand!(
1913 Perquintill,
1914 test_perquintill,
1915 test_perquintill_extra,
1916 [u64, u128],
1917 1_000_000_000_000_000_000u64,
1918 u64,
1919 u128,
1920 "_Parts per Quintillion_",
1921);