1pub mod glv;
2pub mod wnaf;
3
4pub mod variable_base;
5
6use crate::{
7 short_weierstrass::{Affine, Projective, SWCurveConfig},
8 PrimeGroup,
9};
10use ark_ff::{AdditiveGroup, BigInteger, PrimeField, Zero};
11use ark_std::{
12 cfg_iter, cfg_iter_mut,
13 ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign},
14 vec::*,
15};
16
17#[cfg(feature = "parallel")]
18use rayon::prelude::*;
19
20fn ln_without_floats(a: usize) -> usize {
25 (ark_std::log2(a) * 69 / 100) as usize
27}
28
29#[inline(always)]
31pub fn sw_double_and_add_affine<P: SWCurveConfig>(
32 base: &Affine<P>,
33 scalar: impl AsRef<[u64]>,
34) -> Projective<P> {
35 let mut res = Projective::<P>::zero();
36 for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
37 res.double_in_place();
38 if b {
39 res += base
40 }
41 }
42
43 res
44}
45
46#[inline(always)]
48pub fn sw_double_and_add_projective<P: SWCurveConfig>(
49 base: &Projective<P>,
50 scalar: impl AsRef<[u64]>,
51) -> Projective<P> {
52 let mut res = Projective::<P>::zero();
53 for b in ark_ff::BitIteratorBE::without_leading_zeros(scalar) {
54 res.double_in_place();
55 if b {
56 res += base
57 }
58 }
59
60 res
61}
62
63pub trait ScalarMul:
64 PrimeGroup
65 + Add<Self::MulBase, Output = Self>
66 + AddAssign<Self::MulBase>
67 + for<'a> Add<&'a Self::MulBase, Output = Self>
68 + for<'a> AddAssign<&'a Self::MulBase>
69 + Sub<Self::MulBase, Output = Self>
70 + SubAssign<Self::MulBase>
71 + for<'a> Sub<&'a Self::MulBase, Output = Self>
72 + for<'a> SubAssign<&'a Self::MulBase>
73 + From<Self::MulBase>
74{
75 type MulBase: Send
76 + Sync
77 + Copy
78 + Eq
79 + core::hash::Hash
80 + Mul<Self::ScalarField, Output = Self>
81 + for<'a> Mul<&'a Self::ScalarField, Output = Self>
82 + Neg<Output = Self::MulBase>
83 + From<Self>;
84
85 const NEGATION_IS_CHEAP: bool;
86
87 fn batch_convert_to_mul_base(bases: &[Self]) -> Vec<Self::MulBase>;
88
89 fn batch_mul(self, v: &[Self::ScalarField]) -> Vec<Self::MulBase> {
117 let table = BatchMulPreprocessing::new(self, v.len());
118 Self::batch_mul_with_preprocessing(&table, v)
119 }
120
121 fn batch_mul_with_preprocessing(
155 table: &BatchMulPreprocessing<Self>,
156 v: &[Self::ScalarField],
157 ) -> Vec<Self::MulBase> {
158 table.batch_mul(v)
159 }
160}
161
162pub struct BatchMulPreprocessing<T: ScalarMul> {
167 pub window: usize,
168 pub max_scalar_size: usize,
169 pub table: Vec<Vec<T::MulBase>>,
170}
171
172impl<T: ScalarMul> BatchMulPreprocessing<T> {
173 pub fn new(base: T, num_scalars: usize) -> Self {
174 let scalar_size = T::ScalarField::MODULUS_BIT_SIZE as usize;
175 Self::with_num_scalars_and_scalar_size(base, num_scalars, scalar_size)
176 }
177
178 pub fn with_num_scalars_and_scalar_size(
179 base: T,
180 num_scalars: usize,
181 max_scalar_size: usize,
182 ) -> Self {
183 let window = Self::compute_window_size(num_scalars);
184 let in_window = 1 << window;
185 let outerc = (max_scalar_size + window - 1) / window;
186 let last_in_window = 1 << (max_scalar_size - (outerc - 1) * window);
187
188 let mut multiples_of_g = vec![vec![T::zero(); in_window]; outerc];
189
190 let mut g_outer = base;
191 let mut g_outers = Vec::with_capacity(outerc);
192 for _ in 0..outerc {
193 g_outers.push(g_outer);
194 for _ in 0..window {
195 g_outer.double_in_place();
196 }
197 }
198 cfg_iter_mut!(multiples_of_g)
199 .enumerate()
200 .take(outerc)
201 .zip(g_outers)
202 .for_each(|((outer, multiples_of_g), g_outer)| {
203 let cur_in_window = if outer == outerc - 1 {
204 last_in_window
205 } else {
206 in_window
207 };
208
209 let mut g_inner = T::zero();
210 for inner in multiples_of_g.iter_mut().take(cur_in_window) {
211 *inner = g_inner;
212 g_inner += &g_outer;
213 }
214 });
215 let table = cfg_iter!(multiples_of_g)
216 .map(|s| T::batch_convert_to_mul_base(s))
217 .collect();
218 Self {
219 window,
220 max_scalar_size,
221 table,
222 }
223 }
224
225 pub fn compute_window_size(num_scalars: usize) -> usize {
226 if num_scalars < 32 {
227 3
228 } else {
229 ln_without_floats(num_scalars)
230 }
231 }
232
233 pub fn batch_mul(&self, v: &[T::ScalarField]) -> Vec<T::MulBase> {
234 let result: Vec<_> = cfg_iter!(v).map(|e| self.windowed_mul(e)).collect();
235 T::batch_convert_to_mul_base(&result)
236 }
237
238 fn windowed_mul(&self, scalar: &T::ScalarField) -> T {
239 let outerc = (self.max_scalar_size + self.window - 1) / self.window;
240 let modulus_size = T::ScalarField::MODULUS_BIT_SIZE as usize;
241 let scalar_val = scalar.into_bigint().to_bits_le();
242
243 let mut res = T::from(self.table[0][0]);
244 for outer in 0..outerc {
245 let mut inner = 0usize;
246 for i in 0..self.window {
247 if outer * self.window + i < modulus_size && scalar_val[outer * self.window + i] {
248 inner |= 1 << i;
249 }
250 }
251 res += &self.table[outer][inner];
252 }
253 res
254 }
255}