use crate::{Digit, WnafGroup, le_repr, wnaf_form, wnaf_multi_exp, wnaf_table};
use alloc::vec::Vec;
use ff::PrimeField;
use group::Group;
#[cfg(doc)]
use crate::{WnafBase, WnafScalar};
#[derive(Debug)]
pub struct BoxedWnaf<W, B, S> {
base: B,
scalar: S,
window_size: W,
}
impl<G: Group> Default for BoxedWnaf<(), Vec<G>, Vec<Digit>> {
fn default() -> Self {
Self::new()
}
}
impl<G: Group> BoxedWnaf<(), Vec<G>, Vec<Digit>> {
#[must_use]
pub fn new() -> Self {
BoxedWnaf {
base: vec![],
scalar: vec![],
window_size: (),
}
}
}
impl<G: WnafGroup> BoxedWnaf<(), Vec<G>, Vec<Digit>> {
pub fn base(
&mut self,
base: &G,
num_scalars: usize,
) -> BoxedWnaf<usize, &[G], &mut Vec<Digit>> {
let window_size = G::recommended_wnaf_for_num_scalars(num_scalars);
self.base.resize_with(1 << (window_size - 2), G::identity);
wnaf_table(&mut self.base, base, window_size);
BoxedWnaf {
base: &self.base[..],
scalar: &mut self.scalar,
window_size,
}
}
pub fn scalar(&mut self, scalar: &G::Scalar) -> BoxedWnaf<usize, &mut Vec<G>, &[Digit]> {
let window_size = 4;
let repr = le_repr(scalar);
let bit_len = init_storage::<G::Scalar>(&mut self.scalar, repr);
let digits = wnaf_form(&mut self.scalar, repr, bit_len, window_size);
self.scalar.truncate(digits);
BoxedWnaf {
base: &mut self.base,
scalar: &self.scalar[..],
window_size,
}
}
}
impl<'a, G: Group> BoxedWnaf<usize, &'a [G], &'a mut Vec<Digit>> {
#[must_use]
pub fn shared(&self) -> BoxedWnaf<usize, &'a [G], Vec<Digit>> {
BoxedWnaf {
base: self.base,
scalar: vec![],
window_size: self.window_size,
}
}
}
impl<'a, G: Group> BoxedWnaf<usize, &'a mut Vec<G>, &'a [Digit]> {
#[must_use]
pub fn shared(&self) -> BoxedWnaf<usize, Vec<G>, &'a [Digit]> {
BoxedWnaf {
base: vec![],
scalar: self.scalar,
window_size: self.window_size,
}
}
}
impl<B, S: AsRef<[Digit]>> BoxedWnaf<usize, B, S> {
pub fn base<G: Group>(&mut self, base: &G) -> G
where
B: AsMut<Vec<G>>,
{
self.base
.as_mut()
.resize_with(1 << (self.window_size - 2), G::identity);
wnaf_table(self.base.as_mut(), base, self.window_size);
wnaf_exp(self.base.as_mut(), self.scalar.as_ref())
}
}
impl<B, S: AsMut<Vec<Digit>>> BoxedWnaf<usize, B, S> {
pub fn scalar<G: Group>(&mut self, scalar: &G::Scalar) -> G
where
B: AsRef<[G]>,
{
let repr = le_repr(scalar);
let bit_len = init_storage::<G::Scalar>(self.scalar.as_mut(), repr);
let digits = wnaf_form(self.scalar.as_mut(), repr, bit_len, self.window_size);
self.scalar.as_mut().truncate(digits);
wnaf_exp(self.base.as_ref(), self.scalar.as_mut())
}
}
#[inline]
fn init_storage<F: PrimeField>(digits: &mut Vec<Digit>, repr: F::Repr) -> usize {
let bit_len = (repr.as_ref().len() * 8).min(F::NUM_BITS as usize);
digits.resize(bit_len + 1, 0);
bit_len
}
#[inline]
fn wnaf_exp<G: Group>(table: &[G], wnaf: &[Digit]) -> G {
wnaf_multi_exp(core::iter::once((table, wnaf, wnaf.len())))
}