use crate::{WnafScalar, wnaf_exp, wnaf_multi_exp, wnaf_table};
use alloc::vec::Vec;
use core::ops::Mul;
use group::Group;
#[derive(Clone, Debug)]
pub struct WnafBase<G: Group, const WINDOW_SIZE: usize> {
table: Vec<G>,
}
impl<G: Group, const WINDOW_SIZE: usize> WnafBase<G, WINDOW_SIZE> {
pub fn new(base: G) -> Self {
let mut table = vec![];
wnaf_table(&mut table, base, WINDOW_SIZE);
WnafBase { table }
}
pub fn multiscalar_mul<I, J>(scalars: I, bases: J) -> G
where
I: IntoIterator<Item = WnafScalar<G::Scalar, WINDOW_SIZE>>,
J: IntoIterator<Item = Self>,
{
let wnafs = scalars.into_iter().map(|s| s.wnaf).collect::<Vec<_>>();
let tables = bases.into_iter().map(|b| b.table).collect::<Vec<_>>();
wnaf_multi_exp(tables.as_slice(), wnafs.as_slice())
}
#[must_use]
pub fn multiscalar_mul_array<const N: usize>(
scalars: &[WnafScalar<G::Scalar, WINDOW_SIZE>; N],
bases: &[Self; N],
) -> G {
let wnafs = scalars.each_ref().map(|s| s.wnaf.as_slice());
let tables = bases.each_ref().map(|b| b.table.as_slice());
wnaf_multi_exp(&tables, &wnafs)
}
}
impl<G: Group, const WINDOW_SIZE: usize> Mul<&WnafScalar<G::Scalar, WINDOW_SIZE>>
for &WnafBase<G, WINDOW_SIZE>
{
type Output = G;
fn mul(self, rhs: &WnafScalar<G::Scalar, WINDOW_SIZE>) -> Self::Output {
wnaf_exp(&self.table, &rhs.wnaf)
}
}