mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 15:47:58 +00:00
optimize biguint div closure (#7754)
* optimize biguint div closure * optimize biguint sub and fix note * change and add biguint split test * add biguint div_unit test * update biguint sub v to v1 * add biguint shift_check
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@@ -212,9 +212,9 @@ impl BigUint {
|
||||
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;
|
||||
if let Some(v1) = u.checked_sub(v) {
|
||||
if let Some(v2) = v1.checked_sub(k) {
|
||||
t = v2;
|
||||
k = 0;
|
||||
} else {
|
||||
needs_borrow = true;
|
||||
@@ -228,9 +228,9 @@ impl BigUint {
|
||||
}
|
||||
t
|
||||
};
|
||||
// PROOF: t either comes from `v2 % B`, or from `u + B - v - k`. The former is
|
||||
// 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`.
|
||||
// `u - v - k` part has been negative, hence `u + B - v - k < B`.
|
||||
w.set(j, s as Single);
|
||||
}
|
||||
|
||||
@@ -287,9 +287,9 @@ impl BigUint {
|
||||
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 };
|
||||
let with_r = |x: Single, r: Single| { Double::from(r) * B + Double::from(x) };
|
||||
for d in (0..n).rev() {
|
||||
let (q, rr) = div_single(with_r(self.get(d).into(), r), other) ;
|
||||
let (q, rr) = div_single(with_r(self.get(d), r), other) ;
|
||||
out.set(d, q as Single);
|
||||
r = rr;
|
||||
}
|
||||
@@ -580,14 +580,25 @@ 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;
|
||||
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!(num, 0x_0001_0000_0001_0000);
|
||||
assert_eq!(split(num), (1 << a, 1 << a));
|
||||
|
||||
let a = SHIFT / 2 + 4;
|
||||
let b = SHIFT / 2 - 4;
|
||||
let num: Double = 1 << (SHIFT + a) | 1 << b;
|
||||
assert_eq!(num, 0x_0010_0000_0000_1000);
|
||||
assert_eq!(split(num), (1 << a, 1 << b));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -734,6 +745,7 @@ pub mod tests {
|
||||
fn div_unit_works() {
|
||||
let a = BigUint { digits: vec![100] };
|
||||
let b = BigUint { digits: vec![1, 100] };
|
||||
let c = BigUint { digits: vec![14, 28, 100] };
|
||||
|
||||
assert_eq!(a.clone().div_unit(1), a);
|
||||
assert_eq!(a.clone().div_unit(0), a);
|
||||
@@ -745,5 +757,9 @@ pub mod tests {
|
||||
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));
|
||||
|
||||
assert_eq!(c.clone().div_unit(1), c);
|
||||
assert_eq!(c.clone().div_unit(0), c);
|
||||
assert_eq!(c.clone().div_unit(2), BigUint { digits: vec![7, 14, 50] });
|
||||
assert_eq!(c.clone().div_unit(7), BigUint { digits: vec![2, 4, 14] });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user