use crate::ProjectiveCurve;
use ark_ff::{BigInteger, PrimeField};
use ark_std::vec::Vec;
pub struct WnafContext {
pub window_size: usize,
}
impl WnafContext {
pub fn new(window_size: usize) -> Self {
assert!(window_size >= 2);
assert!(window_size < 64);
Self { window_size }
}
pub fn table<G: ProjectiveCurve>(&self, mut base: G) -> Vec<G> {
let mut table = Vec::with_capacity(1 << (self.window_size - 1));
let dbl = base.double();
for _ in 0..(1 << (self.window_size - 1)) {
table.push(base);
base += &dbl;
}
table
}
pub fn mul<G: ProjectiveCurve>(&self, g: G, scalar: &G::ScalarField) -> G {
let table = self.table(g);
self.mul_with_table(&table, scalar).unwrap()
}
pub fn mul_with_table<G: ProjectiveCurve>(
&self,
base_table: &[G],
scalar: &G::ScalarField,
) -> Option<G> {
if 1 << (self.window_size - 1) > base_table.len() {
return None;
}
let scalar_wnaf = scalar.into_repr().find_wnaf(self.window_size).unwrap();
let mut result = G::zero();
let mut found_non_zero = false;
for n in scalar_wnaf.iter().rev() {
if found_non_zero {
result.double_in_place();
}
if *n != 0 {
found_non_zero = true;
if *n > 0 {
result += &base_table[(n / 2) as usize];
} else {
result -= &base_table[((-n) / 2) as usize];
}
}
}
Some(result)
}
}