1use super::{CurveProjective, PrimeField, PrimeFieldRepr};
2
3pub(crate) fn wnaf_table<G: CurveProjective>(table: &mut Vec<G>, mut base: G, window: usize) {
5 table.truncate(0);
6 table.reserve(1 << (window - 1));
7
8 let mut dbl = base;
9 dbl.double();
10
11 for _ in 0..(1 << (window - 1)) {
12 table.push(base);
13 base.add_assign(&dbl);
14 }
15}
16
17pub(crate) fn wnaf_form<S: PrimeFieldRepr>(wnaf: &mut Vec<i64>, mut c: S, window: usize) {
19 wnaf.truncate(0);
20
21 while !c.is_zero() {
22 let mut u;
23 if c.is_odd() {
24 u = (c.as_ref()[0] % (1 << (window + 1))) as i64;
25
26 if u > (1 << window) {
27 u -= 1 << (window + 1);
28 }
29
30 if u > 0 {
31 c.sub_noborrow(&S::from(u as u64));
32 } else {
33 c.add_nocarry(&S::from((-u) as u64));
34 }
35 } else {
36 u = 0;
37 }
38
39 wnaf.push(u);
40
41 c.div2();
42 }
43}
44
45pub(crate) fn wnaf_exp<G: CurveProjective>(table: &[G], wnaf: &[i64]) -> G {
50 let mut result = G::zero();
51
52 let mut found_one = false;
53
54 for n in wnaf.iter().rev() {
55 if found_one {
56 result.double();
57 }
58
59 if *n != 0 {
60 found_one = true;
61
62 if *n > 0 {
63 result.add_assign(&table[(n / 2) as usize]);
64 } else {
65 result.sub_assign(&table[((-n) / 2) as usize]);
66 }
67 }
68 }
69
70 result
71}
72
73#[derive(Debug)]
75pub struct Wnaf<W, B, S> {
76 base: B,
77 scalar: S,
78 window_size: W,
79}
80
81impl<G: CurveProjective> Wnaf<(), Vec<G>, Vec<i64>> {
82 pub fn new() -> Self {
84 Wnaf {
85 base: vec![],
86 scalar: vec![],
87 window_size: (),
88 }
89 }
90
91 pub fn base(&mut self, base: G, num_scalars: usize) -> Wnaf<usize, &[G], &mut Vec<i64>> {
94 let window_size = G::recommended_wnaf_for_num_scalars(num_scalars);
96
97 wnaf_table(&mut self.base, base, window_size);
99
100 Wnaf {
103 base: &self.base[..],
104 scalar: &mut self.scalar,
105 window_size,
106 }
107 }
108
109 pub fn scalar(
112 &mut self,
113 scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
114 ) -> Wnaf<usize, &mut Vec<G>, &[i64]> {
115 let window_size = G::recommended_wnaf_for_scalar(scalar);
117
118 wnaf_form(&mut self.scalar, scalar, window_size);
120
121 Wnaf {
124 base: &mut self.base,
125 scalar: &self.scalar[..],
126 window_size,
127 }
128 }
129}
130
131impl<'a, G: CurveProjective> Wnaf<usize, &'a [G], &'a mut Vec<i64>> {
132 pub fn shared(&self) -> Wnaf<usize, &'a [G], Vec<i64>> {
135 Wnaf {
136 base: self.base,
137 scalar: vec![],
138 window_size: self.window_size,
139 }
140 }
141}
142
143impl<'a, G: CurveProjective> Wnaf<usize, &'a mut Vec<G>, &'a [i64]> {
144 pub fn shared(&self) -> Wnaf<usize, Vec<G>, &'a [i64]> {
148 Wnaf {
149 base: vec![],
150 scalar: self.scalar,
151 window_size: self.window_size,
152 }
153 }
154}
155
156impl<B, S: AsRef<[i64]>> Wnaf<usize, B, S> {
157 pub fn base<G: CurveProjective>(&mut self, base: G) -> G
159 where
160 B: AsMut<Vec<G>>,
161 {
162 wnaf_table(self.base.as_mut(), base, self.window_size);
163 wnaf_exp(self.base.as_mut(), self.scalar.as_ref())
164 }
165}
166
167impl<B, S: AsMut<Vec<i64>>> Wnaf<usize, B, S> {
168 pub fn scalar<G: CurveProjective>(
170 &mut self,
171 scalar: <<G as CurveProjective>::Scalar as PrimeField>::Repr,
172 ) -> G
173 where
174 B: AsRef<[G]>,
175 {
176 wnaf_form(self.scalar.as_mut(), scalar, self.window_size);
177 wnaf_exp(self.base.as_ref(), self.scalar.as_mut())
178 }
179}