ark_ec/scalar_mul/variable_base/
stream_pippenger.rsuse ark_ff::{PrimeField, Zero};
use ark_std::{borrow::Borrow, vec::*};
use hashbrown::HashMap;
use super::{DefaultHasher, VariableBaseMSM};
pub struct ChunkedPippenger<G: VariableBaseMSM> {
scalars_buffer: Vec<<G::ScalarField as PrimeField>::BigInt>,
bases_buffer: Vec<G::MulBase>,
result: G,
buf_size: usize,
}
impl<G: VariableBaseMSM> ChunkedPippenger<G> {
pub fn new(max_msm_buffer: usize) -> Self {
Self {
scalars_buffer: Vec::with_capacity(max_msm_buffer),
bases_buffer: Vec::with_capacity(max_msm_buffer),
result: G::zero(),
buf_size: max_msm_buffer,
}
}
pub fn with_size(buf_size: usize) -> Self {
Self {
scalars_buffer: Vec::with_capacity(buf_size),
bases_buffer: Vec::with_capacity(buf_size),
result: G::zero(),
buf_size,
}
}
#[inline(always)]
pub fn add<B, S>(&mut self, base: B, scalar: S)
where
B: Borrow<G::MulBase>,
S: Borrow<<G::ScalarField as PrimeField>::BigInt>,
{
self.scalars_buffer.push(*scalar.borrow());
self.bases_buffer.push(*base.borrow());
if self.scalars_buffer.len() == self.buf_size {
self.result.add_assign(G::msm_bigint(
self.bases_buffer.as_slice(),
self.scalars_buffer.as_slice(),
));
self.scalars_buffer.clear();
self.bases_buffer.clear();
}
}
#[inline(always)]
pub fn finalize(mut self) -> G {
if !self.scalars_buffer.is_empty() {
self.result +=
G::msm_bigint(self.bases_buffer.as_slice(), self.scalars_buffer.as_slice());
}
self.result
}
}
pub struct HashMapPippenger<G: VariableBaseMSM> {
buffer: HashMap<G::MulBase, G::ScalarField, core::hash::BuildHasherDefault<DefaultHasher>>,
result: G,
buf_size: usize,
}
impl<G: VariableBaseMSM> HashMapPippenger<G> {
pub fn new(max_msm_buffer: usize) -> Self {
Self {
buffer: HashMap::with_capacity_and_hasher(
max_msm_buffer,
core::hash::BuildHasherDefault::<DefaultHasher>::default(),
),
result: G::zero(),
buf_size: max_msm_buffer,
}
}
#[inline(always)]
pub fn add<B, S>(&mut self, base: B, scalar: S)
where
B: Borrow<G::MulBase>,
S: Borrow<G::ScalarField>,
{
let entry = self
.buffer
.entry(*base.borrow())
.or_insert(G::ScalarField::zero());
*entry += *scalar.borrow();
if self.buffer.len() == self.buf_size {
let bases = self.buffer.keys().cloned().collect::<Vec<_>>();
let scalars = self
.buffer
.values()
.map(|s| s.into_bigint())
.collect::<Vec<_>>();
self.result += G::msm_bigint(&bases, &scalars);
self.buffer.clear();
}
}
#[inline(always)]
pub fn finalize(mut self) -> G {
if !self.buffer.is_empty() {
let bases = self.buffer.keys().cloned().collect::<Vec<_>>();
let scalars = self
.buffer
.values()
.map(|s| s.into_bigint())
.collect::<Vec<_>>();
self.result += G::msm_bigint(&bases, &scalars);
}
self.result
}
}