use crate::{WindowSize, WnafScalar, WnafSize, wnaf_multi_exp, wnaf_table};
use array::Array;
use core::iter;
use core::ops::Mul;
use group::Group;
#[derive(Clone, Debug)]
pub struct WnafBase<G: Group, W: WindowSize> {
table: Array<G, W::TableSize>,
}
impl<G: Group, W: WindowSize> WnafBase<G, W> {
#[inline]
pub fn new(base: &G) -> Self {
let mut ret = Self::default();
ret.init_from_base(base);
ret
}
#[inline]
pub fn init_from_base(&mut self, base: &G) {
wnaf_table(&mut self.table, base, W::USIZE);
}
#[must_use]
pub fn multiscalar_mul<'a, I>(pairs: I) -> G
where
G::Scalar: WnafSize,
I: Clone + Iterator<Item = (&'a Self, &'a WnafScalar<G::Scalar, W>)>,
{
wnaf_multi_exp(pairs.map(|(b, s)| (b.table.as_slice(), s.wnaf.as_slice(), s.digits)))
}
}
impl<G: Group, W: WindowSize> Default for WnafBase<G, W> {
fn default() -> Self {
Self {
table: Array::from_fn(|_| G::generator()),
}
}
}
impl<G, W> Mul<&WnafScalar<G::Scalar, W>> for &WnafBase<G, W>
where
G: Group<Scalar: WnafSize>,
W: WindowSize,
{
type Output = G;
fn mul(self, rhs: &WnafScalar<G::Scalar, W>) -> Self::Output {
WnafBase::multiscalar_mul(iter::once((self, rhs)))
}
}
impl<G, W> Mul<&WnafScalar<G::Scalar, W>> for WnafBase<G, W>
where
G: Group<Scalar: WnafSize>,
W: WindowSize,
{
type Output = G;
#[inline]
fn mul(self, rhs: &WnafScalar<G::Scalar, W>) -> Self::Output {
&self * rhs
}
}
impl<G, W> Mul<WnafScalar<G::Scalar, W>> for WnafBase<G, W>
where
G: Group<Scalar: WnafSize>,
W: WindowSize,
{
type Output = G;
#[inline]
fn mul(self, rhs: WnafScalar<G::Scalar, W>) -> Self::Output {
&self * &rhs
}
}