mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 21:37:56 +00:00
Accept new Phragmén solutions if they are epsilon better + Better pre-inclusion checks. (#6173)
* part1: Accept inly epsilon better solutions * Fix pre-dispatch check * Fix build * review grumbles * Epsilon -> Threshold
This commit is contained in:
@@ -41,12 +41,89 @@ mod fixed;
|
||||
mod rational128;
|
||||
|
||||
pub use fixed::{FixedPointNumber, Fixed64, Fixed128, FixedPointOperand};
|
||||
pub use per_things::{PerThing, Percent, PerU16, Permill, Perbill, Perquintill};
|
||||
pub use per_things::{PerThing, InnerOf, Percent, PerU16, Permill, Perbill, Perquintill};
|
||||
pub use rational128::Rational128;
|
||||
|
||||
use sp_std::cmp::Ordering;
|
||||
|
||||
/// Trait for comparing two numbers with an threshold.
|
||||
///
|
||||
/// Returns:
|
||||
/// - `Ordering::Greater` if `self` is greater than `other + threshold`.
|
||||
/// - `Ordering::Less` if `self` is less than `other - threshold`.
|
||||
/// - `Ordering::Equal` otherwise.
|
||||
pub trait ThresholdOrd<T> {
|
||||
/// Compare if `self` is `threshold` greater or less than `other`.
|
||||
fn tcmp(&self, other: &T, epsilon: T) -> Ordering;
|
||||
}
|
||||
|
||||
impl<T> ThresholdOrd<T> for T
|
||||
where
|
||||
T: Ord + PartialOrd + Copy + Clone + traits::Zero + traits::Saturating,
|
||||
{
|
||||
fn tcmp(&self, other: &T, threshold: T) -> Ordering {
|
||||
// early exit.
|
||||
if threshold.is_zero() {
|
||||
return self.cmp(&other)
|
||||
}
|
||||
|
||||
let upper_bound = other.saturating_add(threshold);
|
||||
let lower_bound = other.saturating_sub(threshold);
|
||||
|
||||
if upper_bound <= lower_bound {
|
||||
// defensive only. Can never happen.
|
||||
self.cmp(&other)
|
||||
} else {
|
||||
// upper_bound is guaranteed now to be bigger than lower.
|
||||
match (self.cmp(&lower_bound), self.cmp(&upper_bound)) {
|
||||
(Ordering::Greater, Ordering::Greater) => Ordering::Greater,
|
||||
(Ordering::Less, Ordering::Less) => Ordering::Less,
|
||||
_ => Ordering::Equal,
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use sp_std::cmp::Ordering;
|
||||
|
||||
#[test]
|
||||
fn epsilon_ord_works() {
|
||||
let b = 115u32;
|
||||
let e = Perbill::from_percent(10).mul_ceil(b);
|
||||
|
||||
// [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal
|
||||
assert_eq!(103u32.tcmp(&b, e), Ordering::Equal);
|
||||
assert_eq!(104u32.tcmp(&b, e), Ordering::Equal);
|
||||
assert_eq!(115u32.tcmp(&b, e), Ordering::Equal);
|
||||
assert_eq!(120u32.tcmp(&b, e), Ordering::Equal);
|
||||
assert_eq!(126u32.tcmp(&b, e), Ordering::Equal);
|
||||
assert_eq!(127u32.tcmp(&b, e), Ordering::Equal);
|
||||
|
||||
assert_eq!(128u32.tcmp(&b, e), Ordering::Greater);
|
||||
assert_eq!(102u32.tcmp(&b, e), Ordering::Less);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn epsilon_ord_works_with_small_epc() {
|
||||
let b = 115u32;
|
||||
// way less than 1 percent. threshold will be zero. Result should be same as normal ord.
|
||||
let e = Perbill::from_parts(100) * b;
|
||||
|
||||
// [115 - 11,5 (103,5), 115 + 11,5 (126,5)] is all equal
|
||||
assert_eq!(103u32.tcmp(&b, e), 103u32.cmp(&b));
|
||||
assert_eq!(104u32.tcmp(&b, e), 104u32.cmp(&b));
|
||||
assert_eq!(115u32.tcmp(&b, e), 115u32.cmp(&b));
|
||||
assert_eq!(120u32.tcmp(&b, e), 120u32.cmp(&b));
|
||||
assert_eq!(126u32.tcmp(&b, e), 126u32.cmp(&b));
|
||||
assert_eq!(127u32.tcmp(&b, e), 127u32.cmp(&b));
|
||||
|
||||
assert_eq!(128u32.tcmp(&b, e), 128u32.cmp(&b));
|
||||
assert_eq!(102u32.tcmp(&b, e), 102u32.cmp(&b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peru16_rational_does_not_overflow() {
|
||||
|
||||
Reference in New Issue
Block a user