mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-28 01:38:04 +00:00
Use sensible maths for from_rational (#13660)
* Use sensible maths for from_rational * Fixes * Fixes * More fixes * Remove debugging * Add fuzzer tests Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Prevent panics Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * docs Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clean up old code Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Test all rounding modes of from_rational Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Clean up code Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Revert "Prevent panics" This reverts commit 7e88ac76138a1b590e68b68318505b69efe1e1f6. * fix imports Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * cleanup Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fuzz test multiply_rational Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Fix import Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * fmt Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> * Return None in multiply_rational on zero div Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> --------- Signed-off-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io> Co-authored-by: Oliver Tale-Yazdi <oliver.tale-yazdi@parity.io>
This commit is contained in:
@@ -284,6 +284,54 @@ impl PartialEq for Rational128 {
|
||||
}
|
||||
}
|
||||
|
||||
pub trait MultiplyRational: Sized {
|
||||
fn multiply_rational(self, n: Self, d: Self, r: Rounding) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! impl_rrm {
|
||||
($ulow:ty, $uhi:ty) => {
|
||||
impl MultiplyRational for $ulow {
|
||||
fn multiply_rational(self, n: Self, d: Self, r: Rounding) -> Option<Self> {
|
||||
if d.is_zero() {
|
||||
return None
|
||||
}
|
||||
|
||||
let sn = (self as $uhi) * (n as $uhi);
|
||||
let mut result = sn / (d as $uhi);
|
||||
let remainder = (sn % (d as $uhi)) as $ulow;
|
||||
if match r {
|
||||
Rounding::Up => remainder > 0,
|
||||
// cannot be `(d + 1) / 2` since `d` might be `max_value` and overflow.
|
||||
Rounding::NearestPrefUp => remainder >= d / 2 + d % 2,
|
||||
Rounding::NearestPrefDown => remainder > d / 2,
|
||||
Rounding::Down => false,
|
||||
} {
|
||||
result = match result.checked_add(1) {
|
||||
Some(v) => v,
|
||||
None => return None,
|
||||
};
|
||||
}
|
||||
if result > (<$ulow>::max_value() as $uhi) {
|
||||
None
|
||||
} else {
|
||||
Some(result as $ulow)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_rrm!(u8, u16);
|
||||
impl_rrm!(u16, u32);
|
||||
impl_rrm!(u32, u64);
|
||||
impl_rrm!(u64, u128);
|
||||
|
||||
impl MultiplyRational for u128 {
|
||||
fn multiply_rational(self, n: Self, d: Self, r: Rounding) -> Option<Self> {
|
||||
crate::helpers_128bit::multiply_by_rational_with_rounding(self, n, d, r)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{helpers_128bit::*, *};
|
||||
|
||||
Reference in New Issue
Block a user