mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 11:07:56 +00:00
clean arithmetic and unify names with the new api (#8581)
This commit is contained in:
@@ -33,6 +33,10 @@ 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;
|
||||
|
||||
static_assertions::const_assert!(
|
||||
sp_std::mem::size_of::<Double>() - sp_std::mem::size_of::<Single>() == SHIFT / 8
|
||||
);
|
||||
|
||||
/// 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;
|
||||
@@ -187,6 +191,7 @@ impl BigUint {
|
||||
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;
|
||||
// proof: any number % B will fit into `Single`.
|
||||
w.set(j, (s % B) as Single);
|
||||
k = s / B;
|
||||
}
|
||||
@@ -209,28 +214,24 @@ impl BigUint {
|
||||
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(v1) = u.checked_sub(v) {
|
||||
if let Some(v2) = v1.checked_sub(k) {
|
||||
t = v2;
|
||||
k = 0;
|
||||
} else {
|
||||
needs_borrow = true;
|
||||
}
|
||||
if let Some(v2) = u.checked_sub(v).and_then(|v1| v1.checked_sub(k)) {
|
||||
// no borrow is needed. u - v - k can be computed as-is
|
||||
let t = v2;
|
||||
k = 0;
|
||||
|
||||
t
|
||||
} else {
|
||||
needs_borrow = true;
|
||||
}
|
||||
if needs_borrow {
|
||||
t = u + B - v - k;
|
||||
// borrow is needed. Add a `B` to u, before subtracting.
|
||||
// PROOF: addition: `u + B < 2*B`, thus can fit in double.
|
||||
// PROOF: subtraction: if `u - v - k < 0`, then `u + B - v - k < B`.
|
||||
// NOTE: the order of operations is critical to ensure underflow won't happen.
|
||||
let t = u + B - v - k;
|
||||
k = 1;
|
||||
|
||||
t
|
||||
}
|
||||
t
|
||||
};
|
||||
// PROOF: t either comes from `v2`, 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);
|
||||
}
|
||||
|
||||
@@ -264,10 +265,9 @@ impl BigUint {
|
||||
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;
|
||||
@@ -580,12 +580,6 @@ pub mod tests {
|
||||
BigUint { digits: vec![1; n] }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shift_check() {
|
||||
let shift = sp_std::mem::size_of::<Double>() - sp_std::mem::size_of::<Single>();
|
||||
assert_eq!(shift * 8, SHIFT);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn split_works() {
|
||||
let a = SHIFT / 2;
|
||||
@@ -732,12 +726,14 @@ pub mod tests {
|
||||
let c = BigUint { digits: vec![1, 1, 2] };
|
||||
let d = BigUint { digits: vec![0, 2] };
|
||||
let e = BigUint { digits: vec![0, 1, 1, 2] };
|
||||
let f = BigUint { digits: vec![7, 8] };
|
||||
|
||||
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!(f.clone().div(&b, true).is_none());
|
||||
assert!(c.clone().div(&b, true).is_some());
|
||||
}
|
||||
|
||||
|
||||
@@ -381,7 +381,7 @@ macro_rules! implement_fixed {
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "std", test))]
|
||||
pub fn to_fraction(self) -> f64 {
|
||||
pub fn to_float(self) -> f64 {
|
||||
self.0 as f64 / <Self as FixedPointNumber>::DIV as f64
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user