pub fn msm_internal<G, F, I, J>(
    bases: J,
    scalars: I,
    n: usize,
    max_msm_buffer_log: usize,
) -> G::Projective
where
    G: AffineCurve,
    I: IntoIterator,
    F: PrimeField,
    I::Item: Borrow<F>,
    J: IntoIterator,
    J::Item: Borrow<G>,
{
    let c = bounded_ln_without_floats(n, max_msm_buffer_log);
    let num_bits = <G::ScalarField as PrimeField>::MODULUS_BIT_SIZE as usize;
    // split `num_bits` into steps of `c`, but skip window 0.
    let windows = (0..num_bits).step_by(c);
    let buckets_num = 1 << c;

    let mut window_buckets = Vec::with_capacity(windows.len());
    for window in windows {
        window_buckets.push((window, vec![G::Projective::zero(); buckets_num]));
    }

    for (scalar, base) in scalars.into_iter().zip(bases) {
        for (w, bucket) in window_buckets.iter_mut() {
            let mut scalar = scalar.borrow().into_bigint();
            // We right-shift by `w`, thus getting rid of the lower bits.
            scalar.divn(*w as u32);
            // We mod the remaining bits by 2^{window size}, thus taking `c` bits.
            let scalar = scalar.as_ref()[0] % (1 << c);
            // If the scalar is non-zero, we update the corresponding bucket.
            // (Recall that `buckets` doesn't have a zero bucket.)
            if scalar != 0 {
                bucket[(scalar - 1) as usize].add_assign_mixed(base.borrow());
            }
        }
    }

    let mut window_sums = window_buckets.iter().rev().map(|(_w, bucket)| {
        // `running_sum` = sum_{j in i..num_buckets} bucket[j],
        // where we iterate backward from i = num_buckets to 0.
        let mut bucket_sum = G::Projective::zero();
        let mut bucket_running_sum = G::Projective::zero();
        bucket.iter().rev().for_each(|b| {
            bucket_running_sum += b;
            bucket_sum += &bucket_running_sum;
        });
        bucket_sum
    });

    // We're traversing windows from high to low.
    let first = window_sums.next().unwrap();
    window_sums.fold(first, |mut total, sum_i| {
        for _ in 0..c {
            total.double_in_place();
        }
        total + sum_i
    })
}
/// Add a chunk of bases and scalars into the multiscalar multiplication state.
/// XXX. Rust sometimes gets confused if I use G::ScalarField instead of F, so despite it's not really necessary I'm keeping the scalar field as a type parameter.
Add a chunk of bases and scalars into the multiscalar multiplication state.
XXX. Rust sometimes gets confused if I use G::ScalarField instead of F, so despite it's not really necessary I'm keeping the scalar field as a type parameter.
Add a chunk of bases and scalars into the multiscalar multiplication state . XXX . Rust sometimes gets confused if I use G :: ScalarField instead of F so despite it ' s not really necessary I ' m keeping the scalar field as a type parameter .
pub fn msm_internal<G, F, I, J>(
    bases: J,
    scalars: I,
    n: usize,
    max_msm_buffer_log: usize,
) -> G::Projective
where
    G: AffineCurve,
    I: IntoIterator,
    F: PrimeField,
    I::Item: Borrow<F>,
    J: IntoIterator,
    J::Item: Borrow<G>,
{
    let c = bounded_ln_without_floats(n, max_msm_buffer_log);
    let num_bits = <G::ScalarField as PrimeField>::MODULUS_BIT_SIZE as usize;
    // split `num_bits` into steps of `c`, but skip window 0.
    let windows = (0..num_bits).step_by(c);
    let buckets_num = 1 << c;
    let mut window_buckets = Vec::with_capacity(windows.len());
    for window in windows {
        window_buckets.push((window, vec![G::Projective::zero(); buckets_num]));
    }
    for (scalar, base) in scalars.into_iter().zip(bases) {
        for (w, bucket) in window_buckets.iter_mut() {
            let mut scalar = scalar.borrow().into_bigint();
            // We right-shift by `w`, thus getting rid of the lower bits.
            scalar.divn(*w as u32);
            // We mod the remaining bits by 2^{window size}, thus taking `c` bits.
            let scalar = scalar.as_ref()[0] % (1 << c);
            // If the scalar is non-zero, we update the corresponding bucket.
            // (Recall that `buckets` doesn't have a zero bucket.)
            if scalar != 0 {
                bucket[(scalar - 1) as usize].add_assign_mixed(base.borrow());
            }
        }
    }
    let mut window_sums = window_buckets.iter().rev().map(|(_w, bucket)| {
        // `running_sum` = sum_{j in i..num_buckets} bucket[j],
        // where we iterate backward from i = num_buckets to 0.
        let mut bucket_sum = G::Projective::zero();
        let mut bucket_running_sum = G::Projective::zero();
        bucket.iter().rev().for_each(|b| {
            bucket_running_sum += b;
            bucket_sum += &bucket_running_sum;
        });
        bucket_sum
    });
    // We're traversing windows from high to low.
    let first = window_sums.next().unwrap();
    window_sums.fold(first, |mut total, sum_i| {
        for _ in 0..c {
            total.double_in_place();
        }
        total + sum_i
    })
}
pub fn msm_internal < G , F , I , J > ( bases : J , scalars : I , n : usize , max_msm_buffer_log : usize , ) -> G :: Projective where G : AffineCurve , I : IntoIterator , F : PrimeField , I :: Item : Borrow < F > , J : IntoIterator , J :: Item : Borrow < G > , { let c = bounded_ln_without_floats ( n , max_msm_buffer_log ) ; let num_bits = < G :: ScalarField as PrimeField > :: MODULUS_BIT_SIZE as usize ; // split `num_bits` into steps of `c`, but skip window 0. let windows = ( 0 .. num_bits ) . step_by ( c ) ; let buckets_num = 1 << c ; let mut window_buckets = Vec :: with_capacity ( windows . len ( ) ) ; for window in windows { window_buckets . push ( ( window , vec ! [ G Projective zero ( ) buckets_num ] ) ) ; } for ( scalar , base ) in scalars . into_iter ( ) . zip ( bases ) { for ( w , bucket ) in window_buckets . iter_mut ( ) { let mut scalar = scalar . borrow ( ) . into_bigint ( ) ; // We right-shift by `w`, thus getting rid of the lower bits. scalar . divn ( * w as u32 ) ; // We mod the remaining bits by 2^{window size}, thus taking `c` bits. let scalar = scalar . as_ref ( ) [ 0 ] % ( 1 << c ) ; // If the scalar is non-zero, we update the corresponding bucket. // (Recall that `buckets` doesn't have a zero bucket.) if scalar != 0 { bucket [ ( scalar - 1 ) as usize ] . add_assign_mixed ( base . borrow ( ) ) ; } } } let mut window_sums = window_buckets . iter ( ) . rev ( ) . map ( | ( _w , bucket ) | { // `running_sum` = sum_{j in i..num_buckets} bucket[j], // where we iterate backward from i = num_buckets to 0. let mut bucket_sum = G :: Projective :: zero ( ) ; let mut bucket_running_sum = G :: Projective :: zero ( ) ; bucket . iter ( ) . rev ( ) . for_each ( | b | { bucket_running_sum += b ; bucket_sum += & bucket_running_sum ; } ) ; bucket_sum } ) ; // We're traversing windows from high to low. let first = window_sums . next ( ) . unwrap ( ) ; window_sums . fold ( first , | mut total , sum_i | { for _ in 0 .. c { total . double_in_place ( ) ; } total + sum_i } ) }
Add a chunk of bases and scalars into the multiscalar multiplication state.
Add a chunk of bases and scalars into the multiscalar multiplication state .
bases
J
scalars
I
n
usize
max_msm_buffer_log
usize