From 5aff202d8dc06e0ba22aab5e16121e4eb1194af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 00:30:31 +0200 Subject: [PATCH 1/6] Reduce the number subtractions by half --- fastcrypto-tbls/src/polynomial.rs | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index 710bbc815c..30745855f1 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -107,11 +107,29 @@ impl Poly { .iter() .fold(C::ScalarType::generator(), |acc, i| acc * i); let mut coeffs = Vec::new(); - for i in &indices { - let denominator = indices - .iter() - .filter(|j| *j != i) - .fold(*i, |acc, j| acc * (*j - i)); + + // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[i]. + let mut deltas: Vec::ScalarType>> = Vec::new(); + for (index, i) in indices.iter().enumerate() { + // Compute product with cached deltas + let mut denominator = (0..index) + .map(|j| deltas[j].pop().unwrap()) + .fold(*i, |acc, j| acc * j); + + // Adjust sign since the cached values are negations of the factors we need. + if index % 2 == 1 { + denominator = -denominator; + } + + // Compute remaining deltas + let mut new_deltas = Vec::new(); + for j in indices[index + 1..].iter().rev() { + let delta = *j - i; + denominator = denominator * delta; + new_deltas.push(delta); + } + deltas.push(new_deltas); + let coeff = full_numerator / denominator; coeffs.push(coeff.expect("safe since i != j")); } From f887b0f81b052dc6c4200a5552157f2bc9661019 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 01:00:44 +0200 Subject: [PATCH 2/6] Simplify --- fastcrypto-tbls/src/polynomial.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index 30745855f1..92e8dfabbb 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -108,22 +108,22 @@ impl Poly { .fold(C::ScalarType::generator(), |acc, i| acc * i); let mut coeffs = Vec::new(); - // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[i]. + // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[i + j] let mut deltas: Vec::ScalarType>> = Vec::new(); - for (index, i) in indices.iter().enumerate() { + for (i_idx, i) in indices.iter().enumerate() { // Compute product with cached deltas - let mut denominator = (0..index) - .map(|j| deltas[j].pop().unwrap()) + let mut denominator = (0..i_idx) + .map(|j_idx| deltas[j_idx][i_idx - j_idx - 1]) .fold(*i, |acc, j| acc * j); // Adjust sign since the cached values are negations of the factors we need. - if index % 2 == 1 { + if i_idx % 2 == 1 { denominator = -denominator; } // Compute remaining deltas let mut new_deltas = Vec::new(); - for j in indices[index + 1..].iter().rev() { + for j in &indices[i_idx + 1..] { let delta = *j - i; denominator = denominator * delta; new_deltas.push(delta); From ae77625a2164962379262742a8206144e388f511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 01:07:56 +0200 Subject: [PATCH 3/6] Reduce cache size --- fastcrypto-tbls/src/polynomial.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index 92e8dfabbb..e5a51f6f0b 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -113,7 +113,11 @@ impl Poly { for (i_idx, i) in indices.iter().enumerate() { // Compute product with cached deltas let mut denominator = (0..i_idx) - .map(|j_idx| deltas[j_idx][i_idx - j_idx - 1]) + .map(|j_idx| { + deltas[j_idx] + .pop() + .expect("deltas[k] is popped k-1 times and contains exactly k-1 elements") + }) .fold(*i, |acc, j| acc * j); // Adjust sign since the cached values are negations of the factors we need. @@ -123,7 +127,7 @@ impl Poly { // Compute remaining deltas let mut new_deltas = Vec::new(); - for j in &indices[i_idx + 1..] { + for j in indices[i_idx + 1..].iter().rev() { let delta = *j - i; denominator = denominator * delta; new_deltas.push(delta); From 3a3dcc1652fe30b82617b7377888925488257c8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 01:10:30 +0200 Subject: [PATCH 4/6] Fix comment --- fastcrypto-tbls/src/polynomial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index e5a51f6f0b..721fe004ef 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -108,7 +108,7 @@ impl Poly { .fold(C::ScalarType::generator(), |acc, i| acc * i); let mut coeffs = Vec::new(); - // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[i + j] + // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[n - 1 - i] let mut deltas: Vec::ScalarType>> = Vec::new(); for (i_idx, i) in indices.iter().enumerate() { // Compute product with cached deltas From d683e6e47a8295c920cc09fb338079345c7471a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 01:32:50 +0200 Subject: [PATCH 5/6] Fix variable name --- fastcrypto-tbls/src/polynomial.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index 721fe004ef..f943525e1f 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -109,12 +109,13 @@ impl Poly { let mut coeffs = Vec::new(); // Keep track of differences that are already computed: deltas[i][j] = indices[j] - indices[n - 1 - i] - let mut deltas: Vec::ScalarType>> = Vec::new(); + let n = indices.len(); + let mut deltas: Vec::ScalarType>> = vec![Vec::new(); n]; for (i_idx, i) in indices.iter().enumerate() { // Compute product with cached deltas let mut denominator = (0..i_idx) - .map(|j_idx| { - deltas[j_idx] + .map(|k| { + deltas[k] .pop() .expect("deltas[k] is popped k-1 times and contains exactly k-1 elements") }) @@ -126,13 +127,11 @@ impl Poly { } // Compute remaining deltas - let mut new_deltas = Vec::new(); for j in indices[i_idx + 1..].iter().rev() { let delta = *j - i; denominator = denominator * delta; - new_deltas.push(delta); + deltas[i_idx].push(delta); } - deltas.push(new_deltas); let coeff = full_numerator / denominator; coeffs.push(coeff.expect("safe since i != j")); From 8010cbb3800f377305b5d289e75d7ab374359058 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Lindstr=C3=B8m?= Date: Sun, 1 Oct 2023 01:33:32 +0200 Subject: [PATCH 6/6] Fix variable name --- fastcrypto-tbls/src/polynomial.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fastcrypto-tbls/src/polynomial.rs b/fastcrypto-tbls/src/polynomial.rs index f943525e1f..7f21fe7e7a 100644 --- a/fastcrypto-tbls/src/polynomial.rs +++ b/fastcrypto-tbls/src/polynomial.rs @@ -119,7 +119,7 @@ impl Poly { .pop() .expect("deltas[k] is popped k-1 times and contains exactly k-1 elements") }) - .fold(*i, |acc, j| acc * j); + .fold(*i, |acc, delta| acc * delta); // Adjust sign since the cached values are negations of the factors we need. if i_idx % 2 == 1 {