Attempt to remove the where bounds in arithmetic. (#7933)

* Attempt to remove the where bounds.

* Fix further and further.

* Format better.

* Update primitives/npos-elections/src/lib.rs

* fix build

* remove unused
This commit is contained in:
Kian Paimani
2021-01-21 09:39:30 +00:00
committed by GitHub
parent 9031c35114
commit 0dd8cd6277
11 changed files with 125 additions and 139 deletions
+8 -11
View File
@@ -114,19 +114,16 @@ impl_normalize_for_numeric!(u8, u16, u32, u64, u128);
impl<P: PerThing> Normalizable<P> for Vec<P> {
fn normalize(&self, targeted_sum: P) -> Result<Vec<P>, &'static str> {
let inners = self
.iter()
.map(|p| p.clone().deconstruct().into())
.collect::<Vec<_>>();
let uppers =
self.iter().map(|p| <UpperOf<P>>::from(p.clone().deconstruct())).collect::<Vec<_>>();
let normalized = normalize(inners.as_ref(), targeted_sum.deconstruct().into())?;
let normalized =
normalize(uppers.as_ref(), <UpperOf<P>>::from(targeted_sum.deconstruct()))?;
Ok(
normalized
.into_iter()
.map(|i: UpperOf<P>| P::from_parts(i.saturated_into()))
.collect()
)
Ok(normalized
.into_iter()
.map(|i: UpperOf<P>| P::from_parts(i.saturated_into::<P::Inner>()))
.collect())
}
}
@@ -22,6 +22,7 @@ use sp_std::{ops, fmt, prelude::*, convert::TryInto};
use codec::{Encode, CompactAs};
use crate::traits::{
SaturatedConversion, UniqueSaturatedInto, Saturating, BaseArithmetic, Bounded, Zero, Unsigned,
One,
};
use sp_debug_derive::RuntimeDebug;
@@ -37,13 +38,17 @@ pub trait PerThing:
Sized + Saturating + Copy + Default + Eq + PartialEq + Ord + PartialOrd + Bounded + fmt::Debug
{
/// The data type used to build this per-thingy.
type Inner: BaseArithmetic + Unsigned + Copy + fmt::Debug;
type Inner: BaseArithmetic + Unsigned + Copy + Into<u128> + fmt::Debug;
/// A data type larger than `Self::Inner`, used to avoid overflow in some computations.
/// It must be able to compute `ACCURACY^2`.
type Upper:
BaseArithmetic + Copy + From<Self::Inner> + TryInto<Self::Inner> +
UniqueSaturatedInto<Self::Inner> + Unsigned + fmt::Debug;
type Upper: BaseArithmetic
+ Copy
+ From<Self::Inner>
+ TryInto<Self::Inner>
+ UniqueSaturatedInto<Self::Inner>
+ Unsigned
+ fmt::Debug;
/// The accuracy of this type.
const ACCURACY: Self::Inner;
@@ -65,14 +70,14 @@ pub trait PerThing:
fn from_percent(x: Self::Inner) -> Self {
let a: Self::Inner = x.min(100.into());
let b: Self::Inner = 100.into();
Self::from_rational_approximation(a, b)
Self::from_rational_approximation::<Self::Inner>(a, b)
}
/// Return the product of multiplication of this value by itself.
fn square(self) -> Self {
let p = Self::Upper::from(self.deconstruct());
let q = Self::Upper::from(Self::ACCURACY);
Self::from_rational_approximation(p * p, q * q)
Self::from_rational_approximation::<Self::Upper>(p * p, q * q)
}
/// Multiplication that always rounds down to a whole number. The standard `Mul` rounds to the
@@ -91,8 +96,10 @@ pub trait PerThing:
/// # }
/// ```
fn mul_floor<N>(self, b: N) -> N
where N: Clone + From<Self::Inner> + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned
where
N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
Self::Inner: Into<N>,
{
overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
}
@@ -113,8 +120,10 @@ pub trait PerThing:
/// # }
/// ```
fn mul_ceil<N>(self, b: N) -> N
where N: Clone + From<Self::Inner> + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned
where
N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
Self::Inner: Into<N>
{
overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
}
@@ -129,9 +138,11 @@ pub trait PerThing:
/// # }
/// ```
fn saturating_reciprocal_mul<N>(self, b: N) -> N
where N: Clone + From<Self::Inner> + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
where
N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned,
Self::Inner: Into<N>,
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Nearest)
}
@@ -149,9 +160,11 @@ pub trait PerThing:
/// # }
/// ```
fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
where N: Clone + From<Self::Inner> + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
where
N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned,
Self::Inner: Into<N>,
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
}
@@ -169,9 +182,11 @@ pub trait PerThing:
/// # }
/// ```
fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
where N: Clone + From<Self::Inner> + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
where
N: Clone + UniqueSaturatedInto<Self::Inner> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned,
Self::Inner: Into<N>,
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
}
@@ -199,14 +214,16 @@ pub trait PerThing:
/// # fn main () {
/// // 989/100 is technically closer to 99%.
/// assert_eq!(
/// Percent::from_rational_approximation(989u64, 1000),
/// Percent::from_parts(98),
/// );
/// Percent::from_rational_approximation(989u64, 1000),
/// Percent::from_parts(98),
/// );
/// # }
/// ```
fn from_rational_approximation<N>(p: N, q: N) -> Self
where N: Clone + Ord + From<Self::Inner> + TryInto<Self::Inner> + TryInto<Self::Upper> +
ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned;
where
N: Clone + Ord + TryInto<Self::Inner> + TryInto<Self::Upper> +
ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
Self::Inner: Into<N>;
}
/// The rounding method to use.
@@ -221,15 +238,12 @@ enum Rounding {
/// Saturating reciprocal multiplication. Compute `x / self`, saturating at the numeric
/// bounds instead of overflowing.
fn saturating_reciprocal_mul<N, P>(
x: N,
part: P::Inner,
rounding: Rounding,
) -> N
fn saturating_reciprocal_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
where
N: Clone + From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
N: Clone + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Saturating + Unsigned,
P: PerThing,
P::Inner: Into<N>,
{
let maximum: N = P::ACCURACY.into();
let c = rational_mul_correction::<N, P>(
@@ -242,15 +256,12 @@ where
}
/// Overflow-prune multiplication. Accurately multiply a value by `self` without overflowing.
fn overflow_prune_mul<N, P>(
x: N,
part: P::Inner,
rounding: Rounding,
) -> N
fn overflow_prune_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
where
N: Clone + From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
N: Clone + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
P: PerThing,
P::Inner: Into<N>,
{
let maximum: N = P::ACCURACY.into();
let part_n: N = part.into();
@@ -267,19 +278,15 @@ where
///
/// Take the remainder of `x / denom` and multiply by `numer / denom`. The result can be added
/// to `x / denom * numer` for an accurate result.
fn rational_mul_correction<N, P>(
x: N,
numer: P::Inner,
denom: P::Inner,
rounding: Rounding,
) -> N
fn rational_mul_correction<N, P>(x: N, numer: P::Inner, denom: P::Inner, rounding: Rounding) -> N
where
N: From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
N: UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
P: PerThing,
P::Inner: Into<N>
{
let numer_upper = P::Upper::from(numer);
let denom_n = N::from(denom);
let denom_n: N = denom.into();
let denom_upper = P::Upper::from(denom);
let rem = x.rem(denom_n);
// `rem` is less than `denom`, which fits in `P::Inner`.
@@ -362,14 +369,17 @@ macro_rules! implement_per_thing {
}
fn from_rational_approximation<N>(p: N, q: N) -> Self
where N: Clone + Ord + From<Self::Inner> + TryInto<Self::Inner> + TryInto<Self::Upper>
+ ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned
where
N: Clone + Ord + TryInto<Self::Inner> + TryInto<Self::Upper>
+ ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned
+ Zero + One,
Self::Inner: Into<N>,
{
let div_ceil = |x: N, f: N| -> N {
let mut o = x.clone() / f.clone();
let r = x.rem(f.clone());
if r > N::from(0) {
o = o + N::from(1);
if r > N::zero() {
o = o + N::one();
}
o
};
@@ -464,54 +474,66 @@ macro_rules! implement_per_thing {
/// See [`PerThing::from_rational_approximation`].
pub fn from_rational_approximation<N>(p: N, q: N) -> Self
where N: Clone + Ord + From<$type> + TryInto<$type> +
where N: Clone + Ord + TryInto<$type> +
TryInto<$upper_type> + ops::Div<N, Output=N> + ops::Rem<N, Output=N> +
ops::Add<N, Output=N> + Unsigned
ops::Add<N, Output=N> + Unsigned,
$type: Into<N>,
{
<Self as PerThing>::from_rational_approximation(p, q)
}
/// See [`PerThing::mul_floor`].
pub fn mul_floor<N>(self, b: N) -> N
where N: Clone + From<$type> + UniqueSaturatedInto<$type> +
ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
ops::Add<N, Output=N> + Unsigned
where
N: Clone + UniqueSaturatedInto<$type> +
ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
ops::Add<N, Output=N> + Unsigned,
$type: Into<N>,
{
PerThing::mul_floor(self, b)
}
/// See [`PerThing::mul_ceil`].
pub fn mul_ceil<N>(self, b: N) -> N
where N: Clone + From<$type> + UniqueSaturatedInto<$type> +
ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
ops::Add<N, Output=N> + Unsigned
where
N: Clone + UniqueSaturatedInto<$type> +
ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
ops::Add<N, Output=N> + Unsigned,
$type: Into<N>,
{
PerThing::mul_ceil(self, b)
}
/// See [`PerThing::saturating_reciprocal_mul`].
pub fn saturating_reciprocal_mul<N>(self, b: N) -> N
where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned
where
N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned,
$type: Into<N>,
{
PerThing::saturating_reciprocal_mul(self, b)
}
/// See [`PerThing::saturating_reciprocal_mul_floor`].
pub fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned
where
N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned,
$type: Into<N>,
{
PerThing::saturating_reciprocal_mul_floor(self, b)
}
/// See [`PerThing::saturating_reciprocal_mul_ceil`].
pub fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
where N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned
where
N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N> +
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> +
Saturating + Unsigned,
$type: Into<N>,
{
PerThing::saturating_reciprocal_mul_ceil(self, b)
}
@@ -611,8 +633,9 @@ macro_rules! implement_per_thing {
/// This is tailored to be used with a balance type.
impl<N> ops::Mul<N> for $name
where
N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
N: Clone + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
+ ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
$type: Into<N>,
{
type Output = N;
fn mul(self, b: N) -> Self::Output {