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