Skip to content

Commit

Permalink
optimize biguint div closure (paritytech#7754)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
honeywest authored and darkfriend77 committed Jan 11, 2021
1 parent a49f0f0 commit 87d7752
Showing 1 changed file with 26 additions and 10 deletions.
36 changes: 26 additions & 10 deletions primitives/arithmetic/src/biguint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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);
Expand All @@ -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] });
}
}

0 comments on commit 87d7752

Please sign in to comment.