Fix folder names in primitives (#4358)

* sr-arithmetic -> arithmetic

* sr-sandbox -> sandbox

* primitives/sr-staking-primitives -> primitives/staking

* primitives/sr-version -> primitives/version

* primitives/block-builder/runtime-api -> primitives/block-builder
This commit is contained in:
Benjamin Kampmann
2019-12-11 11:36:29 +01:00
committed by GitHub
parent 605c0e655e
commit df133d6be3
56 changed files with 46 additions and 46 deletions
@@ -0,0 +1,735 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Infinite precision unsigned integer for substrate runtime.
use num_traits::Zero;
use sp_std::{cmp::Ordering, ops, prelude::*, cell::RefCell, convert::TryFrom};
// 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
// should yield the most performance.
/// Representation of a single limb.
pub type Single = u32;
/// Representation of two limbs.
pub type Double = u64;
/// Difference in the number of bits of [`Single`] and [`Double`].
const SHIFT: usize = 32;
/// short form of _Base_. Analogous to the value 10 in base-10 decimal numbers.
const B: Double = Single::max_value() as Double + 1;
/// Splits a [`Double`] limb number into a tuple of two [`Single`] limb numbers.
pub fn split(a: Double) -> (Single, Single) {
let al = a as Single;
let ah = (a >> SHIFT) as Single;
(ah, al)
}
/// Assumed as a given primitive.
///
/// Multiplication of two singles, which at most yields 1 double.
pub fn mul_single(a: Single, b: Single) -> Double {
let a: Double = a.into();
let b: Double = b.into();
a * b
}
/// Assumed as a given primitive.
///
/// Addition of two singles, which at most takes a single limb of result and a carry,
/// returned as a tuple respectively.
pub fn add_single(a: Single, b: Single) -> (Single, Single) {
let a: Double = a.into();
let b: Double = b.into();
let q = a + b;
let (carry, r) = split(q);
(r, carry)
}
/// Assumed as a given primitive.
///
/// Division of double by a single limb. Always returns a double limb of quotient and a single
/// limb of remainder.
fn div_single(a: Double, b: Single) -> (Double, Single) {
let b: Double = b.into();
let q = a / b;
let r = a % b;
// both conversions are trivially safe.
(q, r as Single)
}
/// Simple wrapper around an infinitely large integer, represented as limbs of [`Single`].
#[derive(Clone, Default)]
pub struct BigUint {
/// digits (limbs) of this number (sorted as msb -> lsd).
pub(crate) digits: Vec<Single>,
}
impl BigUint {
/// Create a new instance with `size` limbs. This prevents any number with zero limbs to be
/// created.
///
/// The behavior of the type is undefined with zero limbs.
pub fn with_capacity(size: usize) -> Self {
Self { digits: vec![0; size.max(1)] }
}
/// Raw constructor from custom limbs. If `limbs` is empty, `Zero::zero()` implementation is
/// used.
pub fn from_limbs(limbs: &[Single]) -> Self {
if !limbs.is_empty() {
Self { digits: limbs.to_vec() }
} else {
Zero::zero()
}
}
/// Number of limbs.
pub fn len(&self) -> usize { self.digits.len() }
/// A naive getter for limb at `index`. Note that the order is lsb -> msb.
///
/// #### Panics
///
/// This panics if index is out of range.
pub fn get(&self, index: usize) -> Single {
self.digits[self.len() - 1 - index]
}
/// A naive getter for limb at `index`. Note that the order is lsb -> msb.
pub fn checked_get(&self, index: usize) -> Option<Single> {
let i = self.len().checked_sub(1)?;
let j = i.checked_sub(index)?;
self.digits.get(j).cloned()
}
/// A naive setter for limb at `index`. Note that the order is lsb -> msb.
///
/// #### Panics
///
/// This panics if index is out of range.
pub fn set(&mut self, index: usize, value: Single) {
let len = self.digits.len();
self.digits[len - 1 - index] = value;
}
/// returns the least significant limb of the number.
///
/// #### Panics
///
/// While the constructor of the type prevents this, this can panic if `self` has no digits.
pub fn lsb(&self) -> Single {
self.digits[self.len() - 1]
}
/// returns the most significant limb of the number.
///
/// #### Panics
///
/// While the constructor of the type prevents this, this can panic if `self` has no digits.
pub fn msb(&self) -> Single {
self.digits[0]
}
/// Strips zeros from the left side (the most significant limbs) of `self`, if any.
pub fn lstrip(&mut self) {
// 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; }
let index = self.digits.iter().position(|&elem| elem != 0).unwrap_or(0);
if index > 0 {
self.digits = self.digits[index..].to_vec()
}
}
/// Zero-pad `self` from left to reach `size` limbs. Will not make any difference if `self`
/// is already bigger than `size` limbs.
pub fn lpad(&mut self, size: usize) {
let n = self.len();
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());
self.digits = new_digits;
}
/// Adds `self` with `other`. self and other do not have to have any particular size. Given
/// that the `n = max{size(self), size(other)}`, it will produce a number with `n + 1`
/// limbs.
///
/// This function does not strip the output and returns the original allocated `n + 1`
/// limbs. The caller may strip the output if desired.
///
/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
pub fn add(self, other: &Self) -> Self {
let n = self.len().max(other.len());
let mut k: Double = 0;
let mut w = Self::with_capacity(n + 1);
for j in 0..n {
let u = Double::from(self.checked_get(j).unwrap_or(0));
let v = Double::from(other.checked_get(j).unwrap_or(0));
let s = u + v + k;
w.set(j, (s % B) as Single);
k = s / B;
}
// k is always 0 or 1.
w.set(n, k as Single);
w
}
/// Subtracts `other` from `self`. self and other do not have to have any particular size.
/// Given that the `n = max{size(self), size(other)}`, it will produce a number of size `n`.
///
/// If `other` is bigger than `self`, `Err(B - borrow)` is returned.
///
/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
pub fn sub(self, other: &Self) -> Result<Self, Self> {
let n = self.len().max(other.len());
let mut k = 0;
let mut w = Self::with_capacity(n);
for j in 0..n {
let s = {
let u = Double::from(self.checked_get(j).unwrap_or(0));
let v = Double::from(other.checked_get(j).unwrap_or(0));
let mut needs_borrow = false;
let mut t = 0;
if let Some(v) = u.checked_sub(v) {
if let Some(v2) = v.checked_sub(k) {
t = v2 % B;
k = 0;
} else {
needs_borrow = true;
}
} else {
needs_borrow = true;
}
if needs_borrow {
t = u + B - v - k;
k = 1;
}
t
};
// PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is
// trivial. The latter will not overflow this branch will only happen if the sum of
// `u - v - k` part has been negative, hence `u + B - v - k < b`.
w.set(j, s as Single);
}
if k.is_zero() {
Ok(w)
} else {
Err(w)
}
}
/// Multiplies n-limb number `self` with m-limb number `other`.
///
/// The resulting number will always have `n + m` limbs.
///
/// This function does not strip the output and returns the original allocated `n + m`
/// limbs. The caller may strip the output if desired.
///
/// Taken from "The Art of Computer Programming" by D.E. Knuth, vol 2, chapter 4.
pub fn mul(self, other: &Self) -> Self {
let n = self.len();
let m = other.len();
let mut w = Self::with_capacity(m + n);
for j in 0..n {
if self.get(j) == 0 {
// Note: `with_capacity` allocates with 0. Explicitly set j + m to zero if
// otherwise.
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);
w.set(i + j, (t % B) as Single);
// PROOF: (B^2 - 1) / B < B. conversion is safe.
k = (t / B) as Single;
}
w.set(j + m, k);
}
w
}
/// Divides `self` by a single limb `other`. This can be used in cases where the original
/// division cannot work due to the divisor (`other`) being just one limb.
///
/// Invariant: `other` cannot be zero.
pub fn div_unit(self, mut other: Single) -> Self {
other = other.max(1);
let n = self.len();
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: Double, r: Single| { Double::from(r) * B + x };
for d in (0..n).rev() {
let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ;
out.set(d, q as Single);
r = rr;
}
out
}
/// Divides an `n + m` limb self by a `n` limb `other`. The result is a `m + 1` limb
/// quotient and a `n` limb remainder, if enabled by passing `true` in `rem` argument, both
/// in the form of an option's `Ok`.
///
/// - requires `other` to be stripped and have no leading zeros.
/// - requires `self` to be stripped and have no leading zeros.
/// - requires `other` to have at least two limbs.
/// - requires `self` to have a greater length compared to `other`.
///
/// All arguments are examined without being stripped for the above conditions. If any of
/// the above fails, `None` is returned.`
///
/// 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()
{
return None
}
let n = other.len();
let m = self.len() - n;
let mut q = Self::with_capacity(m + 1);
let mut r = Self::with_capacity(n);
// PROOF: 0 <= normalizer_bits < SHIFT 0 <= normalizer < B. all conversions are
// safe.
let normalizer_bits = other.msb().leading_zeros() as Single;
let normalizer = (2 as Single).pow(normalizer_bits as u32) as Single;
// step D1.
let mut self_norm = self.mul(&Self::from(normalizer));
let mut other_norm = other.clone().mul(&Self::from(normalizer));
// defensive only; the mul implementation should always create this.
self_norm.lpad(n + m + 1);
other_norm.lstrip();
// step D2.
for j in (0..=m).rev() {
// step D3.0 Find an estimate of q[j], named qhat.
let (qhat, rhat) = {
// 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_value().
let dividend =
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)
};
// D3.1 test qhat
// replace qhat and rhat with RefCells. This helps share state with the closure
let qhat = RefCell::new(qhat);
let rhat = RefCell::new(Double::from(rhat));
let test = || {
// decrease qhat if it is bigger than the base (B)
let qhat_local = *qhat.borrow();
let rhat_local = *rhat.borrow();
let predicate_1 = qhat_local >= B;
let predicate_2 = {
let lhs = qhat_local * Double::from(other_norm.get(n - 2));
let rhs = B * rhat_local + Double::from(self_norm.get(j + n - 2));
lhs > rhs
};
if predicate_1 || predicate_2 {
*qhat.borrow_mut() -= 1;
*rhat.borrow_mut() += Double::from(other_norm.get(n - 1));
true
} else {
false
}
};
test();
while (*rhat.borrow() as Double) < B {
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 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 }
};
(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
// is safe.
q.set(j, qhat as Single);
// 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 r = other_norm.clone().add(&u);
(j..=j+n).rev().for_each(|d| { self_norm.set(d, r.get(d - j)); })
}
}
// if requested, calculate remainder.
if rem {
// undo the normalization.
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;
r.set(d, v);
}
r.set(n - 1, self_norm.get(n - 1) >> normalizer_bits);
} else {
r = self_norm;
}
}
Some((q, r))
}
}
impl sp_std::fmt::Debug for BigUint {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
write!(
f,
"BigUint {{ {:?} ({:?})}}",
self.digits,
u128::try_from(self.clone()).unwrap_or(0),
)
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter<'_>) -> sp_std::fmt::Result {
Ok(())
}
}
impl PartialEq for BigUint {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for BigUint {}
impl Ord for BigUint {
fn cmp(&self, other: &Self) -> Ordering {
let lhs_first = self.digits.iter().position(|&e| e != 0);
let rhs_first = other.digits.iter().position(|&e| e != 0);
match (lhs_first, rhs_first) {
// edge cases that should not happen. This basically means that one or both were
// zero.
(None, None) => Ordering::Equal,
(Some(_), None) => Ordering::Greater,
(None, Some(_)) => Ordering::Less,
(Some(lhs_idx), Some(rhs_idx)) => {
let lhs = &self.digits[lhs_idx..];
let rhs = &other.digits[rhs_idx..];
let len_cmp = lhs.len().cmp(&rhs.len());
match len_cmp {
Ordering::Equal => lhs.cmp(rhs),
_ => len_cmp,
}
}
}
}
}
impl PartialOrd for BigUint {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl ops::Add for BigUint {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
self.add(&rhs)
}
}
impl ops::Sub for BigUint {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
self.sub(&rhs).unwrap_or_else(|e| e)
}
}
impl ops::Mul for BigUint {
type Output = Self;
fn mul(self, rhs: Self) -> Self::Output {
self.mul(&rhs)
}
}
impl Zero for BigUint {
fn zero() -> Self {
Self { digits: vec![Zero::zero()] }
}
fn is_zero(&self) -> bool {
self.digits.iter().all(|d| d.is_zero())
}
}
macro_rules! impl_try_from_number_for {
($([$type:ty, $len:expr]),+) => {
$(
impl TryFrom<BigUint> for $type {
type Error = &'static str;
fn try_from(mut value: BigUint) -> Result<$type, Self::Error> {
value.lstrip();
let error_message = concat!("cannot fit a number into ", stringify!($type));
if value.len() * SHIFT > $len {
Err(error_message)
} else {
let mut acc: $type = Zero::zero();
for (i, d) in value.digits.iter().rev().cloned().enumerate() {
let d: $type = d.into();
acc += d << (SHIFT * i);
}
Ok(acc)
}
}
}
)*
};
}
// can only be implemented for sizes bigger than two limb.
impl_try_from_number_for!([u128, 128], [u64, 64]);
macro_rules! impl_from_for_smaller_than_word {
($($type:ty),+) => {
$(impl From<$type> for BigUint {
fn from(a: $type) -> Self {
Self { digits: vec! [a.into()] }
}
})*
}
}
impl_from_for_smaller_than_word!(u8, u16, Single);
impl From<Double> for BigUint {
fn from(a: Double) -> Self {
let (ah, al) = split(a);
Self { digits: vec![ah, al] }
}
}
#[cfg(test)]
pub mod tests {
use super::*;
fn with_limbs(n: usize) -> BigUint {
BigUint { digits: vec![1; n] }
}
#[test]
fn split_works() {
let a = SHIFT / 2;
let b = SHIFT * 3 / 2;
let num: Double = 1 << a | 1 << b;
// example when `Single = u8`
// assert_eq!(num, 0b_0001_0000_0001_0000)
assert_eq!(split(num), (1 << a, 1 << a));
}
#[test]
fn strip_works() {
let mut a = BigUint::from_limbs(&[0, 1, 0]);
a.lstrip();
assert_eq!(a, BigUint { digits: vec![1, 0] });
let mut a = BigUint::from_limbs(&[0, 0, 1]);
a.lstrip();
assert_eq!(a, BigUint { digits: vec![1] });
let mut a = BigUint::from_limbs(&[0, 0]);
a.lstrip();
assert_eq!(a, BigUint { digits: vec![0] });
let mut a = BigUint::from_limbs(&[0, 0, 0]);
a.lstrip();
assert_eq!(a, BigUint { digits: vec![0] });
}
#[test]
fn lpad_works() {
let mut a = BigUint::from_limbs(&[0, 1, 0]);
a.lpad(2);
assert_eq!(a.digits, vec![0, 1, 0]);
let mut a = BigUint::from_limbs(&[0, 1, 0]);
a.lpad(3);
assert_eq!(a.digits, vec![0, 1, 0]);
let mut a = BigUint::from_limbs(&[0, 1, 0]);
a.lpad(4);
assert_eq!(a.digits, vec![0, 0, 1, 0]);
}
#[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,
);
}
#[test]
fn ordering_works() {
assert!(BigUint { digits: vec![0] } < BigUint { digits: vec![1] });
assert!(BigUint { digits: vec![0] } == BigUint { digits: vec![0] });
assert!(BigUint { digits: vec![] } == BigUint { digits: vec![0] });
assert!(BigUint { digits: vec![] } == BigUint { digits: vec![] });
assert!(BigUint { digits: vec![] } < BigUint { digits: vec![1] });
assert!(BigUint { digits: vec![1, 2, 3] } == BigUint { digits: vec![1, 2, 3] });
assert!(BigUint { digits: vec![0, 1, 2, 3] } == BigUint { digits: vec![1, 2, 3] });
assert!(BigUint { digits: vec![1, 2, 4] } > BigUint { digits: vec![1, 2, 3] });
assert!(BigUint { digits: vec![0, 1, 2, 4] } > BigUint { digits: vec![1, 2, 3] });
assert!(BigUint { digits: vec![1, 2, 1, 0] } > BigUint { digits: vec![1, 2, 3] });
assert!(BigUint { digits: vec![0, 1, 2, 1] } < BigUint { digits: vec![1, 2, 3] });
}
#[test]
fn can_try_build_numbers_from_types() {
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_value() 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_value() as u128 + u64::max_value() as u128 + 3
);
}
#[test]
fn zero_works() {
assert_eq!(BigUint::zero(), BigUint { digits: vec![0] });
assert_eq!(BigUint { digits: vec![0, 1, 0] }.is_zero(), false);
assert_eq!(BigUint { digits: vec![0, 0, 0] }.is_zero(), true);
let a = BigUint::zero();
let b = BigUint::zero();
let c = a * b;
assert_eq!(c.digits, vec![0, 0]);
}
#[test]
fn sub_negative_works() {
assert_eq!(
BigUint::from(10 as Single).sub(&BigUint::from(5 as Single)).unwrap(),
BigUint::from(5 as Single)
);
assert_eq!(
BigUint::from(10 as Single).sub(&BigUint::from(10 as Single)).unwrap(),
BigUint::from(0 as Single)
);
assert_eq!(
BigUint::from(10 as Single).sub(&BigUint::from(13 as Single)).unwrap_err(),
BigUint::from((B - 3) as Single),
);
}
#[test]
fn mul_always_appends_one_digit() {
let a = BigUint::from(10 as Single);
let b = BigUint::from(4 as Single);
assert_eq!(a.len(), 1);
assert_eq!(b.len(), 1);
let n = a.mul(&b);
assert_eq!(n.len(), 2);
assert_eq!(n.digits, vec![0, 40]);
}
#[test]
fn div_conditions_work() {
let a = BigUint { digits: vec![2] };
let b = BigUint { digits: vec![1, 2] };
let c = BigUint { digits: vec![1, 1, 2] };
let d = BigUint { digits: vec![0, 2] };
let e = BigUint { digits: vec![0, 1, 1, 2] };
assert!(a.clone().div(&b, true).is_none());
assert!(c.clone().div(&a, true).is_none());
assert!(c.clone().div(&d, true).is_none());
assert!(e.clone().div(&a, true).is_none());
assert!(c.clone().div(&b, true).is_some());
}
#[test]
fn div_unit_works() {
let a = BigUint { digits: vec![100] };
let b = BigUint { digits: vec![1, 100] };
assert_eq!(a.clone().div_unit(1), a);
assert_eq!(a.clone().div_unit(0), a);
assert_eq!(a.clone().div_unit(2), BigUint::from(50 as Single));
assert_eq!(a.clone().div_unit(7), BigUint::from(14 as Single));
assert_eq!(b.clone().div_unit(1), b);
assert_eq!(b.clone().div_unit(0), b);
assert_eq!(b.clone().div_unit(2), BigUint::from(((B + 100) / 2) as Single));
assert_eq!(b.clone().div_unit(7), BigUint::from(((B + 100) / 7) as Single));
}
}
@@ -0,0 +1,326 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use sp_std::{
ops, prelude::*,
convert::{TryFrom, TryInto},
};
use codec::{Encode, Decode};
use crate::{
Perbill,
traits::{
SaturatedConversion, CheckedSub, CheckedAdd, CheckedDiv, Bounded, UniqueSaturatedInto, Saturating
}
};
/// An unsigned fixed point number. Can hold any value in the range [-9_223_372_036, 9_223_372_036]
/// with fixed point accuracy of one billion.
#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Fixed64(i64);
/// The accuracy of the `Fixed64` type.
const DIV: i64 = 1_000_000_000;
impl Fixed64 {
/// creates self from a natural number.
///
/// Note that this might be lossy.
pub fn from_natural(int: i64) -> Self {
Self(int.saturating_mul(DIV))
}
/// Return the accuracy of the type. Given that this function returns the value `X`, it means
/// that an instance composed of `X` parts (`Fixed64::from_parts(X)`) is equal to `1`.
pub fn accuracy() -> i64 {
DIV
}
/// Consume self and return the inner value.
///
/// This should only be used for testing.
#[cfg(any(feature = "std", test))]
pub fn into_inner(self) -> i64 { self.0 }
/// Raw constructor. Equal to `parts / 1_000_000_000`.
pub fn from_parts(parts: i64) -> Self {
Self(parts)
}
/// creates self from a rational number. Equal to `n/d`.
///
/// Note that this might be lossy.
pub fn from_rational(n: i64, d: u64) -> Self {
Self(
(i128::from(n).saturating_mul(i128::from(DIV)) / i128::from(d).max(1))
.try_into()
.unwrap_or_else(|_| Bounded::max_value())
)
}
/// Performs a saturated multiply and accumulate by unsigned number.
///
/// Returns a saturated `int + (self * int)`.
pub fn saturated_multiply_accumulate<N>(self, int: N) -> N
where
N: TryFrom<u64> + From<u32> + UniqueSaturatedInto<u32> + Bounded + Clone + Saturating +
ops::Rem<N, Output=N> + ops::Div<N, Output=N> + ops::Mul<N, Output=N> +
ops::Add<N, Output=N>,
{
let div = DIV as u64;
let positive = self.0 > 0;
// safe to convert as absolute value.
let parts = self.0.checked_abs().map(|v| v as u64).unwrap_or(i64::max_value() as u64 + 1);
// will always fit.
let natural_parts = parts / div;
// might saturate.
let natural_parts: N = natural_parts.saturated_into();
// fractional parts can always fit into u32.
let perbill_parts = (parts % div) as u32;
let n = int.clone().saturating_mul(natural_parts);
let p = Perbill::from_parts(perbill_parts) * int.clone();
// everything that needs to be either added or subtracted from the original weight.
let excess = n.saturating_add(p);
if positive {
int.saturating_add(excess)
} else {
int.saturating_sub(excess)
}
}
}
impl Saturating for Fixed64 {
fn saturating_add(self, rhs: Self) -> Self {
Self(self.0.saturating_add(rhs.0))
}
fn saturating_mul(self, rhs: Self) -> Self {
Self(self.0.saturating_mul(rhs.0) / DIV)
}
fn saturating_sub(self, rhs: Self) -> Self {
Self(self.0.saturating_sub(rhs.0))
}
}
/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait
/// for safe addition.
impl ops::Add for Fixed64 {
type Output = Self;
fn add(self, rhs: Self) -> Self::Output {
Self(self.0 + rhs.0)
}
}
/// Note that this is a standard, _potentially-panicking_, implementation. Use `Saturating` trait
/// for safe subtraction.
impl ops::Sub for Fixed64 {
type Output = Self;
fn sub(self, rhs: Self) -> Self::Output {
Self(self.0 - rhs.0)
}
}
/// Note that this is a standard, _potentially-panicking_, implementation. Use `CheckedDiv` trait
/// for safe division.
impl ops::Div for Fixed64 {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
if rhs.0 == 0 {
let zero = 0;
return Fixed64::from_parts( self.0 / zero);
}
let (n, d) = if rhs.0 < 0 {
(-self.0, rhs.0.abs() as u64)
} else {
(self.0, rhs.0 as u64)
};
Fixed64::from_rational(n, d)
}
}
impl CheckedSub for Fixed64 {
fn checked_sub(&self, rhs: &Self) -> Option<Self> {
self.0.checked_sub(rhs.0).map(Self)
}
}
impl CheckedAdd for Fixed64 {
fn checked_add(&self, rhs: &Self) -> Option<Self> {
self.0.checked_add(rhs.0).map(Self)
}
}
impl CheckedDiv for Fixed64 {
fn checked_div(&self, rhs: &Self) -> Option<Self> {
if rhs.0 == 0 {
None
} else {
Some(*self / *rhs)
}
}
}
impl sp_std::fmt::Debug for Fixed64 {
#[cfg(feature = "std")]
fn fmt(&self, f: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
write!(f, "Fixed64({},{})", self.0 / DIV, (self.0 % DIV) / 1000)
}
#[cfg(not(feature = "std"))]
fn fmt(&self, _: &mut sp_std::fmt::Formatter) -> sp_std::fmt::Result {
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
fn max() -> Fixed64 {
Fixed64::from_parts(i64::max_value())
}
#[test]
fn fixed64_semantics() {
assert_eq!(Fixed64::from_rational(5, 2).0, 5 * 1_000_000_000 / 2);
assert_eq!(Fixed64::from_rational(5, 2), Fixed64::from_rational(10, 4));
assert_eq!(Fixed64::from_rational(5, 0), Fixed64::from_rational(5, 1));
// biggest value that can be created.
assert_ne!(max(), Fixed64::from_natural(9_223_372_036));
assert_eq!(max(), Fixed64::from_natural(9_223_372_037));
}
#[test]
fn fixed_64_growth_decrease_curve() {
let test_set = vec![0u32, 1, 10, 1000, 1_000_000_000];
// negative (1/2)
let mut fm = Fixed64::from_rational(-1, 2);
test_set.clone().into_iter().for_each(|i| {
assert_eq!(fm.saturated_multiply_accumulate(i) as i32, i as i32 - i as i32 / 2);
});
// unit (1) multiplier
fm = Fixed64::from_parts(0);
test_set.clone().into_iter().for_each(|i| {
assert_eq!(fm.saturated_multiply_accumulate(i), i);
});
// i.5 multiplier
fm = Fixed64::from_rational(1, 2);
test_set.clone().into_iter().for_each(|i| {
assert_eq!(fm.saturated_multiply_accumulate(i), i * 3 / 2);
});
// dual multiplier
fm = Fixed64::from_rational(1, 1);
test_set.clone().into_iter().for_each(|i| {
assert_eq!(fm.saturated_multiply_accumulate(i), i * 2);
});
}
macro_rules! saturating_mul_acc_test {
($num_type:tt) => {
assert_eq!(
Fixed64::from_rational(100, 1).saturated_multiply_accumulate(10 as $num_type),
1010,
);
assert_eq!(
Fixed64::from_rational(100, 2).saturated_multiply_accumulate(10 as $num_type),
510,
);
assert_eq!(
Fixed64::from_rational(100, 3).saturated_multiply_accumulate(0 as $num_type),
0,
);
assert_eq!(
Fixed64::from_rational(5, 1).saturated_multiply_accumulate($num_type::max_value()),
$num_type::max_value()
);
assert_eq!(
max().saturated_multiply_accumulate($num_type::max_value()),
$num_type::max_value()
);
}
}
#[test]
fn fixed64_multiply_accumulate_works() {
saturating_mul_acc_test!(u32);
saturating_mul_acc_test!(u64);
saturating_mul_acc_test!(u128);
}
#[test]
fn div_works() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 100));
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a / b, Fixed64::from_rational(120, 1));
let a = Fixed64::from_rational(12, 100);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 1000));
let a = Fixed64::from_rational(12, 100);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a / b, Fixed64::from_rational(12, 1));
let a = Fixed64::from_rational(-12, 10);
let b = Fixed64::from_rational(10, 1);
assert_eq!(a / b, Fixed64::from_rational(-12, 100));
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(-10, 1);
assert_eq!(a / b, Fixed64::from_rational(-12, 100));
let a = Fixed64::from_rational(-12, 10);
let b = Fixed64::from_rational(-10, 1);
assert_eq!(a / b, Fixed64::from_rational(12, 100));
}
#[test]
#[should_panic(expected = "attempt to divide by zero")]
fn div_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_natural(0);
let _ = a / b;
}
#[test]
fn checked_div_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_natural(0);
assert_eq!(a.checked_div(&b), None);
}
#[test]
fn checked_div_non_zero() {
let a = Fixed64::from_rational(12, 10);
let b = Fixed64::from_rational(1, 100);
assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1)));
}
}
@@ -0,0 +1,112 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Some helper functions to work with 128bit numbers. Note that the functionality provided here is
//! only sensible to use with 128bit numbers because for smaller sizes, you can always rely on
//! assumptions of a bigger type (u128) being available, or simply create a per-thing and use the
//! multiplication implementation provided there.
use crate::biguint;
use num_traits::Zero;
use sp_std::{cmp::{min, max}, convert::TryInto, mem};
/// Helper gcd function used in Rational128 implementation.
pub fn gcd(a: u128, b: u128) -> u128 {
match ((a, b), (a & 1, b & 1)) {
((x, y), _) if x == y => y,
((0, x), _) | ((x, 0), _) => x,
((x, y), (0, 1)) | ((y, x), (1, 0)) => gcd(x >> 1, y),
((x, y), (0, 0)) => gcd(x >> 1, y >> 1) << 1,
((x, y), (1, 1)) => {
let (x, y) = (min(x, y), max(x, y));
gcd((y - x) >> 1, x)
},
_ => unreachable!(),
}
}
/// split a u128 into two u64 limbs
pub fn split(a: u128) -> (u64, u64) {
let al = a as u64;
let ah = (a >> 64) as u64;
(ah, al)
}
/// Convert a u128 to a u32 based biguint.
pub fn to_big_uint(x: u128) -> biguint::BigUint {
let (xh, xl) = split(x);
let (xhh, xhl) = biguint::split(xh);
let (xlh, xll) = biguint::split(xl);
let mut n = biguint::BigUint::from_limbs(&[xhh, xhl, xlh, xll]);
n.lstrip();
n
}
/// Safely and accurately compute `a * b / c`. The approach is:
/// - Simply try `a * b / c`.
/// - Else, convert them both into big numbers and re-try. `Err` is returned if the result
/// cannot be safely casted back to u128.
///
/// 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()); }
c = c.max(1);
// a and b are interchangeable by definition in this function. It always helps to assume the
// bigger of which is being multiplied by a `0 < b/c < 1`. Hence, a should be the bigger and
// b the smaller one.
if b > a {
mem::swap(&mut a, &mut b);
}
// Attempt to perform the division first
if a % c == 0 {
a /= c;
c = 1;
} else if b % c == 0 {
b /= c;
c = 1;
}
if let Some(x) = a.checked_mul(b) {
// This is the safest way to go. Try it.
Ok(x / c)
} else {
let a_num = to_big_uint(a);
let b_num = to_big_uint(b);
let c_num = to_big_uint(c);
let mut ab = a_num * b_num;
ab.lstrip();
let mut q = if c_num.len() == 1 {
// PROOF: if `c_num.len() == 1` then `c` fits in one limb.
ab.div_unit(c as biguint::Single)
} else {
// PROOF: both `ab` and `c` cannot have leading zero limbs; if length of `c` is 1,
// the previous branch would handle. Also, if ab for sure has a bigger size than
// c, because `a.checked_mul(b)` has failed, hence ab must be at least one limb
// 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)); }
q
};
q.lstrip();
q.try_into().map_err(|_| "result cannot fit in u128")
}
}
@@ -0,0 +1,44 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Minimal fixed point arithmetic primitives and types for runtime.
#![cfg_attr(not(feature = "std"), no_std)]
/// Copied from `sp-runtime` and documented there.
#[cfg(test)]
macro_rules! assert_eq_error_rate {
($x:expr, $y:expr, $error:expr $(,)?) => {
assert!(
($x) >= (($y) - ($error)) && ($x) <= (($y) + ($error)),
"{:?} != {:?} (with error rate {:?})",
$x,
$y,
$error,
);
};
}
pub mod biguint;
pub mod helpers_128bit;
pub mod traits;
mod per_things;
mod fixed64;
mod rational128;
pub use fixed64::Fixed64;
pub use per_things::{Percent, Permill, Perbill, Perquintill};
pub use rational128::Rational128;
@@ -0,0 +1,520 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
#[cfg(feature = "std")]
use serde::{Serialize, Deserialize};
use sp_std::{ops, prelude::*, convert::TryInto};
use codec::{Encode, Decode, CompactAs};
use crate::traits::{SaturatedConversion, UniqueSaturatedInto, Saturating};
use sp_debug_derive::RuntimeDebug;
macro_rules! implement_per_thing {
($name:ident, $test_mod:ident, [$($test_units:tt),+], $max:tt, $type:ty, $upper_type:ty, $title:expr $(,)?) => {
/// A fixed point representation of a number between in the range [0, 1].
///
#[doc = $title]
#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
#[derive(Encode, Decode, Default, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, CompactAs)]
pub struct $name($type);
impl $name {
/// Nothing.
pub fn zero() -> Self { Self(0) }
/// `true` if this is nothing.
pub fn is_zero(&self) -> bool { self.0 == 0 }
/// Everything.
pub fn one() -> Self { Self($max) }
/// Consume self and deconstruct into a raw numeric type.
pub fn deconstruct(self) -> $type { self.0 }
/// Return the scale at which this per-thing is working.
pub const fn accuracy() -> $type { $max }
/// From an explicitly defined number of parts per maximum of the type.
///
/// This can be called at compile time.
pub const fn from_parts(parts: $type) -> Self {
Self([parts, $max][(parts > $max) as usize])
}
/// Converts from a percent. Equal to `x / 100`.
///
/// This can be created at compile time.
pub const fn from_percent(x: $type) -> Self {
Self([x, 100][(x > 100) as usize] * ($max / 100))
}
/// Return the product of multiplication of this value by itself.
pub fn square(self) -> Self {
// both can be safely casted and multiplied.
let p: $upper_type = self.0 as $upper_type * self.0 as $upper_type;
let q: $upper_type = <$upper_type>::from($max) * <$upper_type>::from($max);
Self::from_rational_approximation(p, q)
}
/// Converts a fraction into `Permill`.
#[cfg(feature = "std")]
pub fn from_fraction(x: f64) -> Self { Self((x * ($max as f64)) as $type) }
/// Approximate the fraction `p/q` into a per-thing fraction. This will never overflow.
///
/// The computation of this approximation is performed in the generic type `N`. Given
/// `M` as the data type that can hold the maximum value of this per-thing (e.g. u32 for
/// perbill), this can only work if `N == M` or `N: From<M> + TryInto<M>`.
pub fn from_rational_approximation<N>(p: N, q: N) -> Self
where N: Clone + Ord + From<$type> + TryInto<$type> + ops::Div<N, Output=N>
{
// q cannot be zero.
let q = q.max((1 as $type).into());
// p should not be bigger than q.
let p = p.min(q.clone());
let factor = (q.clone() / $max.into()).max((1 as $type).into());
// q cannot overflow: (q / (q/$max)) < 2 * $max. p < q hence p also cannot overflow.
// this implies that $type must be able to fit 2 * $max.
let q_reduce: $type = (q / factor.clone())
.try_into()
.map_err(|_| "Failed to convert")
.expect(
"q / (q/$max) < (2 * $max). Macro prevents any type being created that \
does not satisfy this; qed"
);
let p_reduce: $type = (p / factor.clone())
.try_into()
.map_err(|_| "Failed to convert")
.expect(
"q / (q/$max) < (2 * $max). Macro prevents any type being created that \
does not satisfy this; qed"
);
// `p_reduced` and `q_reduced` are withing $type. Mul by another $max will always
// fit in $upper_type. This is guaranteed by the macro tests.
let part =
p_reduce as $upper_type
* <$upper_type>::from($max)
/ q_reduce as $upper_type;
$name(part as $type)
}
}
impl Saturating for $name {
fn saturating_add(self, rhs: Self) -> Self {
// defensive-only: since `$max * 2 < $type::max_value()`, this can never overflow.
Self::from_parts(self.0.saturating_add(rhs.0))
}
fn saturating_sub(self, rhs: Self) -> Self {
Self::from_parts(self.0.saturating_sub(rhs.0))
}
fn saturating_mul(self, rhs: Self) -> Self {
let a = self.0 as $upper_type;
let b = rhs.0 as $upper_type;
let m = <$upper_type>::from($max);
let parts = a * b / m;
// This will always fit into $type.
Self::from_parts(parts as $type)
}
}
impl ops::Div for $name {
type Output = Self;
fn div(self, rhs: Self) -> Self::Output {
let p = self.0;
let q = rhs.0;
Self::from_rational_approximation(p, q)
}
}
/// Overflow-prune multiplication.
///
/// tailored to be used with a balance type.
impl<N> ops::Mul<N> for $name
where
N: Clone + From<$type> + UniqueSaturatedInto<$type> + ops::Rem<N, Output=N>
+ ops::Div<N, Output=N> + ops::Mul<N, Output=N> + ops::Add<N, Output=N>,
{
type Output = N;
fn mul(self, b: N) -> Self::Output {
let maximum: N = $max.into();
let upper_max: $upper_type = $max.into();
let part: N = self.0.into();
let rem_multiplied_divided = {
let rem = b.clone().rem(maximum.clone());
// `rem_sized` is inferior to $max, thus it fits into $type. This is assured by
// a test.
let rem_sized = rem.saturated_into::<$type>();
// `self` and `rem_sized` are inferior to $max, thus the product is less than
// $max^2 and fits into $upper_type. This is assured by a test.
let rem_multiplied_upper = rem_sized as $upper_type * self.0 as $upper_type;
// `rem_multiplied_upper` is less than $max^2 therefore divided by $max it fits
// in $type. remember that $type always fits $max.
let mut rem_multiplied_divided_sized =
(rem_multiplied_upper / upper_max) as $type;
// fix a tiny rounding error
if rem_multiplied_upper % upper_max > upper_max / 2 {
rem_multiplied_divided_sized += 1;
}
// `rem_multiplied_divided_sized` is inferior to b, thus it can be converted
// back to N type
rem_multiplied_divided_sized.into()
};
(b / maximum) * part + rem_multiplied_divided
}
}
#[cfg(test)]
mod $test_mod {
use codec::{Encode, Decode};
use super::{$name, Saturating, RuntimeDebug};
use crate::traits::Zero;
#[test]
fn macro_expanded_correctly() {
// needed for the `from_percent` to work.
assert!($max >= 100);
assert!($max % 100 == 0);
// needed for `from_rational_approximation`
assert!(2 * $max < <$type>::max_value());
assert!(<$upper_type>::from($max) < <$upper_type>::max_value());
// for something like percent they can be the same.
assert!((<$type>::max_value() as $upper_type) <= <$upper_type>::max_value());
assert!(<$upper_type>::from($max).checked_mul($max.into()).is_some());
}
#[derive(Encode, Decode, PartialEq, Eq, RuntimeDebug)]
struct WithCompact<T: codec::HasCompact> {
data: T,
}
#[test]
fn has_compact() {
let data = WithCompact { data: $name(1) };
let encoded = data.encode();
assert_eq!(data, WithCompact::<$name>::decode(&mut &encoded[..]).unwrap());
}
#[test]
fn compact_encoding() {
let tests = [
// assume all per_things have the size u8 at least.
(0 as $type, 1usize),
(1 as $type, 1usize),
(63, 1),
(64, 2),
(65, 2),
(<$type>::max_value(), <$type>::max_value().encode().len() + 1)
];
for &(n, l) in &tests {
let compact: codec::Compact<$name> = $name(n).into();
let encoded = compact.encode();
assert_eq!(encoded.len(), l);
let decoded = <codec::Compact<$name>>::decode(&mut & encoded[..])
.unwrap();
let per_thingy: $name = decoded.into();
assert_eq!(per_thingy, $name(n));
}
}
#[test]
fn per_thing_api_works() {
// some really basic stuff
assert_eq!($name::zero(), $name::from_parts(Zero::zero()));
assert_eq!($name::one(), $name::from_parts($max));
assert_eq!($name::accuracy(), $max);
assert_eq!($name::from_percent(0), $name::from_parts(Zero::zero()));
assert_eq!($name::from_percent(10), $name::from_parts($max / 10));
assert_eq!($name::from_percent(100), $name::from_parts($max));
}
macro_rules! per_thing_mul_test {
($num_type:tt) => {
// multiplication from all sort of from_percent
assert_eq!(
$name::from_percent(100) * $num_type::max_value(),
$num_type::max_value()
);
assert_eq_error_rate!(
$name::from_percent(99) * $num_type::max_value(),
((Into::<U256>::into($num_type::max_value()) * 99u32) / 100u32).as_u128() as $num_type,
1,
);
assert_eq!(
$name::from_percent(50) * $num_type::max_value(),
$num_type::max_value() / 2,
);
assert_eq_error_rate!(
$name::from_percent(1) * $num_type::max_value(),
$num_type::max_value() / 100,
1,
);
assert_eq!($name::from_percent(0) * $num_type::max_value(), 0);
// // multiplication with bounds
assert_eq!($name::one() * $num_type::max_value(), $num_type::max_value());
assert_eq!($name::zero() * $num_type::max_value(), 0);
}
}
#[test]
fn per_thing_mul_works() {
use primitive_types::U256;
// accuracy test
assert_eq!($name::from_rational_approximation(1 as $type, 3) * 30 as $type, 10);
$(per_thing_mul_test!($test_units);)*
}
#[test]
fn per_thing_mul_rounds_to_nearest_number() {
assert_eq!($name::from_percent(33) * 10u64, 3);
assert_eq!($name::from_percent(34) * 10u64, 3);
assert_eq!($name::from_percent(35) * 10u64, 3);
assert_eq!($name::from_percent(36) * 10u64, 4);
assert_eq!($name::from_percent(36) * 10u64, 4);
}
#[test]
fn per_thing_multiplication_with_large_number() {
use primitive_types::U256;
let max_minus_one = $max - 1;
assert_eq_error_rate!(
$name::from_parts(max_minus_one) * std::u128::MAX,
((Into::<U256>::into(std::u128::MAX) * max_minus_one) / $max).as_u128(),
1,
);
}
macro_rules! per_thing_from_rationale_approx_test {
($num_type:tt) => {
// within accuracy boundary
assert_eq!(
$name::from_rational_approximation(1 as $num_type, 0),
$name::one(),
);
assert_eq!(
$name::from_rational_approximation(1 as $num_type, 1),
$name::one(),
);
assert_eq_error_rate!(
$name::from_rational_approximation(1 as $num_type, 3).0,
$name::from_parts($max / 3).0,
2
);
assert_eq!(
$name::from_rational_approximation(1 as $num_type, 10),
$name::from_percent(10),
);
assert_eq!(
$name::from_rational_approximation(1 as $num_type, 4),
$name::from_percent(25),
);
assert_eq!(
$name::from_rational_approximation(1 as $num_type, 4),
$name::from_rational_approximation(2 as $num_type, 8),
);
// no accurate anymore but won't overflow.
assert_eq!(
$name::from_rational_approximation(
$num_type::max_value() - 1,
$num_type::max_value()
),
$name::one(),
);
assert_eq_error_rate!(
$name::from_rational_approximation(
$num_type::max_value() / 3,
$num_type::max_value()
).0,
$name::from_parts($max / 3).0,
2
);
assert_eq!(
$name::from_rational_approximation(1, $num_type::max_value()),
$name::zero(),
);
};
}
#[test]
fn per_thing_from_rationale_approx_works() {
// This is just to make sure something like Percent which _might_ get built from a
// u8 does not overflow in the context of this test.
let max_value = <$upper_type>::from($max);
// almost at the edge
assert_eq!(
$name::from_rational_approximation($max - 1, $max + 1),
$name::from_parts($max - 2),
);
assert_eq!(
$name::from_rational_approximation(1, $max-1),
$name::from_parts(1),
);
assert_eq!(
$name::from_rational_approximation(1, $max),
$name::from_parts(1),
);
assert_eq!(
$name::from_rational_approximation(2, 2 * $max - 1),
$name::from_parts(1),
);
assert_eq!(
$name::from_rational_approximation(1, $max+1),
$name::zero(),
);
assert_eq!(
$name::from_rational_approximation(3 * max_value / 2, 3 * max_value),
$name::from_percent(50),
);
$(per_thing_from_rationale_approx_test!($test_units);)*
}
#[test]
fn per_things_mul_operates_in_output_type() {
// assert_eq!($name::from_percent(50) * 100u32, 50u32);
assert_eq!($name::from_percent(50) * 100u64, 50u64);
assert_eq!($name::from_percent(50) * 100u128, 50u128);
}
#[test]
fn per_thing_saturating_op_works() {
assert_eq!(
$name::from_percent(50).saturating_add($name::from_percent(40)),
$name::from_percent(90)
);
assert_eq!(
$name::from_percent(50).saturating_add($name::from_percent(50)),
$name::from_percent(100)
);
assert_eq!(
$name::from_percent(60).saturating_add($name::from_percent(50)),
$name::from_percent(100)
);
assert_eq!(
$name::from_percent(60).saturating_sub($name::from_percent(50)),
$name::from_percent(10)
);
assert_eq!(
$name::from_percent(60).saturating_sub($name::from_percent(60)),
$name::from_percent(0)
);
assert_eq!(
$name::from_percent(60).saturating_sub($name::from_percent(70)),
$name::from_percent(0)
);
assert_eq!(
$name::from_percent(50).saturating_mul($name::from_percent(50)),
$name::from_percent(25)
);
assert_eq!(
$name::from_percent(20).saturating_mul($name::from_percent(20)),
$name::from_percent(4)
);
assert_eq!(
$name::from_percent(10).saturating_mul($name::from_percent(10)),
$name::from_percent(1)
);
}
#[test]
fn per_thing_square_works() {
assert_eq!($name::from_percent(100).square(), $name::from_percent(100));
assert_eq!($name::from_percent(50).square(), $name::from_percent(25));
assert_eq!($name::from_percent(10).square(), $name::from_percent(1));
assert_eq!(
$name::from_percent(2).square(),
$name::from_parts((4 * <$upper_type>::from($max) / 100 / 100) as $type)
);
}
#[test]
fn per_things_div_works() {
// normal
assert_eq!($name::from_percent(10) / $name::from_percent(20),
$name::from_percent(50)
);
assert_eq!($name::from_percent(10) / $name::from_percent(10),
$name::from_percent(100)
);
assert_eq!($name::from_percent(10) / $name::from_percent(0),
$name::from_percent(100)
);
// will not overflow
assert_eq!($name::from_percent(10) / $name::from_percent(5),
$name::from_percent(100)
);
assert_eq!($name::from_percent(100) / $name::from_percent(50),
$name::from_percent(100)
);
}
}
};
}
implement_per_thing!(
Percent,
test_per_cent,
[u32, u64, u128],
100u8,
u8,
u16,
"_Percent_",
);
implement_per_thing!(
Permill,
test_permill,
[u32, u64, u128],
1_000_000u32,
u32,
u64,
"_Parts per Million_",
);
implement_per_thing!(
Perbill,
test_perbill,
[u32, u64, u128],
1_000_000_000u32,
u32,
u64,
"_Parts per Billion_",
);
implement_per_thing!(
Perquintill,
test_perquintill,
[u64, u128],
1_000_000_000_000_000_000u64,
u64,
u128,
"_Parts per Quintillion_",
);
@@ -0,0 +1,384 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use sp_std::{cmp::Ordering, prelude::*};
use crate::helpers_128bit;
use num_traits::Zero;
use sp_debug_derive::RuntimeDebug;
/// A wrapper for any rational number with a 128 bit numerator and denominator.
#[derive(Clone, Copy, Default, Eq, RuntimeDebug)]
pub struct Rational128(u128, u128);
impl Rational128 {
/// Nothing.
pub fn zero() -> Self {
Self(0, 1)
}
/// If it is zero or not
pub fn is_zero(&self) -> bool {
self.0.is_zero()
}
/// Build from a raw `n/d`.
pub fn from(n: u128, d: u128) -> Self {
Self(n, d.max(1))
}
/// Build from a raw `n/d`. This could lead to / 0 if not properly handled.
pub fn from_unchecked(n: u128, d: u128) -> Self {
Self(n, d)
}
/// Return the numerator.
pub fn n(&self) -> u128 {
self.0
}
/// Return the denominator.
pub fn d(&self) -> u128 {
self.1
}
/// Convert `self` to a similar rational number where denominator is the given `den`.
//
/// This only returns if the result is accurate. `Err` is returned if the result cannot be
/// accurately calculated.
pub fn to_den(self, den: u128) -> Result<Self, &'static str> {
if den == self.1 {
Ok(self)
} else {
helpers_128bit::multiply_by_rational(self.0, den, self.1).map(|n| Self(n, den))
}
}
/// Get the least common divisor of `self` and `other`.
///
/// This only returns if the result is accurate. `Err` is returned if the result cannot be
/// 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) }
let g = helpers_128bit::gcd(self.1, other.1);
helpers_128bit::multiply_by_rational(self.1 , other.1, g)
}
/// A saturating add that assumes `self` and `other` have the same denominator.
pub fn lazy_saturating_add(self, other: Self) -> Self {
if other.is_zero() {
self
} else {
Self(self.0.saturating_add(other.0) ,self.1)
}
}
/// A saturating subtraction that assumes `self` and `other` have the same denominator.
pub fn lazy_saturating_sub(self, other: Self) -> Self {
if other.is_zero() {
self
} else {
Self(self.0.saturating_sub(other.0) ,self.1)
}
}
/// Addition. Simply tries to unify the denominators and add the numerators.
///
/// Overflow might happen during any of the steps. Error is returned in such cases.
pub fn checked_add(self, other: Self) -> Result<Self, &'static str> {
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)
.ok_or("overflow while adding numerators")?;
Ok(Self(n, self_scaled.1))
}
/// Subtraction. Simply tries to unify the denominators and subtract the numerators.
///
/// Overflow might happen during any of the steps. None is returned in such cases.
pub fn checked_sub(self, other: Self) -> Result<Self, &'static str> {
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_sub(other_scaled.0)
.ok_or("overflow while subtracting numerators")?;
Ok(Self(n, self_scaled.1))
}
}
impl PartialOrd for Rational128 {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for Rational128 {
fn cmp(&self, other: &Self) -> Ordering {
// handle some edge cases.
if self.1 == other.1 {
self.0.cmp(&other.0)
} else if self.1.is_zero() {
Ordering::Greater
} else if other.1.is_zero() {
Ordering::Less
} 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);
self_n.cmp(&other_n)
}
}
}
impl PartialEq for Rational128 {
fn eq(&self, other: &Self) -> bool {
// handle some edge cases.
if self.1 == other.1 {
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);
self_n.eq(&other_n)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use super::helpers_128bit::*;
const MAX128: u128 = u128::max_value();
const MAX64: u128 = u64::max_value() as u128;
const MAX64_2: u128 = 2 * u64::max_value() as u128;
fn r(p: u128, q: u128) -> Rational128 {
Rational128(p, q)
}
fn mul_div(a: u128, b: u128, c: u128) -> u128 {
use primitive_types::U256;
if a.is_zero() { return Zero::zero(); }
let c = c.max(1);
// e for extended
let ae: U256 = a.into();
let be: U256 = b.into();
let ce: U256 = c.into();
let r = ae * be / ce;
if r > u128::max_value().into() {
a
} else {
r.as_u128()
}
}
#[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)
);
// and it returns a if result cannot fit
assert_eq!(mul_div(MAX128 - 10, 2, 1), MAX128 - 10);
}
#[test]
fn to_denom_works() {
// simple up and down
assert_eq!(r(1, 5).to_den(10), Ok(r(2, 10)));
assert_eq!(r(4, 10).to_den(5), Ok(r(2, 5)));
// up and down with large numbers
assert_eq!(r(MAX128 - 10, MAX128).to_den(10), Ok(r(10, 10)));
assert_eq!(r(MAX128 / 2, MAX128).to_den(10), Ok(r(5, 10)));
// large to perbill. This is very well needed for phragmen.
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)));
}
#[test]
fn gdc_works() {
assert_eq!(gcd(10, 5), 5);
assert_eq!(gcd(7, 22), 1);
}
#[test]
fn lcm_works() {
// simple stuff
assert_eq!(r(3, 10).lcm(&r(4, 15)).unwrap(), 30);
assert_eq!(r(5, 30).lcm(&r(1, 7)).unwrap(), 210);
assert_eq!(r(5, 30).lcm(&r(1, 10)).unwrap(), 30);
// large numbers
assert_eq!(
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)),
Ok(340282366920938463408034375210639556610),
);
assert!(340282366920938463408034375210639556610 < MAX128);
assert!(340282366920938463408034375210639556610 == MAX64 * (MAX64 - 1));
}
#[test]
fn add_works() {
// works
assert_eq!(r(3, 10).checked_add(r(1, 10)).unwrap(), r(2, 5));
assert_eq!(r(3, 10).checked_add(r(3, 7)).unwrap(), r(51, 70));
// errors
assert_eq!(
r(1, MAX128).checked_add(r(1, MAX128-1)),
Err("failed to scale to denominator"),
);
assert_eq!(
r(7, MAX128).checked_add(r(MAX128, MAX128)),
Err("overflow while adding numerators"),
);
assert_eq!(
r(MAX128, MAX128).checked_add(r(MAX128, MAX128)),
Err("overflow while adding numerators"),
);
}
#[test]
fn sub_works() {
// works
assert_eq!(r(3, 10).checked_sub(r(1, 10)).unwrap(), r(1, 5));
assert_eq!(r(6, 10).checked_sub(r(3, 7)).unwrap(), r(12, 70));
// errors
assert_eq!(
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"),
);
}
#[test]
fn ordering_and_eq_works() {
assert!(r(1, 2) > r(1, 3));
assert!(r(1, 2) > r(2, 6));
assert!(r(1, 2) < r(6, 6));
assert!(r(2, 1) > r(2, 6));
assert!(r(5, 10) == r(1, 2));
assert!(r(1, 2) == r(1, 2));
assert!(r(1, 1490000000000200000) > r(1, 1490000000000200001));
}
#[test]
fn multiply_by_rational_works() {
assert_eq!(multiply_by_rational(7, 2, 3).unwrap(), 7 * 2 / 3);
assert_eq!(multiply_by_rational(7, 20, 30).unwrap(), 7 * 2 / 3);
assert_eq!(multiply_by_rational(20, 7, 30).unwrap(), 7 * 2 / 3);
assert_eq!(
// MAX128 % 3 == 0
multiply_by_rational(MAX128, 2, 3).unwrap(),
MAX128 / 3 * 2,
);
assert_eq!(
// MAX128 % 7 == 3
multiply_by_rational(MAX128, 5, 7).unwrap(),
(MAX128 / 7 * 5) + (3 * 5 / 7),
);
assert_eq!(
// MAX128 % 7 == 3
multiply_by_rational(MAX128, 11 , 13).unwrap(),
(MAX128 / 13 * 11) + (8 * 11 / 13),
);
assert_eq!(
// MAX128 % 1000 == 455
multiply_by_rational(MAX128, 555, 1000).unwrap(),
(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(MAX64 + 100, MAX64_2, MAX64_2 / 2).unwrap(),
(MAX64 + 100) * 2,
);
assert_eq!(
multiply_by_rational(MAX64 + 100, MAX64_2 / 100, MAX64_2 / 200).unwrap(),
(MAX64 + 100) * 2,
);
assert_eq!(
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,
);
}
#[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),
);
}
#[test]
#[ignore]
fn multiply_by_rational_fuzzed_equation() {
assert_eq!(
multiply_by_rational(154742576605164960401588224, 9223376310179529214, 549756068598),
Ok(2596149632101417846585204209223679)
);
}
}
@@ -0,0 +1,143 @@
// Copyright 2017-2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
//! Primitives for the runtime modules.
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,
CheckedShl, CheckedShr
};
use sp_std::ops::{
Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
RemAssign, Shl, Shr
};
/// A meta trait for arithmetic.
///
/// Arithmetic types do all the usual stuff you'd expect numbers to do. They are guaranteed to
/// be able to represent at least `u32` values without loss, hence the trait implies `From<u32>`
/// and smaller ints. All other conversions are fallible.
pub trait SimpleArithmetic:
Zero + One + IntegerSquareRoot +
From<u8> + From<u16> + From<u32> + TryInto<u8> + TryInto<u16> + TryInto<u32> +
TryFrom<u64> + TryInto<u64> + TryFrom<u128> + TryInto<u128> + TryFrom<usize> + TryInto<usize> +
UniqueSaturatedInto<u8> + UniqueSaturatedInto<u16> + UniqueSaturatedInto<u32> +
UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128> + UniqueSaturatedInto<u128> +
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
{}
impl<T:
Zero + One + IntegerSquareRoot +
From<u8> + From<u16> + From<u32> + TryInto<u8> + TryInto<u16> + TryInto<u32> +
TryFrom<u64> + TryInto<u64> + TryFrom<u128> + TryInto<u128> + TryFrom<usize> + TryInto<usize> +
UniqueSaturatedInto<u8> + UniqueSaturatedInto<u16> + UniqueSaturatedInto<u32> +
UniqueSaturatedFrom<u64> + UniqueSaturatedInto<u64> + UniqueSaturatedFrom<u128> +
UniqueSaturatedInto<u128> + UniqueSaturatedFrom<usize> + UniqueSaturatedInto<usize> +
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
> SimpleArithmetic for T {}
/// Just like `From` except that if the source value is too big to fit into the destination type
/// then it'll saturate the destination.
pub trait UniqueSaturatedFrom<T: Sized>: Sized {
/// Convert from a value of `T` into an equivalent instance of `Self`.
fn unique_saturated_from(t: T) -> Self;
}
/// Just like `Into` except that if the source value is too big to fit into the destination type
/// then it'll saturate the destination.
pub trait UniqueSaturatedInto<T: Sized>: Sized {
/// Consume self to return an equivalent value of `T`.
fn unique_saturated_into(self) -> T;
}
impl<T: Sized, S: TryFrom<T> + Bounded + Sized> UniqueSaturatedFrom<T> for S {
fn unique_saturated_from(t: T) -> Self {
S::try_from(t).unwrap_or_else(|_| Bounded::max_value())
}
}
impl<T: Bounded + Sized, S: TryInto<T> + Sized> UniqueSaturatedInto<T> for S {
fn unique_saturated_into(self) -> T {
self.try_into().unwrap_or_else(|_| Bounded::max_value())
}
}
/// Simple trait to use checked mul and max value to give a saturated mul operation over
/// supported types.
pub trait Saturating {
/// Saturated addition - if the product can't fit in the type then just use max-value.
fn saturating_add(self, o: Self) -> Self;
/// Saturated subtraction - if the product can't fit in the type then just use max-value.
fn saturating_sub(self, o: Self) -> Self;
/// Saturated multiply - if the product can't fit in the type then just use max-value.
fn saturating_mul(self, o: Self) -> Self;
}
impl<T: CheckedMul + Bounded + num_traits::Saturating> Saturating for T {
fn saturating_add(self, o: Self) -> Self {
<Self as num_traits::Saturating>::saturating_add(self, o)
}
fn saturating_sub(self, o: Self) -> Self {
<Self as num_traits::Saturating>::saturating_sub(self, o)
}
fn saturating_mul(self, o: Self) -> Self {
self.checked_mul(&o).unwrap_or_else(Bounded::max_value)
}
}
/// Convenience type to work around the highly unergonomic syntax needed
/// to invoke the functions of overloaded generic traits, in this case
/// `SaturatedFrom` and `SaturatedInto`.
pub trait SaturatedConversion {
/// Convert from a value of `T` into an equivalent instance of `Self`.
///
/// 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> {
<Self as UniqueSaturatedFrom<T>>::unique_saturated_from(t)
}
/// Consume self to return an equivalent value of `T`.
///
/// 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> {
<Self as UniqueSaturatedInto<T>>::unique_saturated_into(self)
}
}
impl<T: Sized> SaturatedConversion for T {}