Skip to content

Commit

Permalink
More efficient fixed-base MSM
Browse files Browse the repository at this point in the history
Parallelize table generation, and used mixed addition to speed up MSM.
  • Loading branch information
Pratyush committed Oct 26, 2020
1 parent a511cad commit 5ff4ec5
Showing 1 changed file with 23 additions and 13 deletions.
36 changes: 23 additions & 13 deletions ec/src/msm/fixed_base.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use crate::ProjectiveCurve;
use crate::{AffineCurve, ProjectiveCurve};
use ark_ff::{BigInteger, FpParameters, PrimeField};
use ark_std::vec::Vec;
use ark_std::{cfg_iter, cfg_iter_mut};

#[cfg(feature = "parallel")]
use rayon::prelude::*;
Expand All @@ -16,20 +17,30 @@ impl FixedBaseMSM {
}
}

// TODO: parallelize this by extracting out `g_outer` computation.
pub fn get_window_table<T: ProjectiveCurve>(
scalar_size: usize,
window: usize,
g: T,
) -> Vec<Vec<T>> {
) -> Vec<Vec<T::Affine>> {
let in_window = 1 << window;
let outerc = (scalar_size + window - 1) / window;
let last_in_window = 1 << (scalar_size - (outerc - 1) * window);

let mut multiples_of_g = vec![vec![T::zero(); in_window]; outerc];

let mut g_outer = g;
for (outer, multiples_of_g) in multiples_of_g.iter_mut().enumerate().take(outerc) {
let mut g_outers = Vec::with_capacity(outerc);
for _ in 0..outerc {
g_outers.push(g_outer);
for _ in 0..window {
g_outer.double_in_place();
}
}
for ((outer, multiples_of_g), g_outer) in cfg_iter_mut!(multiples_of_g)
.enumerate()
.take(outerc)
.zip(g_outers)
{
let mut g_inner = T::zero();
let cur_in_window = if outer == outerc - 1 {
last_in_window
Expand All @@ -40,23 +51,22 @@ impl FixedBaseMSM {
*inner = g_inner;
g_inner += &g_outer;
}
for _ in 0..window {
g_outer.double_in_place();
}
}
multiples_of_g
cfg_iter!(multiples_of_g)
.map(|s| T::batch_normalization_into_affine(&s))
.collect()
}

pub fn windowed_mul<T: ProjectiveCurve>(
outerc: usize,
window: usize,
multiples_of_g: &[Vec<T>],
multiples_of_g: &[Vec<T::Affine>],
scalar: &T::ScalarField,
) -> T {
let mut scalar_val = scalar.into_repr().to_bits();
scalar_val.reverse();

let mut res = multiples_of_g[0][0];
let mut res = multiples_of_g[0][0].into_projective();
for outer in 0..outerc {
let mut inner = 0usize;
for i in 0..window {
Expand All @@ -67,21 +77,21 @@ impl FixedBaseMSM {
inner |= 1 << i;
}
}
res += &multiples_of_g[outer][inner];
res.add_assign_mixed(&multiples_of_g[outer][inner]);
}
res
}

pub fn multi_scalar_mul<T: ProjectiveCurve>(
scalar_size: usize,
window: usize,
table: &[Vec<T>],
table: &[Vec<T::Affine>],
v: &[T::ScalarField],
) -> Vec<T> {
let outerc = (scalar_size + window - 1) / window;
assert!(outerc <= table.len());

ark_std::cfg_iter!(v)
cfg_iter!(v)
.map(|e| Self::windowed_mul::<T>(outerc, window, table, e))
.collect::<Vec<_>>()
}
Expand Down

0 comments on commit 5ff4ec5

Please sign in to comment.