Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Attempt to remove the where bounds in arithmetic. #7933

Merged
7 commits merged into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ use frame_support::{
};
use pallet_session::historical;
use sp_runtime::{
Percent, Perbill, PerU16, InnerOf, RuntimeDebug, DispatchError,
Percent, Perbill, PerU16, RuntimeDebug, DispatchError,
curve::PiecewiseLinear,
traits::{
Convert, Zero, StaticLookup, CheckedSub, Saturating, SaturatedConversion,
Expand Down Expand Up @@ -2991,10 +2991,7 @@ impl<T: Config> Module<T> {
/// No storage item is updated.
pub fn do_phragmen<Accuracy: PerThing128>(
iterations: usize,
) -> Option<PrimitiveElectionResult<T::AccountId, Accuracy>>
where
ExtendedBalance: From<InnerOf<Accuracy>>,
{
) -> Option<PrimitiveElectionResult<T::AccountId, Accuracy>> {
let weight_of = Self::slashable_balance_of_fn();
let mut all_nominators: Vec<(T::AccountId, VoteWeight, Vec<T::AccountId>)> = Vec::new();
let mut all_validators = Vec::new();
Expand Down
7 changes: 2 additions & 5 deletions frame/staking/src/offchain_election.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ use sp_npos_elections::{
ExtendedBalance, CompactSolution,
};
use sp_runtime::{
offchain::storage::StorageValueRef, traits::TrailingZeroInput, PerThing, RuntimeDebug,
offchain::storage::StorageValueRef, traits::TrailingZeroInput, RuntimeDebug,
};
use sp_std::{convert::TryInto, prelude::*};

Expand Down Expand Up @@ -326,10 +326,7 @@ pub fn prepare_submission<T: Config>(
) -> Result<
(Vec<ValidatorIndex>, CompactAssignments, ElectionScore, ElectionSize),
OffchainElectionError,
>
where
ExtendedBalance: From<<OffchainAccuracy as PerThing>::Inner>,
{
> {
// make sure that the snapshot is available.
let snapshot_validators =
<Module<T>>::snapshot_validators().ok_or(OffchainElectionError::SnapshotUnavailable)?;
Expand Down
23 changes: 10 additions & 13 deletions primitives/arithmetic/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 normalized = normalize(inners.as_ref(), targeted_sum.deconstruct().into())?;

Ok(
normalized
.into_iter()
.map(|i: UpperOf<P>| P::from_parts(i.saturated_into()))
.collect()
)
let uppers =
self.iter().map(|p| <UpperOf<P>>::from(p.clone().deconstruct())).collect::<Vec<_>>();

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::<P::Inner>()))
.collect())
}
}

Expand Down
155 changes: 89 additions & 66 deletions primitives/arithmetic/src/per_things.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TLDR ^^^^^^^^^^^^^^^^^^^^^^


/// 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;
Expand All @@ -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
Expand All @@ -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
kianenigma marked this conversation as resolved.
Show resolved Hide resolved
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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand All @@ -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)
}
Expand Down Expand 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.
Expand All @@ -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>(
Expand All @@ -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();
Expand All @@ -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`.
Expand Down Expand Up @@ -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
};
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand Down
Loading