mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 11:07:56 +00:00
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:
@@ -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: (B−1) × (B−1) + (B−1) + (B−1) = 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]
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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],);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user