1#[cfg(feature = "std")]
19use serde::{Serialize, Deserialize};
20
21use tetcore_std::{ops, fmt, prelude::*, convert::TryInto};
22use codec::{Encode, CompactAs};
23use crate::traits::{
24 SaturatedConversion, UniqueSaturatedInto, Saturating, BaseArithmetic, Bounded, Zero, Unsigned,
25 One,
26};
27use debug_derive::RuntimeDebug;
28
29pub type InnerOf<P> = <P as PerThing>::Inner;
31
32pub type UpperOf<P> = <P as PerThing>::Upper;
34
35pub trait PerThing:
38 Sized + Saturating + Copy + Default + Eq + PartialEq + Ord + PartialOrd + Bounded + fmt::Debug
39{
40 type Inner: BaseArithmetic + Unsigned + Copy + Into<u128> + fmt::Debug;
42
43 type Upper: BaseArithmetic
46 + Copy
47 + From<Self::Inner>
48 + TryInto<Self::Inner>
49 + UniqueSaturatedInto<Self::Inner>
50 + Unsigned
51 + fmt::Debug;
52
53 const ACCURACY: Self::Inner;
55
56 fn zero() -> Self { Self::from_parts(Self::Inner::zero()) }
58
59 fn is_zero(&self) -> bool { self.deconstruct() == Self::Inner::zero() }
61
62 fn one() -> Self { Self::from_parts(Self::ACCURACY) }
64
65 fn is_one(&self) -> bool { self.deconstruct() == Self::ACCURACY }
67
68 fn from_percent(x: Self::Inner) -> Self {
71 let a: Self::Inner = x.min(100.into());
72 let b: Self::Inner = 100.into();
73 Self::from_rational_approximation::<Self::Inner>(a, b)
74 }
75
76 fn square(self) -> Self {
78 let p = Self::Upper::from(self.deconstruct());
79 let q = Self::Upper::from(Self::ACCURACY);
80 Self::from_rational_approximation::<Self::Upper>(p * p, q * q)
81 }
82
83 fn mul_floor<N>(self, b: N) -> N
99 where
100 N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
101 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
102 Self::Inner: Into<N>,
103 {
104 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
105 }
106
107 fn mul_ceil<N>(self, b: N) -> N
123 where
124 N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
125 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
126 Self::Inner: Into<N>
127 {
128 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
129 }
130
131 fn saturating_reciprocal_mul<N>(self, b: N) -> N
141 where
142 N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
143 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
144 Unsigned,
145 Self::Inner: Into<N>,
146 {
147 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Nearest)
148 }
149
150 fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
163 where
164 N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
165 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
166 Unsigned,
167 Self::Inner: Into<N>,
168 {
169 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
170 }
171
172 fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
185 where
186 N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
187 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
188 Unsigned,
189 Self::Inner: Into<N>,
190 {
191 saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
192 }
193
194 fn deconstruct(self) -> Self::Inner;
196
197 fn from_parts(parts: Self::Inner) -> Self;
199
200 #[cfg(feature = "std")]
202 fn from_fraction(x: f64) -> Self;
203
204 fn from_rational_approximation<N>(p: N, q: N) -> Self
223 where
224 N: Clone + Ord + TryInto<Self::Inner> + TryInto<Self::Upper> +
225 ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
226 Self::Inner: Into<N>;
227}
228
229enum Rounding {
234 Up,
235 Down,
236 Nearest,
237}
238
239fn saturating_reciprocal_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
242where
243 N: Clone + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
244 Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Saturating + Unsigned,
245 P: PerThing,
246 P::Inner: Into<N>,
247{
248 let maximum: N = P::ACCURACY.into();
249 let c = rational_mul_correction::<N, P>(
250 x.clone(),
251 P::ACCURACY,
252 part,
253 rounding,
254 );
255 (x / part.into()).saturating_mul(maximum).saturating_add(c)
256}
257
258fn overflow_prune_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
260where
261 N: Clone + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
262 Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
263 P: PerThing,
264 P::Inner: Into<N>,
265{
266 let maximum: N = P::ACCURACY.into();
267 let part_n: N = part.into();
268 let c = rational_mul_correction::<N, P>(
269 x.clone(),
270 part,
271 P::ACCURACY,
272 rounding,
273 );
274 (x / maximum) * part_n + c
275}
276
277fn rational_mul_correction<N, P>(x: N, numer: P::Inner, denom: P::Inner, rounding: Rounding) -> N
282where
283 N: UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
284 Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
285 P: PerThing,
286 P::Inner: Into<N>
287{
288 let numer_upper = P::Upper::from(numer);
289 let denom_n: N = denom.into();
290 let denom_upper = P::Upper::from(denom);
291 let rem = x.rem(denom_n);
292 let rem_inner = rem.saturated_into::<P::Inner>();
294 let rem_mul_upper = P::Upper::from(rem_inner) * numer_upper;
296 let mut rem_mul_div_inner = (rem_mul_upper / denom_upper).saturated_into::<P::Inner>();
299 match rounding {
300 Rounding::Down => {},
302 Rounding::Up => if rem_mul_upper % denom_upper > 0.into() {
304 rem_mul_div_inner = rem_mul_div_inner + 1.into();
306 },
307 Rounding::Nearest => if rem_mul_upper % denom_upper > denom_upper / 2.into() {
310 rem_mul_div_inner = rem_mul_div_inner + 1.into();
312 },
313 }
314 rem_mul_div_inner.into()
315}
316
317macro_rules! implement_per_thing {
318 (
319 $name:ident,
320 $test_mod:ident,
321 [$($test_units:tt),+],
322 $max:tt,
323 $type:ty,
324 $upper_type:ty,
325 $title:expr $(,)?
326 ) => {
327 #[doc = $title]
330 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
331 #[derive(Encode, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug)]
332 pub struct $name($type);
333
334 impl CompactAs for $name {
337 type As = $type;
338 fn encode_as(&self) -> &Self::As {
339 &self.0
340 }
341 fn decode_from(x: Self::As) -> Result<Self, codec::Error> {
342 Ok(Self::from_parts(x))
344 }
345 }
346
347 impl From<codec::Compact<$name>> for $name {
348 fn from(x: codec::Compact<$name>) -> $name {
349 x.0
350 }
351 }
352
353 impl PerThing for $name {
354 type Inner = $type;
355 type Upper = $upper_type;
356
357 const ACCURACY: Self::Inner = $max;
358
359 fn deconstruct(self) -> Self::Inner { self.0 }
361
362 fn from_parts(parts: Self::Inner) -> Self { Self(parts.min($max)) }
364
365 #[cfg(feature = "std")]
367 fn from_fraction(x: f64) -> Self {
368 Self::from_parts((x.max(0.).min(1.) * $max as f64) as Self::Inner)
369 }
370
371 fn from_rational_approximation<N>(p: N, q: N) -> Self
372 where
373 N: Clone + Ord + TryInto<Self::Inner> + TryInto<Self::Upper>
374 + ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned
375 + Zero + One,
376 Self::Inner: Into<N>,
377 {
378 let div_ceil = |x: N, f: N| -> N {
379 let mut o = x.clone() / f.clone();
380 let r = x.rem(f.clone());
381 if r > N::zero() {
382 o = o + N::one();
383 }
384 o
385 };
386
387 let q: N = q.max((1 as Self::Inner).into());
389 let p: N = p.min(q.clone());
391
392 let factor: N = div_ceil(q.clone(), $max.into()).max((1 as Self::Inner).into());
393
394 let q_reduce: $type = (q.clone() / factor.clone())
396 .try_into()
397 .map_err(|_| "Failed to convert")
398 .expect(
399 "q / ceil(q/$max) < $max. Macro prevents any type being created that \
400 does not satisfy this; qed"
401 );
402 let p_reduce: $type = (p / factor)
403 .try_into()
404 .map_err(|_| "Failed to convert")
405 .expect(
406 "q / ceil(q/$max) < $max. Macro prevents any type being created that \
407 does not satisfy this; qed"
408 );
409
410 let part =
413 p_reduce as $upper_type
414 * <$upper_type>::from($max)
415 / q_reduce as $upper_type;
416
417 $name(part as Self::Inner)
418 }
419 }
420
421 impl $name {
422 #[allow(unused_comparisons)]
428 pub const fn from_parts(parts: $type) -> Self {
429 Self([parts, $max][(parts > $max) as usize])
430 }
431
432 pub const fn from_percent(x: $type) -> Self {
436 Self(([x, 100][(x > 100) as usize] as $upper_type * $max as $upper_type / 100) as $type)
437 }
438
439 pub const fn one() -> Self {
441 Self::from_parts($max)
442 }
443
444 pub fn is_one(&self) -> bool {
446 PerThing::is_one(self)
447 }
448
449 pub const fn zero() -> Self {
451 Self::from_parts(0)
452 }
453
454 pub fn is_zero(&self) -> bool {
456 PerThing::is_zero(self)
457 }
458
459 pub const fn deconstruct(self) -> $type {
461 self.0
462 }
463
464 pub fn square(self) -> Self {
466 PerThing::square(self)
467 }
468
469 #[cfg(feature = "std")]
471 pub fn from_fraction(x: f64) -> Self {
472 <Self as PerThing>::from_fraction(x)
473 }
474
475 pub fn from_rational_approximation<N>(p: N, q: N) -> Self
477 where N: Clone + Ord + TryInto<$type> +
478 TryInto<$upper_type> + ops::Div<N, Output=N> + ops::Rem<N, Output=N> +
479 ops::Add<N, Output=N> + Unsigned,
480 $type: Into<N>,
481 {
482 <Self as PerThing>::from_rational_approximation(p, q)
483 }
484
485 pub fn mul_floor<N>(self, b: N) -> N
487 where
488 N: Clone + UniqueSaturatedInto<$type> +
489 ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
490 ops::Add<N, Output=N> + Unsigned,
491 $type: Into<N>,
492
493 {
494 PerThing::mul_floor(self, b)
495 }
496
497 pub fn mul_ceil<N>(self, b: N) -> N
499 where
500 N: Clone + UniqueSaturatedInto<$type> +
501 ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
502 ops::Add<N, Output=N> + Unsigned,
503 $type: Into<N>,
504 {
505 PerThing::mul_ceil(self, b)
506 }
507
508 pub fn saturating_reciprocal_mul<N>(self, b: N) -> N
510 where
511 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
512 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
513 Saturating + Unsigned,
514 $type: Into<N>,
515 {
516 PerThing::saturating_reciprocal_mul(self, b)
517 }
518
519 pub fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
521 where
522 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
523 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
524 Saturating + Unsigned,
525 $type: Into<N>,
526 {
527 PerThing::saturating_reciprocal_mul_floor(self, b)
528 }
529
530 pub fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
532 where
533 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
534 ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
535 Saturating + Unsigned,
536 $type: Into<N>,
537 {
538 PerThing::saturating_reciprocal_mul_ceil(self, b)
539 }
540 }
541
542 impl Saturating for $name {
543 fn saturating_add(self, rhs: Self) -> Self {
546 Self::from_parts(self.0.saturating_add(rhs.0))
548 }
549
550 fn saturating_sub(self, rhs: Self) -> Self {
553 Self::from_parts(self.0.saturating_sub(rhs.0))
554 }
555
556 fn saturating_mul(self, rhs: Self) -> Self {
559 let a = self.0 as $upper_type;
560 let b = rhs.0 as $upper_type;
561 let m = <$upper_type>::from($max);
562 let parts = a * b / m;
563 Self::from_parts(parts as $type)
565 }
566
567 fn saturating_pow(self, exp: usize) -> Self {
570 if self.is_zero() || self.is_one() {
571 self
572 } else {
573 let p = <$name as PerThing>::Upper::from(self.deconstruct());
574 let q = <$name as PerThing>::Upper::from(Self::ACCURACY);
575 let mut s = Self::one();
576 for _ in 0..exp {
577 if s.is_zero() {
578 break;
579 } else {
580 s = Self::from_rational_approximation(
583 <$name as PerThing>::Upper::from(s.deconstruct()) * p,
584 q * q,
585 );
586 }
587 }
588 s
589 }
590 }
591 }
592
593 impl codec::Decode for $name {
594 fn decode<I: codec::Input>(input: &mut I) -> Result<Self, codec::Error> {
595 let inner = <$type as codec::Decode>::decode(input)?;
596
597 if inner <= <Self as PerThing>::ACCURACY {
598 Ok(Self(inner))
599 } else {
600 Err("Value is greater than allowed maximum!".into())
601 }
602 }
603 }
604
605 impl crate::traits::Bounded for $name {
606 fn min_value() -> Self {
607 <Self as PerThing>::zero()
608 }
609
610 fn max_value() -> Self {
611 <Self as PerThing>::one()
612 }
613 }
614
615 impl ops::Div for $name {
616 type Output = Self;
617
618 fn div(self, rhs: Self) -> Self::Output {
619 let p = self.0;
620 let q = rhs.0;
621 Self::from_rational_approximation(p, q)
622 }
623 }
624
625 impl Default for $name {
626 fn default() -> Self {
627 <Self as PerThing>::zero()
628 }
629 }
630
631 impl<N> ops::Mul<N> for $name
635 where
636 N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
637 + ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
638 $type: Into<N>,
639 {
640 type Output = N;
641 fn mul(self, b: N) -> Self::Output {
642 overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Nearest)
643 }
644 }
645
646 #[cfg(test)]
647 mod $test_mod {
648 use codec::{Encode, Decode};
649 use super::{$name, Saturating, RuntimeDebug, PerThing};
650 use crate::traits::Zero;
651
652 #[test]
653 fn macro_expanded_correctly() {
654 assert!(2 * ($max as $upper_type) < <$upper_type>::max_value());
663 assert!(<$upper_type>::from($max) < <$upper_type>::max_value());
664
665 assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value());
667 assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some());
668
669 assert!(<$upper_type>::from($max) * <$upper_type>::from($max) < <$upper_type>::max_value());
671 }
672
673 #[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)]
674 struct WithCompact<T: codec::HasCompact> {
675 data: T,
676 }
677
678 #[test]
679 fn has_compact() {
680 let data = WithCompact { data: $name(1) };
681 let encoded = data.encode();
682 assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap());
683 }
684
685 #[test]
686 fn compact_encoding() {
687 let tests = [
688 (0 as $type, 1usize),
690 (1 as $type, 1usize),
691 (63, 1),
692 (64, 2),
693 (65, 2),
694 ];
696 for &(n, l) in &tests {
697 let compact: codec::Compact<$name> = $name(n).into();
698 let encoded = compact.encode();
699 assert_eq!(encoded.len(), l);
700 let decoded = <codec::Compact<$name>>::decode(&mut & encoded[..])
701 .unwrap();
702 let per_thingy: $name = decoded.into();
703 assert_eq!(per_thingy, $name(n));
704 }
705 }
706
707 #[test]
708 fn fail_on_invalid_encoded_value() {
709 let value = <$upper_type>::from($max) * 2;
710 let casted = value as $type;
711 let encoded = casted.encode();
712
713 if <$upper_type>::from(casted) == value {
715 assert_eq!(
716 $name::decode(&mut &encoded[..]),
717 Err("Value is greater than allowed maximum!".into()),
718 );
719 }
720 }
721
722 #[test]
723 fn per_thing_api_works() {
724 assert_eq!($name::zero(), $name::from_parts(Zero::zero()));
726 assert_eq!($name::one(), $name::from_parts($max));
727 assert_eq!($name::ACCURACY, $max);
728
729 assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero()));
730 assert_eq!($name::from_percent(10), $name::from_parts($max / 10));
731 assert_eq!($name::from_percent(50), $name::from_parts($max / 2));
732 assert_eq!($name::from_percent(100), $name::from_parts($max));
733 assert_eq!($name::from_percent(200), $name::from_parts($max));
734
735 assert_eq!($name::from_fraction(0.0), $name::from_parts(Zero::zero()));
736 assert_eq!($name::from_fraction(0.1), $name::from_parts($max / 10));
737 assert_eq!($name::from_fraction(1.0), $name::from_parts($max));
738 assert_eq!($name::from_fraction(2.0), $name::from_parts($max));
739 assert_eq!($name::from_fraction(-1.0), $name::from_parts(Zero::zero()));
740 }
741
742 #[test]
743 fn percent_trait_impl_works() {
744 assert_eq!(<$name as PerThing>::from_percent(0), $name::from_parts(Zero::zero()));
745 assert_eq!(<$name as PerThing>::from_percent(10), $name::from_parts($max / 10));
746 assert_eq!(<$name as PerThing>::from_percent(50), $name::from_parts($max / 2));
747 assert_eq!(<$name as PerThing>::from_percent(100), $name::from_parts($max));
748 assert_eq!(<$name as PerThing>::from_percent(200), $name::from_parts($max));
749 }
750
751 macro_rules! u256ify {
752 ($val:expr) => {
753 Into::<U256>::into($val)
754 };
755 }
756
757 macro_rules! per_thing_mul_test {
758 ($num_type:tt) => {
759 assert_eq!(
761 $name::from_fraction(1.0) * $num_type::max_value(),
762 $num_type::max_value()
763 );
764 if $max % 100 == 0 {
765 assert_eq_error_rate!(
766 $name::from_percent(99) * $num_type::max_value(),
767 ((Into::<U256>::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type,
768 1,
769 );
770 assert_eq!(
771 $name::from_fraction(0.5) * $num_type::max_value(),
772 $num_type::max_value() / 2,
773 );
774 assert_eq_error_rate!(
775 $name::from_percent(1) * $num_type::max_value(),
776 $num_type::max_value() / 100,
777 1,
778 );
779 } else {
780 assert_eq!(
781 $name::from_fraction(0.99) * <$num_type>::max_value(),
782 (
783 (
784 u256ify!($name::from_fraction(0.99).0) *
785 u256ify!(<$num_type>::max_value()) /
786 u256ify!($max)
787 ).as_u128()
788 ) as $num_type,
789 );
790 assert_eq!(
791 $name::from_fraction(0.50) * <$num_type>::max_value(),
792 (
793 (
794 u256ify!($name::from_fraction(0.50).0) *
795 u256ify!(<$num_type>::max_value()) /
796 u256ify!($max)
797 ).as_u128()
798 ) as $num_type,
799 );
800 assert_eq!(
801 $name::from_fraction(0.01) * <$num_type>::max_value(),
802 (
803 (
804 u256ify!($name::from_fraction(0.01).0) *
805 u256ify!(<$num_type>::max_value()) /
806 u256ify!($max)
807 ).as_u128()
808 ) as $num_type,
809 );
810 }
811
812 assert_eq!($name::from_fraction(0.0) * $num_type::max_value(), 0);
813
814 assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value());
816 assert_eq!($name::zero() * $num_type::max_value(), 0);
817 }
818 }
819
820 #[test]
821 fn per_thing_mul_works() {
822 use tetsy_primitive_types::U256;
823
824 assert_eq!(
826 $name::from_rational_approximation(1 as $type, 3) * 30 as $type,
827 10,
828 );
829
830 $(per_thing_mul_test!($test_units);)*
831 }
832
833 #[test]
834 fn per_thing_mul_rounds_to_nearest_number() {
835 assert_eq!($name::from_fraction(0.33) * 10u64, 3);
836 assert_eq!($name::from_fraction(0.34) * 10u64, 3);
837 assert_eq!($name::from_fraction(0.35) * 10u64, 3);
838 assert_eq!($name::from_fraction(0.36) * 10u64, 4);
839 }
840
841 #[test]
842 fn per_thing_multiplication_with_large_number() {
843 use tetsy_primitive_types::U256;
844 let max_minus_one = $max - 1;
845 assert_eq_error_rate!(
846 $name::from_parts(max_minus_one) * std::u128::MAX,
847 ((Into::<U256>::into(std::u128::MAX) * max_minus_one) / $max).as_u128(),
848 1,
849 );
850 }
851
852 macro_rules! per_thing_from_rationale_approx_test {
853 ($num_type:tt) => {
854 assert_eq!(
856 $name::from_rational_approximation(1 as $num_type, 0),
857 $name::one(),
858 );
859 assert_eq!(
860 $name::from_rational_approximation(1 as $num_type, 1),
861 $name::one(),
862 );
863 assert_eq_error_rate!(
864 $name::from_rational_approximation(1 as $num_type, 3).0,
865 $name::from_parts($max / 3).0,
866 2
867 );
868 assert_eq!(
869 $name::from_rational_approximation(1 as $num_type, 10),
870 $name::from_fraction(0.10),
871 );
872 assert_eq!(
873 $name::from_rational_approximation(1 as $num_type, 4),
874 $name::from_fraction(0.25),
875 );
876 assert_eq!(
877 $name::from_rational_approximation(1 as $num_type, 4),
878 $name::from_rational_approximation(2 as $num_type, 8),
879 );
880 assert_eq_error_rate!(
882 $name::from_rational_approximation(
883 $num_type::max_value() - 1,
884 $num_type::max_value()
885 ).0 as $upper_type,
886 $name::one().0 as $upper_type,
887 2,
888 );
889 assert_eq_error_rate!(
890 $name::from_rational_approximation(
891 $num_type::max_value() / 3,
892 $num_type::max_value()
893 ).0 as $upper_type,
894 $name::from_parts($max / 3).0 as $upper_type,
895 2,
896 );
897 assert_eq!(
898 $name::from_rational_approximation(1, $num_type::max_value()),
899 $name::zero(),
900 );
901 };
902 }
903
904 #[test]
905 fn per_thing_from_rationale_approx_works() {
906 let max_value = <$upper_type>::from($max);
909
910 assert_eq!(
912 $name::from_rational_approximation(max_value - 1, max_value + 1),
913 $name::from_parts($max - 2),
914 );
915 assert_eq!(
916 $name::from_rational_approximation(1, $max - 1),
917 $name::from_parts(1),
918 );
919 assert_eq!(
920 $name::from_rational_approximation(1, $max),
921 $name::from_parts(1),
922 );
923 assert_eq!(
924 $name::from_rational_approximation(2, 2 * max_value - 1),
925 $name::from_parts(1),
926 );
927 assert_eq!(
928 $name::from_rational_approximation(1, max_value + 1),
929 $name::zero(),
930 );
931 assert_eq!(
932 $name::from_rational_approximation(3 * max_value / 2, 3 * max_value),
933 $name::from_fraction(0.5),
934 );
935
936 $(per_thing_from_rationale_approx_test!($test_units);)*
937 }
938
939 #[test]
940 fn per_things_mul_operates_in_output_type() {
941 assert_eq!($name::from_fraction(0.5) * 100u64, 50u64);
943 assert_eq!($name::from_fraction(0.5) * 100u128, 50u128);
944 }
945
946 #[test]
947 fn per_thing_saturating_op_works() {
948 assert_eq_error_rate!(
949 $name::from_fraction(0.5).saturating_add($name::from_fraction(0.4)).0 as $upper_type,
950 $name::from_fraction(0.9).0 as $upper_type,
951 2,
952 );
953 assert_eq_error_rate!(
954 $name::from_fraction(0.5).saturating_add($name::from_fraction(0.5)).0 as $upper_type,
955 $name::one().0 as $upper_type,
956 2,
957 );
958 assert_eq!(
959 $name::from_fraction(0.6).saturating_add($name::from_fraction(0.5)),
960 $name::one(),
961 );
962
963 assert_eq_error_rate!(
964 $name::from_fraction(0.6).saturating_sub($name::from_fraction(0.5)).0 as $upper_type,
965 $name::from_fraction(0.1).0 as $upper_type,
966 2,
967 );
968 assert_eq!(
969 $name::from_fraction(0.6).saturating_sub($name::from_fraction(0.6)),
970 $name::from_fraction(0.0),
971 );
972 assert_eq!(
973 $name::from_fraction(0.6).saturating_sub($name::from_fraction(0.7)),
974 $name::from_fraction(0.0),
975 );
976
977 assert_eq_error_rate!(
978 $name::from_fraction(0.5).saturating_mul($name::from_fraction(0.5)).0 as $upper_type,
979 $name::from_fraction(0.25).0 as $upper_type,
980 2,
981 );
982 assert_eq_error_rate!(
983 $name::from_fraction(0.2).saturating_mul($name::from_fraction(0.2)).0 as $upper_type,
984 $name::from_fraction(0.04).0 as $upper_type,
985 2,
986 );
987 assert_eq_error_rate!(
988 $name::from_fraction(0.1).saturating_mul($name::from_fraction(0.1)).0 as $upper_type,
989 $name::from_fraction(0.01).0 as $upper_type,
990 1,
991 );
992 }
993
994 #[test]
995 fn per_thing_square_works() {
996 assert_eq!($name::from_fraction(1.0).square(), $name::from_fraction(1.0));
997 assert_eq!($name::from_fraction(0.5).square(), $name::from_fraction(0.25));
998 assert_eq!($name::from_fraction(0.1).square(), $name::from_fraction(0.01));
999 assert_eq!(
1000 $name::from_fraction(0.02).square(),
1001 $name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type)
1002 );
1003 }
1004
1005 #[test]
1006 fn per_things_div_works() {
1007 assert_eq_error_rate!(
1009 ($name::from_fraction(0.1) / $name::from_fraction(0.20)).0 as $upper_type,
1010 $name::from_fraction(0.50).0 as $upper_type,
1011 2,
1012 );
1013 assert_eq_error_rate!(
1014 ($name::from_fraction(0.1) / $name::from_fraction(0.10)).0 as $upper_type,
1015 $name::from_fraction(1.0).0 as $upper_type,
1016 2,
1017 );
1018 assert_eq_error_rate!(
1019 ($name::from_fraction(0.1) / $name::from_fraction(0.0)).0 as $upper_type,
1020 $name::from_fraction(1.0).0 as $upper_type,
1021 2,
1022 );
1023
1024 assert_eq_error_rate!(
1026 ($name::from_fraction(0.10) / $name::from_fraction(0.05)).0 as $upper_type,
1027 $name::from_fraction(1.0).0 as $upper_type,
1028 2,
1029 );
1030 assert_eq_error_rate!(
1031 ($name::from_fraction(1.0) / $name::from_fraction(0.5)).0 as $upper_type,
1032 $name::from_fraction(1.0).0 as $upper_type,
1033 2,
1034 );
1035 }
1036
1037 #[test]
1038 fn saturating_pow_works() {
1039 assert_eq!(
1041 $name::from_parts($max / 2).saturating_pow(0),
1042 $name::from_parts($max),
1043 );
1044
1045 assert_eq!(
1047 $name::from_parts($max / 2).saturating_pow(1),
1048 $name::from_parts($max / 2),
1049 );
1050
1051 assert_eq!(
1053 $name::from_parts($max / 2).saturating_pow(2),
1054 $name::from_parts($max / 2).square(),
1055 );
1056
1057 assert_eq!(
1059 $name::from_parts($max / 2).saturating_pow(3),
1060 $name::from_parts($max / 8),
1061 );
1062
1063 assert_eq!(
1065 $name::from_parts(0).saturating_pow(3),
1066 $name::from_parts(0),
1067 );
1068
1069 assert_eq!(
1071 $name::from_parts($max).saturating_pow(3),
1072 $name::from_parts($max),
1073 );
1074
1075 assert_eq!(
1077 $name::from_parts($max / 2).saturating_pow(2usize.pow(31)),
1078 $name::from_parts(0),
1079 );
1080 }
1081
1082 #[test]
1083 fn saturating_reciprocal_mul_works() {
1084 assert_eq!(
1086 $name::from_parts($max).saturating_reciprocal_mul(<$type>::from(10u8)),
1087 10,
1088 );
1089 assert_eq!(
1091 $name::from_parts($max / 2).saturating_reciprocal_mul(<$type>::from(10u8)),
1092 20,
1093 );
1094 assert_eq!(
1096 $name::from_parts(1).saturating_reciprocal_mul($max),
1097 <$type>::max_value(),
1098 );
1099 assert_eq!(
1101 $name::from_percent(60).saturating_reciprocal_mul(<$type>::from(10u8)),
1102 17,
1103 );
1104 assert_eq!(
1106 $name::from_percent(60).saturating_reciprocal_mul_floor(<$type>::from(10u8)),
1107 16,
1108 );
1109 assert_eq!(
1111 $name::from_percent(61).saturating_reciprocal_mul(<$type>::from(10u8)),
1112 16,
1113 );
1114 assert_eq!(
1116 $name::from_percent(61).saturating_reciprocal_mul_ceil(<$type>::from(10u8)),
1117 17,
1118 );
1119 }
1120
1121 #[test]
1122 fn saturating_truncating_mul_works() {
1123 assert_eq!(
1124 $name::from_percent(49).mul_floor(10 as $type),
1125 4,
1126 );
1127 let a: $upper_type = $name::from_percent(50).mul_floor(($max as $upper_type).pow(2));
1128 let b: $upper_type = ($max as $upper_type).pow(2) / 2;
1129 if $max % 2 == 0 {
1130 assert_eq!(a, b);
1131 } else {
1132 assert!(b - a < ($max as $upper_type).pow(2) / 100 as $upper_type);
1134 }
1135 }
1136
1137 #[test]
1138 fn rational_mul_correction_works() {
1139 assert_eq!(
1140 super::rational_mul_correction::<$type, $name>(
1141 <$type>::max_value(),
1142 <$type>::max_value(),
1143 <$type>::max_value(),
1144 super::Rounding::Nearest,
1145 ),
1146 0,
1147 );
1148 assert_eq!(
1149 super::rational_mul_correction::<$type, $name>(
1150 <$type>::max_value() - 1,
1151 <$type>::max_value(),
1152 <$type>::max_value(),
1153 super::Rounding::Nearest,
1154 ),
1155 <$type>::max_value() - 1,
1156 );
1157 assert_eq!(
1158 super::rational_mul_correction::<$upper_type, $name>(
1159 ((<$type>::max_value() - 1) as $upper_type).pow(2),
1160 <$type>::max_value(),
1161 <$type>::max_value(),
1162 super::Rounding::Nearest,
1163 ),
1164 1,
1165 );
1166 assert_eq!(
1168 super::rational_mul_correction::<$upper_type, $name>(
1169 (<$type>::max_value() as $upper_type).pow(2) - 1,
1170 <$type>::max_value(),
1171 <$type>::max_value(),
1172 super::Rounding::Nearest,
1173 ),
1174 <$upper_type>::from((<$type>::max_value() - 1)),
1175 );
1176 assert_eq!(
1178 super::rational_mul_correction::<$upper_type, $name>(
1179 (<$type>::max_value() as $upper_type).pow(2),
1180 <$type>::max_value(),
1181 2 as $type,
1182 super::Rounding::Nearest,
1183 ),
1184 <$type>::max_value() as $upper_type / 2,
1185 );
1186 assert_eq!(
1188 super::rational_mul_correction::<$upper_type, $name>(
1189 (<$type>::max_value() as $upper_type).pow(2) - 1,
1190 2 as $type,
1191 <$type>::max_value(),
1192 super::Rounding::Nearest,
1193 ),
1194 2,
1195 );
1196 assert_eq!(
1198 super::rational_mul_correction::<$upper_type, $name>(
1199 (<$type>::max_value() as $upper_type).pow(2) - 1,
1200 2 as $type,
1201 <$type>::max_value(),
1202 super::Rounding::Down,
1203 ),
1204 1,
1205 );
1206 }
1207
1208 #[test]
1209 #[allow(unused)]
1210 fn const_fns_work() {
1211 const C1: $name = $name::from_percent(50);
1212 const C2: $name = $name::one();
1213 const C3: $name = $name::zero();
1214 const C4: $name = $name::from_parts(1);
1215
1216 const C5: bool = C1.deconstruct() == 0;
1218 }
1219
1220 #[test]
1221 fn compact_decoding_saturate_when_beyond_accuracy() {
1222 use num_traits::Bounded;
1223 use codec::Compact;
1224
1225 let p = Compact::<$name>::decode(&mut &Compact(<$type>::max_value()).encode()[..])
1226 .unwrap();
1227 assert_eq!((p.0).0, $max);
1228 assert_eq!($name::from(p), $name::max_value());
1229 }
1230 }
1231 };
1232}
1233
1234macro_rules! implement_per_thing_with_perthousand {
1235 (
1236 $name:ident,
1237 $test_mod:ident,
1238 $pt_test_mod:ident,
1239 [$($test_units:tt),+],
1240 $max:tt,
1241 $type:ty,
1242 $upper_type:ty,
1243 $title:expr $(,)?
1244 ) => {
1245 implement_per_thing! {
1246 $name, $test_mod, [ $( $test_units ),+ ], $max, $type, $upper_type, $title,
1247 }
1248 impl $name {
1249 pub const fn from_perthousand(x: $type) -> Self {
1253 Self(([x, 1000][(x > 1000) as usize] as $upper_type * $max as $upper_type / 1000) as $type)
1254 }
1255 }
1256 #[cfg(test)]
1257 mod $pt_test_mod {
1258 use super::$name;
1259 use crate::traits::Zero;
1260
1261 #[test]
1262 fn from_perthousand_works() {
1263 assert_eq!($name::from_perthousand(00), $name::from_parts(Zero::zero()));
1265 assert_eq!($name::from_perthousand(100), $name::from_parts($max / 10));
1266 assert_eq!($name::from_perthousand(1000), $name::from_parts($max));
1267 assert_eq!($name::from_perthousand(2000), $name::from_parts($max));
1268 }
1269
1270 #[test]
1271 #[allow(unused)]
1272 fn const_fns_work() {
1273 const C1: $name = $name::from_perthousand(500);
1274 }
1275 }
1276 }
1277}
1278
1279implement_per_thing!(
1280 Percent,
1281 test_per_cent,
1282 [u32, u64, u128],
1283 100u8,
1284 u8,
1285 u16,
1286 "_Percent_",
1287);
1288implement_per_thing_with_perthousand!(
1289 PerU16,
1290 test_peru16,
1291 test_peru16_extra,
1292 [u32, u64, u128],
1293 65535_u16,
1294 u16,
1295 u32,
1296 "_Parts per 65535_",
1297);
1298implement_per_thing_with_perthousand!(
1299 Permill,
1300 test_permill,
1301 test_permill_extra,
1302 [u32, u64, u128],
1303 1_000_000u32,
1304 u32,
1305 u64,
1306 "_Parts per Million_",
1307);
1308implement_per_thing_with_perthousand!(
1309 Perbill,
1310 test_perbill,
1311 test_perbill_extra,
1312 [u32, u64, u128],
1313 1_000_000_000u32,
1314 u32,
1315 u64,
1316 "_Parts per Billion_",
1317);
1318implement_per_thing_with_perthousand!(
1319 Perquintill,
1320 test_perquintill,
1321 test_perquintill_extra,
1322 [u64, u128],
1323 1_000_000_000_000_000_000u64,
1324 u64,
1325 u128,
1326 "_Parts per Quintillion_",
1327);