Run cargo fmt on the whole code base (#9394)

* Run cargo fmt on the whole code base

* Second run

* Add CI check

* Fix compilation

* More unnecessary braces

* Handle weights

* Use --all

* Use correct attributes...

* Fix UI tests

* AHHHHHHHHH

* 🤦

* Docs

* Fix compilation

* 🤷

* Please stop

* 🤦 x 2

* More

* make rustfmt.toml consistent with polkadot

Co-authored-by: André Silva <andrerfosilva@gmail.com>
This commit is contained in:
Bastian Köcher
2021-07-21 16:32:32 +02:00
committed by GitHub
parent d451c38c1c
commit 7b56ab15b4
1010 changed files with 53339 additions and 51208 deletions
+44 -52
View File
@@ -7,7 +7,7 @@
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -17,9 +17,9 @@
//! Infinite precision unsigned integer for substrate runtime.
use num_traits::{Zero, One};
use sp_std::{cmp::Ordering, ops, prelude::*, vec, cell::RefCell, convert::TryFrom};
use codec::{Encode, Decode};
use codec::{Decode, Encode};
use num_traits::{One, Zero};
use sp_std::{cell::RefCell, cmp::Ordering, convert::TryFrom, ops, prelude::*, vec};
// A sensible value for this would be half of the dword size of the host machine. Since the
// runtime is compiled to 32bit webassembly, using 32 and 64 for single and double respectively
@@ -105,7 +105,9 @@ impl BigUint {
}
/// Number of limbs.
pub fn len(&self) -> usize { self.digits.len() }
pub fn len(&self) -> usize {
self.digits.len()
}
/// A naive getter for limb at `index`. Note that the order is lsb -> msb.
///
@@ -156,7 +158,9 @@ impl BigUint {
// by definition, a big-int number should never have leading zero limbs. This function
// has the ability to cause this. There is nothing to do if the number already has 1
// limb only. call it a day and return.
if self.len().is_zero() { return; }
if self.len().is_zero() {
return
}
let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(self.len() - 1);
if index > 0 {
@@ -168,7 +172,9 @@ impl BigUint {
/// is already bigger than `size` limbs.
pub fn lpad(&mut self, size: usize) {
let n = self.len();
if n >= size { return; }
if n >= size {
return
}
let pad = size - n;
let mut new_digits = (0..pad).map(|_| 0).collect::<Vec<Single>>();
new_digits.extend(self.digits.iter());
@@ -260,15 +266,15 @@ impl BigUint {
if self.get(j) == 0 {
// Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if
// otherwise.
continue;
continue
}
let mut k = 0;
for i in 0..m {
// PROOF: (B1) × (B1) + (B1) + (B1) = B^2 1 < B^2. addition is safe.
let t = mul_single(self.get(j), other.get(i))
+ Double::from(w.get(i + j))
+ Double::from(k);
let t = mul_single(self.get(j), other.get(i)) +
Double::from(w.get(i + j)) +
Double::from(k);
w.set(i + j, (t % B) as Single);
// PROOF: (B^2 - 1) / B < B. conversion is safe.
k = (t / B) as Single;
@@ -288,9 +294,9 @@ impl BigUint {
let mut out = Self::with_capacity(n);
let mut r: Single = 0;
// PROOF: (B-1) * B + (B-1) still fits in double
let with_r = |x: Single, r: Single| { Double::from(r) * B + Double::from(x) };
let with_r = |x: Single, r: Single| Double::from(r) * B + Double::from(x);
for d in (0..n).rev() {
let (q, rr) = div_single(with_r(self.get(d), r), other) ;
let (q, rr) = div_single(with_r(self.get(d), r), other);
out.set(d, q as Single);
r = rr;
}
@@ -311,11 +317,7 @@ impl BigUint {
///
/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
pub fn div(self, other: &Self, rem: bool) -> Option<(Self, Self)> {
if other.len() <= 1
|| other.msb() == 0
|| self.msb() == 0
|| self.len() <= other.len()
{
if other.len() <= 1 || other.msb() == 0 || self.msb() == 0 || self.len() <= other.len() {
return None
}
let n = other.len();
@@ -344,9 +346,7 @@ impl BigUint {
// PROOF: this always fits into `Double`. In the context of Single = u8, and
// Double = u16, think of 255 * 256 + 255 which is just u16::MAX.
let dividend =
Double::from(self_norm.get(j + n))
* B
+ Double::from(self_norm.get(j + n - 1));
Double::from(self_norm.get(j + n)) * B + Double::from(self_norm.get(j + n - 1));
let divisor = other_norm.get(n - 1);
div_single(dividend, divisor)
};
@@ -377,23 +377,30 @@ impl BigUint {
test();
while (*rhat.borrow() as Double) < B {
if !test() { break; }
if !test() {
break
}
}
let qhat = qhat.into_inner();
// we don't need rhat anymore. just let it go out of scope when it does.
// step D4
let lhs = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() };
let lhs = Self { digits: (j..=j + n).rev().map(|d| self_norm.get(d)).collect() };
let rhs = other_norm.clone().mul(&Self::from(qhat));
let maybe_sub = lhs.sub(&rhs);
let mut negative = false;
let sub = match maybe_sub {
Ok(t) => t,
Err(t) => { negative = true; t }
Err(t) => {
negative = true;
t
},
};
(j..=j+n).for_each(|d| { self_norm.set(d, sub.get(d - j)); });
(j..=j + n).for_each(|d| {
self_norm.set(d, sub.get(d - j));
});
// step D5
// PROOF: the `test()` specifically decreases qhat until it is below `B`. conversion
@@ -403,9 +410,11 @@ impl BigUint {
// step D6: add back if negative happened.
if negative {
q.set(j, q.get(j) - 1);
let u = Self { digits: (j..=j+n).rev().map(|d| self_norm.get(d)).collect() };
let u = Self { digits: (j..=j + n).rev().map(|d| self_norm.get(d)).collect() };
let r = other_norm.clone().add(&u);
(j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); })
(j..=j + n).rev().for_each(|d| {
self_norm.set(d, r.get(d - j));
})
}
}
@@ -415,9 +424,8 @@ impl BigUint {
if normalizer_bits > 0 {
let s = SHIFT as u32;
let nb = normalizer_bits;
for d in 0..n-1 {
let v = self_norm.get(d) >> nb
| self_norm.get(d + 1).overflowing_shl(s - nb).0;
for d in 0..n - 1 {
let v = self_norm.get(d) >> nb | self_norm.get(d + 1).overflowing_shl(s - nb).0;
r.set(d, v);
}
r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits);
@@ -445,7 +453,6 @@ impl sp_std::fmt::Debug for BigUint {
fn fmt(&self, _: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
Ok(())
}
}
impl PartialEq for BigUint {
@@ -475,7 +482,7 @@ impl Ord for BigUint {
Ordering::Equal => lhs.cmp(rhs),
_ => len_cmp,
}
}
},
}
}
}
@@ -632,18 +639,9 @@ pub mod tests {
#[test]
fn equality_works() {
assert_eq!(
BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] },
true,
);
assert_eq!(
BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] },
false,
);
assert_eq!(
BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] },
true,
);
assert_eq!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, true,);
assert_eq!(BigUint { digits: vec![3, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, false,);
assert_eq!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] }, true,);
}
#[test]
@@ -669,14 +667,8 @@ pub mod tests {
use sp_std::convert::TryFrom;
assert_eq!(u64::try_from(with_limbs(1)).unwrap(), 1);
assert_eq!(u64::try_from(with_limbs(2)).unwrap(), u32::MAX as u64 + 2);
assert_eq!(
u64::try_from(with_limbs(3)).unwrap_err(),
"cannot fit a number into u64",
);
assert_eq!(
u128::try_from(with_limbs(3)).unwrap(),
u32::MAX as u128 + u64::MAX as u128 + 3
);
assert_eq!(u64::try_from(with_limbs(3)).unwrap_err(), "cannot fit a number into u64",);
assert_eq!(u128::try_from(with_limbs(3)).unwrap(), u32::MAX as u128 + u64::MAX as u128 + 3);
}
#[test]
+228 -106
View File
@@ -17,22 +17,38 @@
//! Decimal Fixed Point implementations for Substrate runtime.
use sp_std::{ops::{self, Add, Sub, Mul, Div}, fmt::Debug, prelude::*, convert::{TryInto, TryFrom}};
use codec::{Encode, Decode, CompactAs};
use crate::{
helpers_128bit::multiply_by_rational, PerThing,
helpers_128bit::multiply_by_rational,
traits::{
SaturatedConversion, CheckedSub, CheckedAdd, CheckedMul, CheckedDiv, CheckedNeg,
Bounded, Saturating, UniqueSaturatedInto, Zero, One
Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedSub, One,
SaturatedConversion, Saturating, UniqueSaturatedInto, Zero,
},
PerThing,
};
use codec::{CompactAs, Decode, Encode};
use sp_std::{
convert::{TryFrom, TryInto},
fmt::Debug,
ops::{self, Add, Div, Mul, Sub},
prelude::*,
};
#[cfg(feature = "std")]
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
/// Integer types that can be used to interact with `FixedPointNumber` implementations.
pub trait FixedPointOperand: Copy + Clone + Bounded + Zero + Saturating
+ PartialOrd + UniqueSaturatedInto<u128> + TryFrom<u128> + CheckedNeg {}
pub trait FixedPointOperand:
Copy
+ Clone
+ Bounded
+ Zero
+ Saturating
+ PartialOrd
+ UniqueSaturatedInto<u128>
+ TryFrom<u128>
+ CheckedNeg
{
}
impl FixedPointOperand for i128 {}
impl FixedPointOperand for u128 {}
@@ -53,11 +69,26 @@ impl FixedPointOperand for u8 {}
/// to `Self::Inner::max_value() / Self::DIV`.
/// This is also referred to as the _accuracy_ of the type in the documentation.
pub trait FixedPointNumber:
Sized + Copy + Default + Debug
+ Saturating + Bounded
+ Eq + PartialEq + Ord + PartialOrd
+ CheckedSub + CheckedAdd + CheckedMul + CheckedDiv
+ Add + Sub + Div + Mul + Zero + One
Sized
+ Copy
+ Default
+ Debug
+ Saturating
+ Bounded
+ Eq
+ PartialEq
+ Ord
+ PartialOrd
+ CheckedSub
+ CheckedAdd
+ CheckedMul
+ CheckedDiv
+ Add
+ Sub
+ Div
+ Mul
+ Zero
+ One
{
/// The underlying data type used for this fixed point number.
type Inner: Debug + One + CheckedMul + CheckedDiv + FixedPointOperand;
@@ -108,7 +139,10 @@ pub trait FixedPointNumber:
/// Creates `self` from a rational number. Equal to `n / d`.
///
/// Returns `None` if `d == 0` or `n / d` exceeds accuracy.
fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(n: N, d: D) -> Option<Self> {
fn checked_from_rational<N: FixedPointOperand, D: FixedPointOperand>(
n: N,
d: D,
) -> Option<Self> {
if d == D::zero() {
return None
}
@@ -117,7 +151,8 @@ pub trait FixedPointNumber:
let d: I129 = d.into();
let negative = n.negative != d.negative;
multiply_by_rational(n.value, Self::DIV.unique_saturated_into(), d.value).ok()
multiply_by_rational(n.value, Self::DIV.unique_saturated_into(), d.value)
.ok()
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self::from_inner)
}
@@ -130,7 +165,8 @@ pub trait FixedPointNumber:
let rhs: I129 = n.into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational(lhs.value, rhs.value, Self::DIV.unique_saturated_into()).ok()
multiply_by_rational(lhs.value, rhs.value, Self::DIV.unique_saturated_into())
.ok()
.and_then(|value| from_i129(I129 { value, negative }))
}
@@ -149,7 +185,8 @@ pub trait FixedPointNumber:
let rhs: I129 = d.into();
let negative = lhs.negative != rhs.negative;
lhs.value.checked_div(rhs.value)
lhs.value
.checked_div(rhs.value)
.and_then(|n| n.checked_div(Self::DIV.unique_saturated_into()))
.and_then(|value| from_i129(I129 { value, negative }))
}
@@ -212,7 +249,8 @@ pub trait FixedPointNumber:
/// Returns the integer part.
fn trunc(self) -> Self {
self.into_inner().checked_div(&Self::DIV)
self.into_inner()
.checked_div(&Self::DIV)
.expect("panics only if DIV is zero, DIV is not zero; qed")
.checked_mul(&Self::DIV)
.map(Self::from_inner)
@@ -281,7 +319,8 @@ struct I129 {
impl<N: FixedPointOperand> From<N> for I129 {
fn from(n: N) -> I129 {
if n < N::zero() {
let value: u128 = n.checked_neg()
let value: u128 = n
.checked_neg()
.map(|n| n.unique_saturated_into())
.unwrap_or_else(|| N::max_value().unique_saturated_into().saturating_add(1));
I129 { value, negative: true }
@@ -322,9 +361,10 @@ macro_rules! implement_fixed {
$title:expr $(,)?
) => {
/// A fixed point number representation in the range.
///
#[doc = $title]
#[derive(Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
#[derive(
Encode, Decode, CompactAs, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord,
)]
pub struct $name($inner_type);
impl From<$inner_type> for $name {
@@ -386,7 +426,7 @@ macro_rules! implement_fixed {
fn saturating_pow(self, exp: usize) -> Self {
if exp == 0 {
return Self::saturating_from_integer(1);
return Self::saturating_from_integer(1)
}
let exp = exp as u32;
@@ -471,7 +511,8 @@ macro_rules! implement_fixed {
let rhs: I129 = other.0.into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational(lhs.value, Self::DIV as u128, rhs.value).ok()
multiply_by_rational(lhs.value, Self::DIV as u128, rhs.value)
.ok()
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self)
}
@@ -483,7 +524,8 @@ macro_rules! implement_fixed {
let rhs: I129 = other.0.into();
let negative = lhs.negative != rhs.negative;
multiply_by_rational(lhs.value, rhs.value, Self::DIV as u128).ok()
multiply_by_rational(lhs.value, rhs.value, Self::DIV as u128)
.ok()
.and_then(|value| from_i129(I129 { value, negative }))
.map(Self)
}
@@ -524,7 +566,11 @@ macro_rules! implement_fixed {
format!("{}{}", signum_for_zero, int)
};
let precision = (Self::accuracy() as f64).log10() as usize;
let fractional = format!("{:0>weight$}", ((self.0 % Self::accuracy()) as i128).abs(), weight=precision);
let fractional = format!(
"{:0>weight$}",
((self.0 % Self::accuracy()) as i128).abs(),
weight = precision
);
write!(f, "{}({}.{})", stringify!($name), integral, fractional)
}
@@ -534,7 +580,10 @@ macro_rules! implement_fixed {
}
}
impl<P: PerThing> From<P> for $name where P::Inner: FixedPointOperand {
impl<P: PerThing> From<P> for $name
where
P::Inner: FixedPointOperand,
{
fn from(p: P) -> Self {
let accuracy = P::ACCURACY;
let value = p.deconstruct();
@@ -554,8 +603,8 @@ macro_rules! implement_fixed {
type Err = &'static str;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let inner: <Self as FixedPointNumber>::Inner = s.parse()
.map_err(|_| "invalid string input for fixed point number")?;
let inner: <Self as FixedPointNumber>::Inner =
s.parse().map_err(|_| "invalid string input for fixed point number")?;
Ok(Self::from_inner(inner))
}
}
@@ -610,50 +659,32 @@ macro_rules! implement_fixed {
#[test]
fn from_i129_works() {
let a = I129 {
value: 1,
negative: true,
};
let a = I129 { value: 1, negative: true };
// Can't convert negative number to unsigned.
assert_eq!(from_i129::<u128>(a), None);
let a = I129 {
value: u128::MAX - 1,
negative: false,
};
let a = I129 { value: u128::MAX - 1, negative: false };
// Max - 1 value fits.
assert_eq!(from_i129::<u128>(a), Some(u128::MAX - 1));
let a = I129 {
value: u128::MAX,
negative: false,
};
let a = I129 { value: u128::MAX, negative: false };
// Max value fits.
assert_eq!(from_i129::<u128>(a), Some(u128::MAX));
let a = I129 {
value: i128::MAX as u128 + 1,
negative: true,
};
let a = I129 { value: i128::MAX as u128 + 1, negative: true };
// Min value fits.
assert_eq!(from_i129::<i128>(a), Some(i128::MIN));
let a = I129 {
value: i128::MAX as u128 + 1,
negative: false,
};
let a = I129 { value: i128::MAX as u128 + 1, negative: false };
// Max + 1 does not fit.
assert_eq!(from_i129::<i128>(a), None);
let a = I129 {
value: i128::MAX as u128,
negative: false,
};
let a = I129 { value: i128::MAX as u128, negative: false };
// Max value fits.
assert_eq!(from_i129::<i128>(a), Some(i128::MAX));
@@ -724,7 +755,6 @@ macro_rules! implement_fixed {
// Min.
assert_eq!($name::max_value(), b);
}
}
@@ -849,8 +879,7 @@ macro_rules! implement_fixed {
let accuracy = $name::accuracy();
// Case where integer fits.
let a = $name::checked_from_integer(42)
.expect("42 * accuracy <= inner_max; qed");
let a = $name::checked_from_integer(42).expect("42 * accuracy <= inner_max; qed");
assert_eq!(a.into_inner(), 42 * accuracy);
// Max integer that fit.
@@ -928,7 +957,7 @@ macro_rules! implement_fixed {
if $name::SIGNED {
// Negative case: -2.5
let a = $name::saturating_from_rational(-5, 2);
assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
assert_eq!(a.into_inner(), 0 - 25 * accuracy / 10);
// Other negative case: -2.5
let a = $name::saturating_from_rational(5, -2);
@@ -1048,7 +1077,10 @@ macro_rules! implement_fixed {
if $name::SIGNED {
// Min - 1 => Underflow => None.
let a = $name::checked_from_rational(inner_max as u128 + 2, 0.saturating_sub(accuracy));
let a = $name::checked_from_rational(
inner_max as u128 + 2,
0.saturating_sub(accuracy),
);
assert_eq!(a, None);
let a = $name::checked_from_rational(inner_max, 0 - 3 * accuracy).unwrap();
@@ -1163,15 +1195,15 @@ macro_rules! implement_fixed {
// Max - 1.
let b = $name::from_inner(inner_max - 1);
assert_eq!(a.checked_mul(&(b/2.into())), Some(b));
assert_eq!(a.checked_mul(&(b / 2.into())), Some(b));
// Max.
let c = $name::from_inner(inner_max);
assert_eq!(a.checked_mul(&(c/2.into())), Some(b));
assert_eq!(a.checked_mul(&(c / 2.into())), Some(b));
// Max + 1 => None.
let e = $name::from_inner(1);
assert_eq!(a.checked_mul(&(c/2.into()+e)), None);
assert_eq!(a.checked_mul(&(c / 2.into() + e)), None);
if $name::SIGNED {
// Min + 1.
@@ -1192,8 +1224,14 @@ macro_rules! implement_fixed {
let b = $name::saturating_from_rational(1, -2);
assert_eq!(b.checked_mul(&42.into()), Some(0.saturating_sub(21).into()));
assert_eq!(b.checked_mul(&$name::max_value()), $name::max_value().checked_div(&0.saturating_sub(2).into()));
assert_eq!(b.checked_mul(&$name::min_value()), $name::min_value().checked_div(&0.saturating_sub(2).into()));
assert_eq!(
b.checked_mul(&$name::max_value()),
$name::max_value().checked_div(&0.saturating_sub(2).into())
);
assert_eq!(
b.checked_mul(&$name::min_value()),
$name::min_value().checked_div(&0.saturating_sub(2).into())
);
assert_eq!(c.checked_mul(&$name::min_value()), None);
}
@@ -1203,8 +1241,14 @@ macro_rules! implement_fixed {
assert_eq!(a.checked_mul(&42.into()), Some(21.into()));
assert_eq!(c.checked_mul(&2.into()), Some(510.into()));
assert_eq!(c.checked_mul(&$name::max_value()), None);
assert_eq!(a.checked_mul(&$name::max_value()), $name::max_value().checked_div(&2.into()));
assert_eq!(a.checked_mul(&$name::min_value()), $name::min_value().checked_div(&2.into()));
assert_eq!(
a.checked_mul(&$name::max_value()),
$name::max_value().checked_div(&2.into())
);
assert_eq!(
a.checked_mul(&$name::min_value()),
$name::min_value().checked_div(&2.into())
);
}
#[test]
@@ -1230,13 +1274,25 @@ macro_rules! implement_fixed {
if b < c {
// Not executed by unsigned inners.
assert_eq!(a.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_max / (2 * accuracy))));
assert_eq!(a.checked_div_int(0.saturating_sub(inner_max / accuracy)), Some(0.saturating_sub(1)));
assert_eq!(
a.checked_div_int(0.saturating_sub(2)),
Some(0.saturating_sub(inner_max / (2 * accuracy)))
);
assert_eq!(
a.checked_div_int(0.saturating_sub(inner_max / accuracy)),
Some(0.saturating_sub(1))
);
assert_eq!(b.checked_div_int(i128::MIN), Some(0));
assert_eq!(b.checked_div_int(inner_min / accuracy), Some(1));
assert_eq!(b.checked_div_int(1i8), None);
assert_eq!(b.checked_div_int(0.saturating_sub(2)), Some(0.saturating_sub(inner_min / (2 * accuracy))));
assert_eq!(b.checked_div_int(0.saturating_sub(inner_min / accuracy)), Some(0.saturating_sub(1)));
assert_eq!(
b.checked_div_int(0.saturating_sub(2)),
Some(0.saturating_sub(inner_min / (2 * accuracy)))
);
assert_eq!(
b.checked_div_int(0.saturating_sub(inner_min / accuracy)),
Some(0.saturating_sub(1))
);
assert_eq!(c.checked_div_int(i128::MIN), Some(0));
assert_eq!(d.checked_div_int(i32::MIN), Some(0));
}
@@ -1294,7 +1350,10 @@ macro_rules! implement_fixed {
if $name::SIGNED {
assert_eq!($name::from_inner(inner_min).saturating_abs(), $name::max_value());
assert_eq!($name::saturating_from_rational(-1, 2).saturating_abs(), (1, 2).into());
assert_eq!(
$name::saturating_from_rational(-1, 2).saturating_abs(),
(1, 2).into()
);
}
}
@@ -1319,31 +1378,72 @@ macro_rules! implement_fixed {
#[test]
fn saturating_pow_should_work() {
assert_eq!($name::saturating_from_integer(2).saturating_pow(0), $name::saturating_from_integer(1));
assert_eq!($name::saturating_from_integer(2).saturating_pow(1), $name::saturating_from_integer(2));
assert_eq!($name::saturating_from_integer(2).saturating_pow(2), $name::saturating_from_integer(4));
assert_eq!($name::saturating_from_integer(2).saturating_pow(3), $name::saturating_from_integer(8));
assert_eq!($name::saturating_from_integer(2).saturating_pow(50),
$name::saturating_from_integer(1125899906842624i64));
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(0),
$name::saturating_from_integer(1)
);
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(1),
$name::saturating_from_integer(2)
);
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(2),
$name::saturating_from_integer(4)
);
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(3),
$name::saturating_from_integer(8)
);
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(50),
$name::saturating_from_integer(1125899906842624i64)
);
assert_eq!($name::saturating_from_integer(1).saturating_pow(1000), (1).into());
assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::MAX), (1).into());
assert_eq!(
$name::saturating_from_integer(1).saturating_pow(usize::MAX),
(1).into()
);
if $name::SIGNED {
// Saturating.
assert_eq!($name::saturating_from_integer(2).saturating_pow(68), $name::max_value());
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(68),
$name::max_value()
);
assert_eq!($name::saturating_from_integer(-1).saturating_pow(1000), (1).into());
assert_eq!($name::saturating_from_integer(-1).saturating_pow(1001), 0.saturating_sub(1).into());
assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::MAX), 0.saturating_sub(1).into());
assert_eq!($name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1), (1).into());
assert_eq!(
$name::saturating_from_integer(-1).saturating_pow(1001),
0.saturating_sub(1).into()
);
assert_eq!(
$name::saturating_from_integer(-1).saturating_pow(usize::MAX),
0.saturating_sub(1).into()
);
assert_eq!(
$name::saturating_from_integer(-1).saturating_pow(usize::MAX - 1),
(1).into()
);
}
assert_eq!($name::saturating_from_integer(114209).saturating_pow(5), $name::max_value());
assert_eq!(
$name::saturating_from_integer(114209).saturating_pow(5),
$name::max_value()
);
assert_eq!($name::saturating_from_integer(1).saturating_pow(usize::MAX), (1).into());
assert_eq!($name::saturating_from_integer(0).saturating_pow(usize::MAX), (0).into());
assert_eq!($name::saturating_from_integer(2).saturating_pow(usize::MAX), $name::max_value());
assert_eq!(
$name::saturating_from_integer(1).saturating_pow(usize::MAX),
(1).into()
);
assert_eq!(
$name::saturating_from_integer(0).saturating_pow(usize::MAX),
(0).into()
);
assert_eq!(
$name::saturating_from_integer(2).saturating_pow(usize::MAX),
$name::max_value()
);
}
#[test]
@@ -1368,9 +1468,18 @@ macro_rules! implement_fixed {
if b < c {
// Not executed by unsigned inners.
assert_eq!(a.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_max / 2))));
assert_eq!(a.checked_div(&-$name::max_value()), Some(0.saturating_sub(1).into()));
assert_eq!(b.checked_div(&0.saturating_sub(2).into()), Some($name::from_inner(0.saturating_sub(inner_min / 2))));
assert_eq!(
a.checked_div(&0.saturating_sub(2).into()),
Some($name::from_inner(0.saturating_sub(inner_max / 2)))
);
assert_eq!(
a.checked_div(&-$name::max_value()),
Some(0.saturating_sub(1).into())
);
assert_eq!(
b.checked_div(&0.saturating_sub(2).into()),
Some($name::from_inner(0.saturating_sub(inner_min / 2)))
);
assert_eq!(c.checked_div(&$name::max_value()), Some(0.into()));
assert_eq!(b.checked_div(&b), Some($name::one()));
}
@@ -1427,14 +1536,10 @@ macro_rules! implement_fixed {
assert_eq!(n, i + f);
let n = $name::saturating_from_rational(5, 2)
.frac()
.saturating_mul(10.into());
let n = $name::saturating_from_rational(5, 2).frac().saturating_mul(10.into());
assert_eq!(n, 5.into());
let n = $name::saturating_from_rational(1, 2)
.frac()
.saturating_mul(10.into());
let n = $name::saturating_from_rational(1, 2).frac().saturating_mul(10.into());
assert_eq!(n, 5.into());
if $name::SIGNED {
@@ -1444,14 +1549,10 @@ macro_rules! implement_fixed {
assert_eq!(n, i - f);
// The sign is attached to the integer part unless it is zero.
let n = $name::saturating_from_rational(-5, 2)
.frac()
.saturating_mul(10.into());
let n = $name::saturating_from_rational(-5, 2).frac().saturating_mul(10.into());
assert_eq!(n, 5.into());
let n = $name::saturating_from_rational(-1, 2)
.frac()
.saturating_mul(10.into());
let n = $name::saturating_from_rational(-1, 2).frac().saturating_mul(10.into());
assert_eq!(n, 0.saturating_sub(5).into());
}
}
@@ -1564,30 +1665,51 @@ macro_rules! implement_fixed {
#[test]
fn fmt_should_work() {
let zero = $name::zero();
assert_eq!(format!("{:?}", zero), format!("{}(0.{:0>weight$})", stringify!($name), 0, weight=precision()));
assert_eq!(
format!("{:?}", zero),
format!("{}(0.{:0>weight$})", stringify!($name), 0, weight = precision())
);
let one = $name::one();
assert_eq!(format!("{:?}", one), format!("{}(1.{:0>weight$})", stringify!($name), 0, weight=precision()));
assert_eq!(
format!("{:?}", one),
format!("{}(1.{:0>weight$})", stringify!($name), 0, weight = precision())
);
let frac = $name::saturating_from_rational(1, 2);
assert_eq!(format!("{:?}", frac), format!("{}(0.{:0<weight$})", stringify!($name), 5, weight=precision()));
assert_eq!(
format!("{:?}", frac),
format!("{}(0.{:0<weight$})", stringify!($name), 5, weight = precision())
);
let frac = $name::saturating_from_rational(5, 2);
assert_eq!(format!("{:?}", frac), format!("{}(2.{:0<weight$})", stringify!($name), 5, weight=precision()));
assert_eq!(
format!("{:?}", frac),
format!("{}(2.{:0<weight$})", stringify!($name), 5, weight = precision())
);
let frac = $name::saturating_from_rational(314, 100);
assert_eq!(format!("{:?}", frac), format!("{}(3.{:0<weight$})", stringify!($name), 14, weight=precision()));
assert_eq!(
format!("{:?}", frac),
format!("{}(3.{:0<weight$})", stringify!($name), 14, weight = precision())
);
if $name::SIGNED {
let neg = -$name::one();
assert_eq!(format!("{:?}", neg), format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight=precision()));
assert_eq!(
format!("{:?}", neg),
format!("{}(-1.{:0>weight$})", stringify!($name), 0, weight = precision())
);
let frac = $name::saturating_from_rational(-314, 100);
assert_eq!(format!("{:?}", frac), format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight=precision()));
assert_eq!(
format!("{:?}", frac),
format!("{}(-3.{:0<weight$})", stringify!($name), 14, weight = precision())
);
}
}
}
}
};
}
implement_fixed!(
@@ -22,7 +22,11 @@
use crate::biguint;
use num_traits::Zero;
use sp_std::{cmp::{min, max}, convert::TryInto, mem};
use sp_std::{
cmp::{max, min},
convert::TryInto,
mem,
};
/// Helper gcd function used in Rational128 implementation.
pub fn gcd(a: u128, b: u128) -> u128 {
@@ -63,7 +67,9 @@ pub fn to_big_uint(x: u128) -> biguint::BigUint {
///
/// Invariant: c must be greater than or equal to 1.
pub fn multiply_by_rational(mut a: u128, mut b: u128, mut c: u128) -> Result<u128, &'static str> {
if a.is_zero() || b.is_zero() { return Ok(Zero::zero()); }
if a.is_zero() || b.is_zero() {
return Ok(Zero::zero())
}
c = c.max(1);
// a and b are interchangeable by definition in this function. It always helps to assume the
@@ -102,9 +108,10 @@ pub fn multiply_by_rational(mut a: u128, mut b: u128, mut c: u128) -> Result<u12
// bigger than c. In this case, returning zero is defensive-only and div should
// always return Some.
let (mut q, r) = ab.div(&c_num, true).unwrap_or((Zero::zero(), Zero::zero()));
let r: u128 = r.try_into()
.expect("reminder of div by c is always less than c; qed");
if r > (c / 2) { q = q.add(&to_big_uint(1)); }
let r: u128 = r.try_into().expect("reminder of div by c is always less than c; qed");
if r > (c / 2) {
q = q.add(&to_big_uint(1));
}
q
};
q.lstrip();
+48 -102
View File
@@ -34,18 +34,18 @@ macro_rules! assert_eq_error_rate {
}
pub mod biguint;
pub mod helpers_128bit;
pub mod traits;
pub mod per_things;
pub mod fixed_point;
pub mod helpers_128bit;
pub mod per_things;
pub mod rational;
pub mod traits;
pub use fixed_point::{FixedPointNumber, FixedPointOperand, FixedI64, FixedI128, FixedU128};
pub use per_things::{PerThing, InnerOf, UpperOf, Percent, PerU16, Permill, Perbill, Perquintill};
pub use fixed_point::{FixedI128, FixedI64, FixedPointNumber, FixedPointOperand, FixedU128};
pub use per_things::{InnerOf, PerThing, PerU16, Perbill, Percent, Permill, Perquintill, UpperOf};
pub use rational::{Rational128, RationalInfinite};
use sp_std::{prelude::*, cmp::Ordering, fmt::Debug, convert::TryInto};
use traits::{BaseArithmetic, One, Zero, SaturatedConversion, Unsigned};
use sp_std::{cmp::Ordering, convert::TryInto, fmt::Debug, prelude::*};
use traits::{BaseArithmetic, One, SaturatedConversion, Unsigned, Zero};
/// Trait for comparing two numbers with an threshold.
///
@@ -82,7 +82,6 @@ where
_ => Ordering::Equal,
}
}
}
}
@@ -114,8 +113,10 @@ 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 uppers =
self.iter().map(|p| <UpperOf<P>>::from(p.clone().deconstruct())).collect::<Vec<_>>();
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()))?;
@@ -157,7 +158,8 @@ impl<P: PerThing> Normalizable<P> for Vec<P> {
///
/// * This proof is used in the implementation as well.
pub fn normalize<T>(input: &[T], targeted_sum: T) -> Result<Vec<T>, &'static str>
where T: Clone + Copy + Ord + BaseArithmetic + Unsigned + Debug,
where
T: Clone + Copy + Ord + BaseArithmetic + Unsigned + Debug,
{
// compute sum and return error if failed.
let mut sum = T::zero();
@@ -171,12 +173,12 @@ pub fn normalize<T>(input: &[T], targeted_sum: T) -> Result<Vec<T>, &'static str
// Nothing to do here.
if count.is_zero() {
return Ok(Vec::<T>::new());
return Ok(Vec::<T>::new())
}
let diff = targeted_sum.max(sum) - targeted_sum.min(sum);
if diff.is_zero() {
return Ok(input.to_vec());
return Ok(input.to_vec())
}
let needs_bump = targeted_sum > sum;
@@ -198,7 +200,8 @@ pub fn normalize<T>(input: &[T], targeted_sum: T) -> Result<Vec<T>, &'static str
if !per_round.is_zero() {
for _ in 0..count {
output_with_idx[min_index].1 = output_with_idx[min_index].1
output_with_idx[min_index].1 = output_with_idx[min_index]
.1
.checked_add(&per_round)
.expect("Proof provided in the module doc; qed.");
if output_with_idx[min_index].1 >= threshold {
@@ -210,7 +213,8 @@ pub fn normalize<T>(input: &[T], targeted_sum: T) -> Result<Vec<T>, &'static str
// continue with the previous min_index
while !leftover.is_zero() {
output_with_idx[min_index].1 = output_with_idx[min_index].1
output_with_idx[min_index].1 = output_with_idx[min_index]
.1
.checked_add(&T::one())
.expect("Proof provided in the module doc; qed.");
if output_with_idx[min_index].1 >= threshold {
@@ -232,9 +236,8 @@ pub fn normalize<T>(input: &[T], targeted_sum: T) -> Result<Vec<T>, &'static str
if !per_round.is_zero() {
for _ in 0..count {
output_with_idx[max_index].1 = output_with_idx[max_index].1
.checked_sub(&per_round)
.unwrap_or_else(|| {
output_with_idx[max_index].1 =
output_with_idx[max_index].1.checked_sub(&per_round).unwrap_or_else(|| {
let remainder = per_round - output_with_idx[max_index].1;
leftover += remainder;
output_with_idx[max_index].1.saturating_sub(per_round)
@@ -284,7 +287,7 @@ mod normalize_tests {
normalize(vec![8 as $type, 9, 7, 10].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
}
};
}
// it should work for all types as long as the length of vector can be converted to T.
test_for!(u128);
@@ -297,22 +300,13 @@ mod normalize_tests {
#[test]
fn fails_on_if_input_sum_large() {
assert!(normalize(vec![1u8; 255].as_ref(), 10).is_ok());
assert_eq!(
normalize(vec![1u8; 256].as_ref(), 10),
Err("sum of input cannot fit in `T`"),
);
assert_eq!(normalize(vec![1u8; 256].as_ref(), 10), Err("sum of input cannot fit in `T`"),);
}
#[test]
fn does_not_fail_on_subtraction_overflow() {
assert_eq!(
normalize(vec![1u8, 100, 100].as_ref(), 10).unwrap(),
vec![1, 9, 0],
);
assert_eq!(
normalize(vec![1u8, 8, 9].as_ref(), 1).unwrap(),
vec![0, 1, 0],
);
assert_eq!(normalize(vec![1u8, 100, 100].as_ref(), 10).unwrap(), vec![1, 9, 0],);
assert_eq!(normalize(vec![1u8, 8, 9].as_ref(), 1).unwrap(), vec![0, 1, 0],);
}
#[test]
@@ -323,11 +317,9 @@ mod normalize_tests {
#[test]
fn works_for_per_thing() {
assert_eq!(
vec![
Perbill::from_percent(33),
Perbill::from_percent(33),
Perbill::from_percent(33)
].normalize(Perbill::one()).unwrap(),
vec![Perbill::from_percent(33), Perbill::from_percent(33), Perbill::from_percent(33)]
.normalize(Perbill::one())
.unwrap(),
vec![
Perbill::from_parts(333333334),
Perbill::from_parts(333333333),
@@ -336,11 +328,9 @@ mod normalize_tests {
);
assert_eq!(
vec![
Perbill::from_percent(20),
Perbill::from_percent(15),
Perbill::from_percent(30)
].normalize(Perbill::one()).unwrap(),
vec![Perbill::from_percent(20), Perbill::from_percent(15), Perbill::from_percent(30)]
.normalize(Perbill::one())
.unwrap(),
vec![
Perbill::from_parts(316666668),
Perbill::from_parts(383333332),
@@ -355,11 +345,9 @@ mod normalize_tests {
// could have a situation where the sum cannot be calculated in the inner type. Calculating
// using the upper type of the per_thing should assure this to be okay.
assert_eq!(
vec![
PerU16::from_percent(40),
PerU16::from_percent(40),
PerU16::from_percent(40),
].normalize(PerU16::one()).unwrap(),
vec![PerU16::from_percent(40), PerU16::from_percent(40), PerU16::from_percent(40),]
.normalize(PerU16::one())
.unwrap(),
vec![
PerU16::from_parts(21845), // 33%
PerU16::from_parts(21845), // 33%
@@ -370,82 +358,40 @@ mod normalize_tests {
#[test]
fn normalize_works_all_le() {
assert_eq!(
normalize(vec![8u32, 9, 7, 10].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(normalize(vec![8u32, 9, 7, 10].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(
normalize(vec![7u32, 7, 7, 7].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(normalize(vec![7u32, 7, 7, 7].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(
normalize(vec![7u32, 7, 7, 10].as_ref(), 40).unwrap(),
vec![11, 11, 8, 10],
);
assert_eq!(normalize(vec![7u32, 7, 7, 10].as_ref(), 40).unwrap(), vec![11, 11, 8, 10],);
assert_eq!(
normalize(vec![7u32, 8, 7, 10].as_ref(), 40).unwrap(),
vec![11, 8, 11, 10],
);
assert_eq!(normalize(vec![7u32, 8, 7, 10].as_ref(), 40).unwrap(), vec![11, 8, 11, 10],);
assert_eq!(
normalize(vec![7u32, 7, 8, 10].as_ref(), 40).unwrap(),
vec![11, 11, 8, 10],
);
assert_eq!(normalize(vec![7u32, 7, 8, 10].as_ref(), 40).unwrap(), vec![11, 11, 8, 10],);
}
#[test]
fn normalize_works_some_ge() {
assert_eq!(
normalize(vec![8u32, 11, 9, 10].as_ref(), 40).unwrap(),
vec![10, 11, 9, 10],
);
assert_eq!(normalize(vec![8u32, 11, 9, 10].as_ref(), 40).unwrap(), vec![10, 11, 9, 10],);
}
#[test]
fn always_inc_min() {
assert_eq!(
normalize(vec![10u32, 7, 10, 10].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(
normalize(vec![10u32, 10, 7, 10].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(
normalize(vec![10u32, 10, 10, 7].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(normalize(vec![10u32, 7, 10, 10].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(normalize(vec![10u32, 10, 7, 10].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(normalize(vec![10u32, 10, 10, 7].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
}
#[test]
fn normalize_works_all_ge() {
assert_eq!(
normalize(vec![12u32, 11, 13, 10].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(normalize(vec![12u32, 11, 13, 10].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(
normalize(vec![13u32, 13, 13, 13].as_ref(), 40).unwrap(),
vec![10, 10, 10, 10],
);
assert_eq!(normalize(vec![13u32, 13, 13, 13].as_ref(), 40).unwrap(), vec![10, 10, 10, 10],);
assert_eq!(
normalize(vec![13u32, 13, 13, 10].as_ref(), 40).unwrap(),
vec![12, 9, 9, 10],
);
assert_eq!(normalize(vec![13u32, 13, 13, 10].as_ref(), 40).unwrap(), vec![12, 9, 9, 10],);
assert_eq!(
normalize(vec![13u32, 12, 13, 10].as_ref(), 40).unwrap(),
vec![9, 12, 9, 10],
);
assert_eq!(normalize(vec![13u32, 12, 13, 10].as_ref(), 40).unwrap(), vec![9, 12, 9, 10],);
assert_eq!(
normalize(vec![13u32, 13, 12, 10].as_ref(), 40).unwrap(),
vec![9, 9, 12, 10],
);
assert_eq!(normalize(vec![13u32, 13, 12, 10].as_ref(), 40).unwrap(), vec![9, 9, 12, 10],);
}
}
+132 -70
View File
@@ -16,16 +16,20 @@
// limitations under the License.
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use sp_std::{ops, fmt, prelude::*, convert::{TryFrom, TryInto}};
use codec::{Encode, CompactAs};
use num_traits::Pow;
use crate::traits::{
SaturatedConversion, UniqueSaturatedInto, Saturating, BaseArithmetic, Bounded, Zero, Unsigned,
One,
BaseArithmetic, Bounded, One, SaturatedConversion, Saturating, UniqueSaturatedInto, Unsigned,
Zero,
};
use codec::{CompactAs, Encode};
use num_traits::Pow;
use sp_debug_derive::RuntimeDebug;
use sp_std::{
convert::{TryFrom, TryInto},
fmt, ops,
prelude::*,
};
/// Get the inner type of a `PerThing`.
pub type InnerOf<P> = <P as PerThing>::Inner;
@@ -36,8 +40,19 @@ pub type UpperOf<P> = <P as PerThing>::Upper;
/// Something that implements a fixed point ration with an arbitrary granularity `X`, as _parts per
/// `X`_.
pub trait PerThing:
Sized + Saturating + Copy + Default + Eq + PartialEq + Ord + PartialOrd + Bounded + fmt::Debug
+ ops::Div<Output=Self> + ops::Mul<Output=Self> + Pow<usize, Output=Self>
Sized
+ Saturating
+ Copy
+ Default
+ Eq
+ PartialEq
+ Ord
+ PartialOrd
+ Bounded
+ fmt::Debug
+ ops::Div<Output = Self>
+ ops::Mul<Output = Self>
+ Pow<usize, Output = Self>
{
/// The data type used to build this per-thingy.
type Inner: BaseArithmetic + Unsigned + Copy + Into<u128> + fmt::Debug;
@@ -56,16 +71,24 @@ pub trait PerThing:
const ACCURACY: Self::Inner;
/// Equivalent to `Self::from_parts(0)`.
fn zero() -> Self { Self::from_parts(Self::Inner::zero()) }
fn zero() -> Self {
Self::from_parts(Self::Inner::zero())
}
/// Return `true` if this is nothing.
fn is_zero(&self) -> bool { self.deconstruct() == Self::Inner::zero() }
fn is_zero(&self) -> bool {
self.deconstruct() == Self::Inner::zero()
}
/// Equivalent to `Self::from_parts(Self::ACCURACY)`.
fn one() -> Self { Self::from_parts(Self::ACCURACY) }
fn one() -> Self {
Self::from_parts(Self::ACCURACY)
}
/// Return `true` if this is one.
fn is_one(&self) -> bool { self.deconstruct() == Self::ACCURACY }
fn is_one(&self) -> bool {
self.deconstruct() == Self::ACCURACY
}
/// Build this type from a percent. Equivalent to `Self::from_parts(x * Self::ACCURACY / 100)`
/// but more accurate and can cope with potential type overflows.
@@ -104,8 +127,13 @@ pub trait PerThing:
/// ```
fn mul_floor<N>(self, b: N) -> N
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,
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)
@@ -128,9 +156,14 @@ pub trait PerThing:
/// ```
fn mul_ceil<N>(self, b: N) -> N
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>
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)
}
@@ -146,9 +179,14 @@ pub trait PerThing:
/// ```
fn saturating_reciprocal_mul<N>(self, b: N) -> N
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,
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)
@@ -168,9 +206,14 @@ pub trait PerThing:
/// ```
fn saturating_reciprocal_mul_floor<N>(self, b: N) -> N
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,
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)
@@ -190,9 +233,14 @@ pub trait PerThing:
/// ```
fn saturating_reciprocal_mul_ceil<N>(self, b: N) -> N
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,
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)
@@ -211,7 +259,9 @@ pub trait PerThing:
/// Same as `Self::from_float`.
#[deprecated = "Use from_float instead"]
#[cfg(feature = "std")]
fn from_fraction(x: f64) -> Self { Self::from_float(x) }
fn from_fraction(x: f64) -> Self {
Self::from_float(x)
}
/// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow.
///
@@ -233,18 +283,31 @@ pub trait PerThing:
/// ```
fn from_rational<N>(p: N, q: N) -> Self
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,
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>;
/// Same as `Self::from_rational`.
#[deprecated = "Use from_rational instead"]
fn from_rational_approximation<N>(p: N, q: N) -> Self
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>,
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>,
{
Self::from_rational(p, q)
}
@@ -264,37 +327,38 @@ enum Rounding {
/// bounds instead of overflowing.
fn saturating_reciprocal_mul<N, P>(x: N, part: P::Inner, rounding: Rounding) -> N
where
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,
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>(
x.clone(),
P::ACCURACY,
part,
rounding,
);
let c = rational_mul_correction::<N, P>(x.clone(), P::ACCURACY, part, rounding);
(x / part.into()).saturating_mul(maximum).saturating_add(c)
}
/// 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
where
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,
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();
let c = rational_mul_correction::<N, P>(
x.clone(),
part,
P::ACCURACY,
rounding,
);
let c = rational_mul_correction::<N, P>(x.clone(), part, P::ACCURACY, rounding);
(x / maximum) * part_n + c
}
@@ -304,10 +368,14 @@ where
/// 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
where
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,
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>
P::Inner: Into<N>,
{
let numer_upper = P::Upper::from(numer);
let denom_n: N = denom.into();
@@ -324,16 +392,18 @@ where
// Already rounded down
Rounding::Down => {},
// Round up if the fractional part of the result is non-zero.
Rounding::Up => if rem_mul_upper % denom_upper > 0.into() {
// `rem * numer / denom` is less than `numer`, so this will not overflow.
rem_mul_div_inner += 1.into();
},
Rounding::Up =>
if rem_mul_upper % denom_upper > 0.into() {
// `rem * numer / denom` is less than `numer`, so this will not overflow.
rem_mul_div_inner += 1.into();
},
// Round up if the fractional part of the result is greater than a half. An exact half is
// rounded down.
Rounding::Nearest => if rem_mul_upper % denom_upper > denom_upper / 2.into() {
// `rem * numer / denom` is less than `numer`, so this will not overflow.
rem_mul_div_inner += 1.into();
},
Rounding::Nearest =>
if rem_mul_upper % denom_upper > denom_upper / 2.into() {
// `rem * numer / denom` is less than `numer`, so this will not overflow.
rem_mul_div_inner += 1.into();
},
}
rem_mul_div_inner.into()
}
@@ -1331,15 +1401,7 @@ macro_rules! implement_per_thing_with_perthousand {
}
}
implement_per_thing!(
Percent,
test_per_cent,
[u32, u64, u128],
100u8,
u8,
u16,
"_Percent_",
);
implement_per_thing!(Percent, test_per_cent, [u32, u64, u128], 100u8, u8, u16, "_Percent_",);
implement_per_thing_with_perthousand!(
PerU16,
test_peru16,
+39 -57
View File
@@ -15,10 +15,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
use crate::{biguint::BigUint, helpers_128bit};
use num_traits::{Bounded, One, Zero};
use sp_std::{cmp::Ordering, prelude::*};
use crate::helpers_128bit;
use num_traits::{Zero, One, Bounded};
use crate::biguint::BigUint;
/// A wrapper for any rational number with infinitely large numerator and denominator.
///
@@ -160,9 +159,11 @@ impl Rational128 {
/// accurately calculated.
pub fn lcm(&self, other: &Self) -> Result<u128, &'static str> {
// this should be tested better: two large numbers that are almost the same.
if self.1 == other.1 { return Ok(self.1) }
if self.1 == other.1 {
return Ok(self.1)
}
let g = helpers_128bit::gcd(self.1, other.1);
helpers_128bit::multiply_by_rational(self.1 , other.1, g)
helpers_128bit::multiply_by_rational(self.1, other.1, g)
}
/// A saturating add that assumes `self` and `other` have the same denominator.
@@ -170,7 +171,7 @@ impl Rational128 {
if other.is_zero() {
self
} else {
Self(self.0.saturating_add(other.0) ,self.1)
Self(self.0.saturating_add(other.0), self.1)
}
}
@@ -179,7 +180,7 @@ impl Rational128 {
if other.is_zero() {
self
} else {
Self(self.0.saturating_sub(other.0) ,self.1)
Self(self.0.saturating_sub(other.0), self.1)
}
}
@@ -190,7 +191,9 @@ impl Rational128 {
let lcm = self.lcm(&other).map_err(|_| "failed to scale to denominator")?;
let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?;
let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?;
let n = self_scaled.0.checked_add(other_scaled.0)
let n = self_scaled
.0
.checked_add(other_scaled.0)
.ok_or("overflow while adding numerators")?;
Ok(Self(n, self_scaled.1))
}
@@ -203,7 +206,9 @@ impl Rational128 {
let self_scaled = self.to_den(lcm).map_err(|_| "failed to scale to denominator")?;
let other_scaled = other.to_den(lcm).map_err(|_| "failed to scale to denominator")?;
let n = self_scaled.0.checked_sub(other_scaled.0)
let n = self_scaled
.0
.checked_sub(other_scaled.0)
.ok_or("overflow while subtracting numerators")?;
Ok(Self(n, self_scaled.1))
}
@@ -243,7 +248,8 @@ impl Ord for Rational128 {
} else {
// Don't even compute gcd.
let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1);
let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1);
let other_n =
helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1);
self_n.cmp(&other_n)
}
}
@@ -256,7 +262,8 @@ impl PartialEq for Rational128 {
self.0.eq(&other.0)
} else {
let self_n = helpers_128bit::to_big_uint(self.0) * helpers_128bit::to_big_uint(other.1);
let other_n = helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1);
let other_n =
helpers_128bit::to_big_uint(other.0) * helpers_128bit::to_big_uint(self.1);
self_n.eq(&other_n)
}
}
@@ -264,8 +271,7 @@ impl PartialEq for Rational128 {
#[cfg(test)]
mod tests {
use super::*;
use super::helpers_128bit::*;
use super::{helpers_128bit::*, *};
const MAX128: u128 = u128::MAX;
const MAX64: u128 = u64::MAX as u128;
@@ -277,7 +283,9 @@ mod tests {
fn mul_div(a: u128, b: u128, c: u128) -> u128 {
use primitive_types::U256;
if a.is_zero() { return Zero::zero(); }
if a.is_zero() {
return Zero::zero()
}
let c = c.max(1);
// e for extended
@@ -295,14 +303,8 @@ mod tests {
#[test]
fn truth_value_function_works() {
assert_eq!(
mul_div(2u128.pow(100), 8, 4),
2u128.pow(101)
);
assert_eq!(
mul_div(2u128.pow(100), 4, 8),
2u128.pow(99)
);
assert_eq!(mul_div(2u128.pow(100), 8, 4), 2u128.pow(101));
assert_eq!(mul_div(2u128.pow(100), 4, 8), 2u128.pow(99));
// and it returns a if result cannot fit
assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10);
@@ -319,13 +321,10 @@ mod tests {
assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10)));
// large to perbill. This is very well needed for npos-elections.
assert_eq!(
r(MAX128 / 2, MAX128).to_den(1000_000_000),
Ok(r(500_000_000, 1000_000_000))
);
assert_eq!(r(MAX128 / 2, MAX128).to_den(1000_000_000), Ok(r(500_000_000, 1000_000_000)));
// large to large
assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128/2), Ok(r(MAX128/4, MAX128/2)));
assert_eq!(r(MAX128 / 2, MAX128).to_den(MAX128 / 2), Ok(r(MAX128 / 4, MAX128 / 2)));
}
#[test]
@@ -343,11 +342,11 @@ mod tests {
// large numbers
assert_eq!(
r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128-1)),
r(1_000_000_000, MAX128).lcm(&r(7_000_000_000, MAX128 - 1)),
Err("result cannot fit in u128"),
);
assert_eq!(
r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64-1)),
r(1_000_000_000, MAX64).lcm(&r(7_000_000_000, MAX64 - 1)),
Ok(340282366920938463408034375210639556610),
);
assert!(340282366920938463408034375210639556610 < MAX128);
@@ -362,7 +361,7 @@ mod tests {
// errors
assert_eq!(
r(1, MAX128).checked_add(r(1, MAX128-1)),
r(1, MAX128).checked_add(r(1, MAX128 - 1)),
Err("failed to scale to denominator"),
);
assert_eq!(
@@ -383,17 +382,14 @@ mod tests {
// errors
assert_eq!(
r(2, MAX128).checked_sub(r(1, MAX128-1)),
r(2, MAX128).checked_sub(r(1, MAX128 - 1)),
Err("failed to scale to denominator"),
);
assert_eq!(
r(7, MAX128).checked_sub(r(MAX128, MAX128)),
Err("overflow while subtracting numerators"),
);
assert_eq!(
r(1, 10).checked_sub(r(2,10)),
Err("overflow while subtracting numerators"),
);
assert_eq!(r(1, 10).checked_sub(r(2, 10)), Err("overflow while subtracting numerators"),);
}
#[test]
@@ -428,7 +424,7 @@ mod tests {
);
assert_eq!(
// MAX128 % 7 == 3
multiply_by_rational(MAX128, 11 , 13).unwrap(),
multiply_by_rational(MAX128, 11, 13).unwrap(),
(MAX128 / 13 * 11) + (8 * 11 / 13),
);
assert_eq!(
@@ -437,14 +433,8 @@ mod tests {
(MAX128 / 1000 * 555) + (455 * 555 / 1000),
);
assert_eq!(
multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(),
2 * MAX64 - 1,
);
assert_eq!(
multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(),
2 * MAX64 - 3,
);
assert_eq!(multiply_by_rational(2 * MAX64 - 1, MAX64, MAX64).unwrap(), 2 * MAX64 - 1,);
assert_eq!(multiply_by_rational(2 * MAX64 - 1, MAX64 - 1, MAX64).unwrap(), 2 * MAX64 - 3,);
assert_eq!(
multiply_by_rational(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(),
@@ -459,31 +449,23 @@ mod tests {
multiply_by_rational(2u128.pow(66) - 1, 2u128.pow(65) - 1, 2u128.pow(65)).unwrap(),
73786976294838206461,
);
assert_eq!(
multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(),
250000000,
);
assert_eq!(multiply_by_rational(1_000_000_000, MAX128 / 8, MAX128 / 2).unwrap(), 250000000,);
assert_eq!(
multiply_by_rational(
29459999999999999988000u128,
1000000000000000000u128,
10000000000000000000u128
).unwrap(),
)
.unwrap(),
2945999999999999998800u128
);
}
#[test]
fn multiply_by_rational_a_b_are_interchangeable() {
assert_eq!(
multiply_by_rational(10, MAX128, MAX128 / 2),
Ok(20),
);
assert_eq!(
multiply_by_rational(MAX128, 10, MAX128 / 2),
Ok(20),
);
assert_eq!(multiply_by_rational(10, MAX128, MAX128 / 2), Ok(20),);
assert_eq!(multiply_by_rational(MAX128, 10, MAX128 / 2), Ok(20),);
}
#[test]
+155 -66
View File
@@ -17,58 +17,129 @@
//! Primitive traits for the runtime arithmetic.
use sp_std::{self, convert::{TryFrom, TryInto}};
use codec::HasCompact;
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedNeg,
CheckedShl, CheckedShr, checked_pow, Signed, Unsigned,
checked_pow, Bounded, CheckedAdd, CheckedDiv, CheckedMul, CheckedNeg, CheckedShl, CheckedShr,
CheckedSub, One, Signed, Unsigned, Zero,
};
use sp_std::ops::{
Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr
use sp_std::{
self,
convert::{TryFrom, TryInto},
ops::{
Add, AddAssign, Div, DivAssign, Mul, MulAssign, Rem, RemAssign, Shl, Shr, Sub, SubAssign,
},
};
/// A meta trait for arithmetic type operations, regardless of any limitation on size.
pub trait BaseArithmetic:
From<u8> +
Zero + One + IntegerSquareRoot +
Add<Self, Output = Self> + AddAssign<Self> +
Sub<Self, Output = Self> + SubAssign<Self> +
Mul<Self, Output = Self> + MulAssign<Self> +
Div<Self, Output = Self> + DivAssign<Self> +
Rem<Self, Output = Self> + RemAssign<Self> +
Shl<u32, Output = Self> + Shr<u32, Output = Self> +
CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + Saturating +
PartialOrd<Self> + Ord + Bounded + HasCompact + Sized +
TryFrom<u8> + TryInto<u8> + TryFrom<u16> + TryInto<u16> + TryFrom<u32> + TryInto<u32> +
TryFrom<u64> + TryInto<u64> + TryFrom<u128> + TryInto<u128> + TryFrom<usize> + TryInto<usize> +
UniqueSaturatedFrom<u8> + UniqueSaturatedInto<u8> +
UniqueSaturatedFrom<u16> + UniqueSaturatedInto<u16> +
UniqueSaturatedFrom<u32> + UniqueSaturatedInto<u32> +
UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64> +
UniqueSaturatedFrom<u128> + UniqueSaturatedInto<u128>
{}
From<u8>
+ Zero
+ One
+ IntegerSquareRoot
+ Add<Self, Output = Self>
+ AddAssign<Self>
+ Sub<Self, Output = Self>
+ SubAssign<Self>
+ Mul<Self, Output = Self>
+ MulAssign<Self>
+ Div<Self, Output = Self>
+ DivAssign<Self>
+ Rem<Self, Output = Self>
+ RemAssign<Self>
+ Shl<u32, Output = Self>
+ Shr<u32, Output = Self>
+ CheckedShl
+ CheckedShr
+ CheckedAdd
+ CheckedSub
+ CheckedMul
+ CheckedDiv
+ Saturating
+ PartialOrd<Self>
+ Ord
+ Bounded
+ HasCompact
+ Sized
+ TryFrom<u8>
+ TryInto<u8>
+ TryFrom<u16>
+ TryInto<u16>
+ TryFrom<u32>
+ TryInto<u32>
+ TryFrom<u64>
+ TryInto<u64>
+ TryFrom<u128>
+ TryInto<u128>
+ TryFrom<usize>
+ TryInto<usize>
+ UniqueSaturatedFrom<u8>
+ UniqueSaturatedInto<u8>
+ UniqueSaturatedFrom<u16>
+ UniqueSaturatedInto<u16>
+ UniqueSaturatedFrom<u32>
+ UniqueSaturatedInto<u32>
+ UniqueSaturatedFrom<u64>
+ UniqueSaturatedInto<u64>
+ UniqueSaturatedFrom<u128>
+ UniqueSaturatedInto<u128>
{
}
impl<T:
From<u8> +
Zero + One + IntegerSquareRoot +
Add<Self, Output = Self> + AddAssign<Self> +
Sub<Self, Output = Self> + SubAssign<Self> +
Mul<Self, Output = Self> + MulAssign<Self> +
Div<Self, Output = Self> + DivAssign<Self> +
Rem<Self, Output = Self> + RemAssign<Self> +
Shl<u32, Output = Self> + Shr<u32, Output = Self> +
CheckedShl + CheckedShr + CheckedAdd + CheckedSub + CheckedMul + CheckedDiv + Saturating +
PartialOrd<Self> + Ord + Bounded + HasCompact + Sized +
TryFrom<u8> + TryInto<u8> + TryFrom<u16> + TryInto<u16> + TryFrom<u32> + TryInto<u32> +
TryFrom<u64> + TryInto<u64> + TryFrom<u128> + TryInto<u128> + TryFrom<usize> + TryInto<usize> +
UniqueSaturatedFrom<u8> + UniqueSaturatedInto<u8> +
UniqueSaturatedFrom<u16> + UniqueSaturatedInto<u16> +
UniqueSaturatedFrom<u32> + UniqueSaturatedInto<u32> +
UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64> +
UniqueSaturatedFrom<u128> + UniqueSaturatedInto<u128>
> BaseArithmetic for T {}
impl<
T: From<u8>
+ Zero
+ One
+ IntegerSquareRoot
+ Add<Self, Output = Self>
+ AddAssign<Self>
+ Sub<Self, Output = Self>
+ SubAssign<Self>
+ Mul<Self, Output = Self>
+ MulAssign<Self>
+ Div<Self, Output = Self>
+ DivAssign<Self>
+ Rem<Self, Output = Self>
+ RemAssign<Self>
+ Shl<u32, Output = Self>
+ Shr<u32, Output = Self>
+ CheckedShl
+ CheckedShr
+ CheckedAdd
+ CheckedSub
+ CheckedMul
+ CheckedDiv
+ Saturating
+ PartialOrd<Self>
+ Ord
+ Bounded
+ HasCompact
+ Sized
+ TryFrom<u8>
+ TryInto<u8>
+ TryFrom<u16>
+ TryInto<u16>
+ TryFrom<u32>
+ TryInto<u32>
+ TryFrom<u64>
+ TryInto<u64>
+ TryFrom<u128>
+ TryInto<u128>
+ TryFrom<usize>
+ TryInto<usize>
+ UniqueSaturatedFrom<u8>
+ UniqueSaturatedInto<u8>
+ UniqueSaturatedFrom<u16>
+ UniqueSaturatedInto<u16>
+ UniqueSaturatedFrom<u32>
+ UniqueSaturatedInto<u32>
+ UniqueSaturatedFrom<u64>
+ UniqueSaturatedInto<u64>
+ UniqueSaturatedFrom<u128>
+ UniqueSaturatedInto<u128>,
> BaseArithmetic for T
{
}
/// A meta trait for arithmetic.
///
@@ -129,35 +200,49 @@ pub trait Saturating {
fn saturating_pow(self, exp: usize) -> Self;
/// Increment self by one, saturating.
fn saturating_inc(&mut self) where Self: One {
fn saturating_inc(&mut self)
where
Self: One,
{
let mut o = Self::one();
sp_std::mem::swap(&mut o, self);
*self = o.saturating_add(One::one());
}
/// Decrement self by one, saturating at zero.
fn saturating_dec(&mut self) where Self: One {
fn saturating_dec(&mut self)
where
Self: One,
{
let mut o = Self::one();
sp_std::mem::swap(&mut o, self);
*self = o.saturating_sub(One::one());
}
/// Increment self by some `amount`, saturating.
fn saturating_accrue(&mut self, amount: Self) where Self: One {
fn saturating_accrue(&mut self, amount: Self)
where
Self: One,
{
let mut o = Self::one();
sp_std::mem::swap(&mut o, self);
*self = o.saturating_add(amount);
}
/// Decrement self by some `amount`, saturating at zero.
fn saturating_reduce(&mut self, amount: Self) where Self: One {
fn saturating_reduce(&mut self, amount: Self)
where
Self: One,
{
let mut o = Self::one();
sp_std::mem::swap(&mut o, self);
*self = o.saturating_sub(amount);
}
}
impl<T: Clone + Zero + One + PartialOrd + CheckedMul + Bounded + num_traits::Saturating> Saturating for T {
impl<T: Clone + Zero + One + PartialOrd + CheckedMul + Bounded + num_traits::Saturating> Saturating
for T
{
fn saturating_add(self, o: Self) -> Self {
<Self as num_traits::Saturating>::saturating_add(self, o)
}
@@ -167,26 +252,24 @@ impl<T: Clone + Zero + One + PartialOrd + CheckedMul + Bounded + num_traits::Sat
}
fn saturating_mul(self, o: Self) -> Self {
self.checked_mul(&o)
.unwrap_or_else(||
if (self < T::zero()) != (o < T::zero()) {
Bounded::min_value()
} else {
Bounded::max_value()
}
)
self.checked_mul(&o).unwrap_or_else(|| {
if (self < T::zero()) != (o < T::zero()) {
Bounded::min_value()
} else {
Bounded::max_value()
}
})
}
fn saturating_pow(self, exp: usize) -> Self {
let neg = self < T::zero() && exp % 2 != 0;
checked_pow(self, exp)
.unwrap_or_else(||
if neg {
Bounded::min_value()
} else {
Bounded::max_value()
}
)
checked_pow(self, exp).unwrap_or_else(|| {
if neg {
Bounded::min_value()
} else {
Bounded::max_value()
}
})
}
}
@@ -199,7 +282,10 @@ pub trait SaturatedConversion {
/// This just uses `UniqueSaturatedFrom` internally but with this
/// variant you can provide the destination type using turbofish syntax
/// in case Rust happens not to assume the correct type.
fn saturated_from<T>(t: T) -> Self where Self: UniqueSaturatedFrom<T> {
fn saturated_from<T>(t: T) -> Self
where
Self: UniqueSaturatedFrom<T>,
{
<Self as UniqueSaturatedFrom<T>>::unique_saturated_from(t)
}
@@ -208,7 +294,10 @@ pub trait SaturatedConversion {
/// This just uses `UniqueSaturatedInto` internally but with this
/// variant you can provide the destination type using turbofish syntax
/// in case Rust happens not to assume the correct type.
fn saturated_into<T>(self) -> T where Self: UniqueSaturatedInto<T> {
fn saturated_into<T>(self) -> T
where
Self: UniqueSaturatedInto<T>,
{
<Self as UniqueSaturatedInto<T>>::unique_saturated_into(self)
}
}