Bound Unsigned when signed is not supported. (#6367)

* bound unsigned when necessary

* convert more type to AtLeast32BitUnsigned

* Update primitives/arithmetic/src/traits.rs

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>

* doc refactor

* line reorganize

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Guillaume Thiolliere
2020-06-25 11:30:20 +02:00
committed by GitHub
parent b17ccf24a8
commit 44fb311f1f
16 changed files with 84 additions and 74 deletions
@@ -94,7 +94,7 @@ 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>
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned
{
overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
}
@@ -116,7 +116,7 @@ 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>
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned
{
overflow_prune_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
}
@@ -132,7 +132,8 @@ 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
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Nearest)
}
@@ -151,7 +152,8 @@ 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
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Down)
}
@@ -170,7 +172,8 @@ 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
ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Saturating +
Unsigned
{
saturating_reciprocal_mul::<N, Self>(b, self.deconstruct(), Rounding::Up)
}
@@ -198,14 +201,14 @@ pub trait PerThing:
/// # fn main () {
/// // 989/100 is technically closer to 99%.
/// assert_eq!(
/// Percent::from_rational_approximation(989, 1000),
/// 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>;
ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned;
}
/// The rounding method to use.
@@ -227,7 +230,7 @@ fn saturating_reciprocal_mul<N, P>(
) -> N
where
N: Clone + From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Saturating,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Saturating + Unsigned,
P: PerThing,
{
let maximum: N = P::ACCURACY.into();
@@ -248,7 +251,7 @@ fn overflow_prune_mul<N, P>(
) -> N
where
N: Clone + From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N>,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
P: PerThing,
{
let maximum: N = P::ACCURACY.into();
@@ -274,7 +277,7 @@ fn rational_mul_correction<N, P>(
) -> N
where
N: From<P::Inner> + UniqueSaturatedInto<P::Inner> + ops::Div<N, Output=N> + ops::Mul<N,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N>,
Output=N> + ops::Add<N, Output=N> + ops::Rem<N, Output=N> + Unsigned,
P: PerThing,
{
let numer_upper = P::Upper::from(numer);
@@ -335,14 +338,15 @@ macro_rules! implement_per_thing {
/// Build this type from a number of parts per thing.
fn from_parts(parts: Self::Inner) -> Self { Self(parts.min($max)) }
/// NOTE: saturate to 0 or 1 if x is beyond `[0, 1]`
#[cfg(feature = "std")]
fn from_fraction(x: f64) -> Self {
Self::from_parts((x * $max as f64) as Self::Inner)
Self::from_parts((x.max(0.).min(1.) * $max as f64) as Self::Inner)
}
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>
+ ops::Div<N, Output=N> + ops::Rem<N, Output=N> + ops::Add<N, Output=N> + Unsigned
{
let div_ceil = |x: N, f: N| -> N {
let mut o = x.clone() / f.clone();
@@ -445,7 +449,8 @@ macro_rules! implement_per_thing {
pub fn from_rational_approximation<N>(p: N, q: N) -> Self
where N: Clone + Ord + From<$type> + TryInto<$type> +
TryInto<$upper_type> + ops::Div<N, Output=N> + ops::Rem<N, Output=N> +
ops::Add<N, Output=N> {
ops::Add<N, Output=N> + Unsigned
{
<Self as PerThing>::from_rational_approximation(p, q)
}
@@ -453,7 +458,8 @@ macro_rules! implement_per_thing {
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> {
ops::Add<N, Output=N> + Unsigned
{
PerThing::mul_floor(self, b)
}
@@ -461,7 +467,8 @@ macro_rules! implement_per_thing {
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> {
ops::Add<N, Output=N> + Unsigned
{
PerThing::mul_ceil(self, b)
}
@@ -469,7 +476,8 @@ macro_rules! implement_per_thing {
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 {
Saturating + Unsigned
{
PerThing::saturating_reciprocal_mul(self, b)
}
@@ -477,7 +485,8 @@ macro_rules! implement_per_thing {
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 {
Saturating + Unsigned
{
PerThing::saturating_reciprocal_mul_floor(self, b)
}
@@ -485,7 +494,8 @@ macro_rules! implement_per_thing {
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 {
Saturating + Unsigned
{
PerThing::saturating_reciprocal_mul_ceil(self, b)
}
}
@@ -585,7 +595,7 @@ macro_rules! implement_per_thing {
impl<N> ops::Mul<N> for $name
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>,
+ ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N> + Unsigned,
{
type Output = N;
fn mul(self, b: N) -> Self::Output {
@@ -684,6 +694,8 @@ macro_rules! implement_per_thing {
assert_eq!($name::from_fraction(0.0), $name::from_parts(Zero::zero()));
assert_eq!($name::from_fraction(0.1), $name::from_parts($max / 10));
assert_eq!($name::from_fraction(1.0), $name::from_parts($max));
assert_eq!($name::from_fraction(2.0), $name::from_parts($max));
assert_eq!($name::from_fraction(-1.0), $name::from_parts(Zero::zero()));
}
macro_rules! u256ify {
@@ -79,6 +79,11 @@ pub trait AtLeast32Bit: BaseArithmetic + From<u16> + From<u32> {}
impl<T: BaseArithmetic + From<u16> + From<u32>> AtLeast32Bit for T {}
/// A meta trait for arithmetic. Same as [`AtLeast32Bit `], but also bounded to be unsigned.
pub trait AtLeast32BitUnsigned: AtLeast32Bit + Unsigned {}
impl<T: AtLeast32Bit + Unsigned> AtLeast32BitUnsigned for T {}
/// Just like `From` except that if the source value is too big to fit into the destination type
/// then it'll saturate the destination.
pub trait UniqueSaturatedFrom<T: Sized>: Sized {
+3 -3
View File
@@ -17,7 +17,7 @@
//! Provides some utilities to define a piecewise linear function.
use crate::{Perbill, traits::{AtLeast32Bit, SaturatedConversion}};
use crate::{Perbill, traits::{AtLeast32BitUnsigned, SaturatedConversion}};
use core::ops::Sub;
/// Piecewise Linear function in [0, 1] -> [0, 1].
@@ -36,7 +36,7 @@ fn abs_sub<N: Ord + Sub<Output=N> + Clone>(a: N, b: N) -> N where {
impl<'a> PiecewiseLinear<'a> {
/// Compute `f(n/d)*d` with `n <= d`. This is useful to avoid loss of precision.
pub fn calculate_for_fraction_times_denominator<N>(&self, n: N, d: N) -> N where
N: AtLeast32Bit + Clone
N: AtLeast32BitUnsigned + Clone
{
let n = n.min(d.clone());
@@ -80,7 +80,7 @@ impl<'a> PiecewiseLinear<'a> {
// This is guaranteed not to overflow on whatever values nor lose precision.
// `q` must be superior to zero.
fn multiply_by_rational_saturating<N>(value: N, p: u32, q: u32) -> N
where N: AtLeast32Bit + Clone
where N: AtLeast32BitUnsigned + Clone
{
let q = q.max(1);
@@ -21,7 +21,7 @@
use serde::{Deserialize, Serialize};
use crate::codec::{Decode, Encode, Codec, Input, Output, HasCompact, EncodeAsRef, Error};
use crate::traits::{
self, Member, AtLeast32Bit, SimpleBitOps, Hash as HashT,
self, Member, AtLeast32BitUnsigned, SimpleBitOps, Hash as HashT,
MaybeSerializeDeserialize, MaybeSerialize, MaybeDisplay,
MaybeMallocSizeOf,
};
@@ -123,7 +123,7 @@ impl<Number, Hash> codec::EncodeLike for Header<Number, Hash> where
impl<Number, Hash> traits::Header for Header<Number, Hash> where
Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + MaybeDisplay +
AtLeast32Bit + Codec + Copy + Into<U256> + TryFrom<U256> + sp_std::str::FromStr +
AtLeast32BitUnsigned + Codec + Copy + Into<U256> + TryFrom<U256> + sp_std::str::FromStr +
MaybeMallocSizeOf,
Hash: HashT,
Hash::Output: Default + sp_std::hash::Hash + Copy + Member + Ord +
@@ -171,7 +171,8 @@ impl<Number, Hash> traits::Header for Header<Number, Hash> where
}
impl<Number, Hash> Header<Number, Hash> where
Number: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32Bit + Codec + Into<U256> + TryFrom<U256>,
Number: Member + sp_std::hash::Hash + Copy + MaybeDisplay + AtLeast32BitUnsigned + Codec +
Into<U256> + TryFrom<U256>,
Hash: HashT,
Hash::Output: Default + sp_std::hash::Hash + Copy + Member + MaybeDisplay + SimpleBitOps + Codec,
{
@@ -61,7 +61,7 @@
//! ```
use crate::offchain::storage::StorageValueRef;
use crate::traits::AtLeast32Bit;
use crate::traits::AtLeast32BitUnsigned;
use codec::{Codec, Decode, Encode};
use sp_core::offchain::{Duration, Timestamp};
use sp_io::offchain;
@@ -430,7 +430,7 @@ where
/// used with [`BlockAndTime<BlockNumberProvider>`](BlockAndTime).
pub trait BlockNumberProvider {
/// Type of `BlockNumber` to provide.
type BlockNumber: Codec + Clone + Ord + Eq + AtLeast32Bit;
type BlockNumber: Codec + Clone + Ord + Eq + AtLeast32BitUnsigned;
/// Returns the current block number.
///
/// Provides an abstraction over an arbitrary way of providing the
+4 -5
View File
@@ -34,8 +34,8 @@ use crate::transaction_validity::{
};
use crate::generic::{Digest, DigestItem};
pub use sp_arithmetic::traits::{
AtLeast32Bit, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating, SaturatedConversion,
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
AtLeast32Bit, AtLeast32BitUnsigned, UniqueSaturatedInto, UniqueSaturatedFrom, Saturating,
SaturatedConversion, Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
CheckedShl, CheckedShr, IntegerSquareRoot
};
use sp_application_crypto::AppKey;
@@ -490,9 +490,8 @@ pub trait Header:
MaybeMallocSizeOf + 'static
{
/// Header number.
type Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash
+ Copy + MaybeDisplay + AtLeast32Bit + Codec + sp_std::str::FromStr
+ MaybeMallocSizeOf;
type Number: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + Copy +
MaybeDisplay + AtLeast32BitUnsigned + Codec + sp_std::str::FromStr + MaybeMallocSizeOf;
/// Header hash type
type Hash: Member + MaybeSerializeDeserialize + Debug + sp_std::hash::Hash + Ord
+ Copy + MaybeDisplay + Default + SimpleBitOps + Codec + AsRef<[u8]>