Batch multiplicative inverse optimizations (#210)

* Batch multiplicative inverse optimizations

* Minor style (Daniel PR comment)
This commit is contained in:
Jakub Nabaglo 2021-08-31 15:08:39 -07:00 committed by GitHub
parent d51bb98dcc
commit 1727d2c872
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 26 additions and 18 deletions

View File

@ -190,8 +190,9 @@ impl Field for CrandallField {
let mut c = 0u64;
while u != 1 && v != 1 {
while u.is_even() {
u /= 2;
let u_tz = u.trailing_zeros();
u >>= u_tz;
for _ in 0..u_tz {
if b.is_even() {
b /= 2;
} else {
@ -200,8 +201,9 @@ impl Field for CrandallField {
}
}
while v.is_even() {
v /= 2;
let v_tz = v.trailing_zeros();
v >>= v_tz;
for _ in 0..v_tz {
if c.is_even() {
c /= 2;
} else {

View File

@ -90,25 +90,31 @@ pub trait Field:
if n == 0 {
return Vec::new();
}
if n == 1 {
return vec![x[0].inverse()];
}
let mut a = Vec::with_capacity(n);
a.push(x[0]);
// Fill buf with cumulative product of x.
let mut buf = Vec::with_capacity(n);
let mut cumul_prod = x[0];
buf.push(cumul_prod);
for i in 1..n {
a.push(a[i - 1] * x[i]);
cumul_prod *= x[i];
buf.push(cumul_prod);
}
let mut a_inv = vec![Self::ZERO; n];
a_inv[n - 1] = a[n - 1].try_inverse().expect("No inverse");
for i in (0..n - 1).rev() {
a_inv[i] = x[i + 1] * a_inv[i + 1];
// At this stage buf contains the the cumulative product of x. We reuse the buffer for
// efficiency. At the end of the loop, it is filled with inverses of x.
let mut a_inv = cumul_prod.inverse();
buf[n - 1] = buf[n - 2] * a_inv;
for i in (1..n - 1).rev() {
a_inv = x[i + 1] * a_inv;
// buf[i - 1] has not been written to by this loop, so it equals x[0] * ... x[n - 1].
buf[i] = buf[i - 1] * a_inv;
// buf[i] now holds the inverse of x[i].
}
let mut x_inv = Vec::with_capacity(n);
x_inv.push(a_inv[0]);
for i in 1..n {
x_inv.push(a[i - 1] * a_inv[i]);
}
x_inv
buf[0] = x[1] * a_inv;
buf
}
/// Compute the inverse of 2^exp in this field.