Extend PerThing + Saturating (#5281)

* Extend PerThing + Saturating

* Add saturating_pow to Saturating
* Add saturating_truncating_mul to PerThing (rounding-down mul)
* Add saturating_reciprocal_mul to PerThing (divide x by perthing)
* Provide default methods where possible

* Restore const functions

* Fix test

* Update primitives/arithmetic/src/per_things.rs

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

* Add comment and test verifying no overflow

* Formatting

* Fix possible overflow and change type constraint

* Use overflow pruning for all mul

* Formatting and comments

* Improve comments and names

* Comments in `rational_mul_correction` explain overflow aversion.

* Test rational_mul_correction

* Formatting

* Docs and formatting

* Add new trait methods to Perthing type impl

* Fix signature

* saturating_pow for Delegations

* Add missing trait method to impl

Co-authored-by: Kian Paimani <5588131+kianenigma@users.noreply.github.com>
This commit is contained in:
Joseph Mark
2020-03-29 13:24:11 +02:00
committed by GitHub
parent d7ffef43ce
commit e8835d64a1
4 changed files with 536 additions and 151 deletions
+22 -10
View File
@@ -21,7 +21,7 @@ use codec::HasCompact;
pub use integer_sqrt::IntegerSquareRoot;
pub use num_traits::{
Zero, One, Bounded, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv,
CheckedShl, CheckedShr
CheckedShl, CheckedShr, checked_pow
};
use sp_std::ops::{
Add, Sub, Mul, Div, Rem, AddAssign, SubAssign, MulAssign, DivAssign,
@@ -104,29 +104,41 @@ impl<T: Bounded + Sized, S: TryInto<T> + Sized> UniqueSaturatedInto<T> for S {
}
}
/// Simple trait to use checked mul and max value to give a saturated mul operation over
/// supported types.
/// Saturating arithmetic operations, returning maximum or minimum values instead of overflowing.
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;
/// Saturating addition. Compute `self + rhs`, saturating at the numeric bounds instead of
/// overflowing.
fn saturating_add(self, rhs: 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;
/// Saturating subtraction. Compute `self - rhs`, saturating at the numeric bounds instead of
/// overflowing.
fn saturating_sub(self, rhs: 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;
/// Saturating multiply. Compute `self * rhs`, saturating at the numeric bounds instead of
/// overflowing.
fn saturating_mul(self, rhs: Self) -> Self;
/// Saturating exponentiation. Compute `self.pow(exp)`, saturating at the numeric bounds
/// instead of overflowing.
fn saturating_pow(self, exp: usize) -> Self;
}
impl<T: CheckedMul + Bounded + num_traits::Saturating> Saturating for T {
impl<T: Clone + One + 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)
}
fn saturating_pow(self, exp: usize) -> Self {
checked_pow(self, exp).unwrap_or_else(Bounded::max_value)
}
}
/// Convenience type to work around the highly unergonomic syntax needed