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