27 #ifndef CRYPTO3_ALGEBRA_MULTIEXP_HPP
28 #define CRYPTO3_ALGEBRA_MULTIEXP_HPP
32 #include <nil/crypto3/multiprecision/number.hpp>
33 #include <nil/crypto3/multiprecision/cpp_int.hpp>
41 template<
typename MultiexpMethod,
typename InputBaseIterator,
typename InputFieldIterator>
42 typename std::iterator_traits<InputBaseIterator>::value_type
43 multiexp(InputBaseIterator vec_start, InputBaseIterator vec_end, InputFieldIterator scalar_start,
44 InputFieldIterator scalar_end,
const std::size_t chunks_count) {
46 typedef typename std::iterator_traits<InputBaseIterator>::value_type base_value_type;
47 typedef typename std::iterator_traits<InputFieldIterator>::value_type field_value_type;
49 const std::size_t total_size = std::distance(vec_start, vec_end);
51 if ((total_size < chunks_count) || (chunks_count == 1)) {
53 return MultiexpMethod::process(vec_start, vec_end, scalar_start, scalar_end);
56 const std::size_t one_chunk_size = total_size / chunks_count;
58 base_value_type result = base_value_type::zero();
60 for (std::size_t i = 0; i < chunks_count; ++i) {
62 result + MultiexpMethod::process(
63 vec_start + i * one_chunk_size,
64 (i == chunks_count - 1 ? vec_end : vec_start + (i + 1) * one_chunk_size),
65 scalar_start + i * one_chunk_size,
66 (i == chunks_count - 1 ? scalar_end : scalar_start + (i + 1) * one_chunk_size));
72 template<
typename MultiexpMethod,
typename InputBaseIterator,
typename InputFieldIterator>
73 typename std::iterator_traits<InputBaseIterator>::value_type
75 InputFieldIterator scalar_start, InputFieldIterator scalar_end,
76 const std::size_t chunks_count) {
78 typedef typename std::iterator_traits<InputBaseIterator>::value_type base_value_type;
79 typedef typename std::iterator_traits<InputFieldIterator>::value_type field_value_type;
81 typedef MultiexpMethod method_type;
83 BOOST_ASSERT(std::distance(vec_start, vec_end) == std::distance(scalar_start, scalar_end));
85 InputBaseIterator vec_it = vec_start;
86 InputFieldIterator scalar_it = scalar_start;
88 const field_value_type zero = field_value_type::zero();
89 const field_value_type one = field_value_type::one();
90 std::vector<field_value_type> p;
91 std::vector<base_value_type> g;
93 base_value_type acc = base_value_type::zero();
95 for (; scalar_it != scalar_end; ++scalar_it, ++vec_it) {
96 if (*scalar_it == one) {
97 #ifdef USE_MIXED_ADDITION
98 acc = acc.mixed_add(*vec_it);
100 acc = acc + (*vec_it);
102 }
else if (*scalar_it != zero) {
103 p.emplace_back(*scalar_it);
104 g.emplace_back(*vec_it);
108 return acc + multiexp<method_type>(g.begin(), g.end(), p.begin(), p.end(), chunks_count);
115 template<
typename GroupType>
116 using window_table = std::vector<std::vector<typename GroupType::value_type>>;
118 template<
typename GroupType>
128 std::size_t window = 1;
140 window =
std::min((std::size_t)14, window);
145 template<
typename GroupType>
147 const std::size_t window,
148 const typename GroupType::value_type &g) {
149 const std::size_t in_window = 1ul << window;
150 const std::size_t outerc = (scalar_size + window - 1) / window;
151 const std::size_t last_in_window = 1ul << (scalar_size - (outerc - 1) * window);
154 outerc, std::vector<typename GroupType::value_type>(in_window, GroupType::value_type::zero()));
156 typename GroupType::value_type gouter = g;
158 for (std::size_t outer = 0; outer < outerc; ++outer) {
159 typename GroupType::value_type ginner = GroupType::value_type::zero();
160 std::size_t cur_in_window = outer == outerc - 1 ? last_in_window : in_window;
161 for (std::size_t inner = 0; inner < cur_in_window; ++inner) {
162 powers_of_g[outer][inner] = ginner;
163 ginner = ginner + gouter;
166 for (std::size_t i = 0; i < window; ++i) {
167 gouter = gouter.doubled();
175 template<
typename GroupType,
typename FieldType>
176 typename GroupType::value_type
windowed_exp(
const std::size_t scalar_size,
177 const std::size_t window,
179 const typename FieldType::value_type &
pow) {
181 typedef typename FieldType::modular_type modular_type;
183 const std::size_t outerc = (scalar_size + window - 1) / window;
184 const modular_type pow_val =
pow.data;
186 typename GroupType::value_type res = powers_of_g[0][0];
188 for (std::size_t outer = 0; outer < outerc; ++outer) {
189 std::size_t inner = 0;
190 for (std::size_t i = 0; i < window; ++i) {
191 if (multiprecision::bit_test(pow_val, outer * window + i)) {
196 res = res + powers_of_g[outer][inner];
202 template<
typename GroupType,
typename FieldType,
typename InputRange,
203 typename =
typename std::enable_if<
204 std::is_same<typename InputRange::value_type, typename FieldType::value_type>::value>::type>
205 std::vector<typename GroupType::value_type>
batch_exp(
const std::size_t scalar_size,
206 const std::size_t window,
208 const InputRange &v) {
209 std::vector<typename GroupType::value_type> res(std::distance(v.begin(), v.end()), table[0][0]);
211 for (std::size_t i = 0; i < v.size(); ++i) {
212 res[i] = windowed_exp<GroupType, FieldType>(scalar_size, window, table, v[i]);
218 template<
typename GroupType,
typename FieldType,
typename InputRange,
219 typename =
typename std::enable_if<
220 std::is_same<typename InputRange::value_type, typename FieldType::value_type>::value>::type>
221 std::vector<typename GroupType::value_type>
223 const std::size_t window,
225 const typename FieldType::value_type &coeff,
226 const InputRange &v) {
227 std::vector<typename GroupType::value_type> res(std::distance(v.begin(), v.end()), table[0][0]);
229 for (std::size_t i = 0; i < v.size(); ++i) {
230 res[i] = windowed_exp<GroupType, FieldType>(scalar_size, window, table, coeff * v[i]);
236 template<
typename GroupType,
typename InputRange>
237 typename std::enable_if<
238 std::is_same<typename InputRange::value_type, typename GroupType::value_type>::value,
void>::type
241 std::vector<typename GroupType::value_type> non_zero_vec;
242 for (std::size_t i = 0; i < vec.size(); ++i) {
244 non_zero_vec.emplace_back(vec[i]);
248 GroupType::batch_to_special_all_non_zeros(non_zero_vec);
249 typename std::vector<typename GroupType::value_type>::const_iterator it = non_zero_vec.begin();
250 typename GroupType::value_type zero_special = GroupType::value_type::zero().to_projective();
252 for (std::size_t i = 0; i < vec.size(); ++i) {
257 vec[i] = zero_special;
constexpr T min(const vector< T, N > &v)
computes the minimum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:135
std::vector< std::vector< typename GroupType::value_type > > window_table
Definition: multiexp.hpp:116
window_table< GroupType > get_window_table(const std::size_t scalar_size, const std::size_t window, const typename GroupType::value_type &g)
Definition: multiexp.hpp:146
std::vector< typename GroupType::value_type > batch_exp_with_coeff(const std::size_t scalar_size, const std::size_t window, const window_table< GroupType > &table, const typename FieldType::value_type &coeff, const InputRange &v)
Definition: multiexp.hpp:222
std::iterator_traits< InputBaseIterator >::value_type multiexp_with_mixed_addition(InputBaseIterator vec_start, InputBaseIterator vec_end, InputFieldIterator scalar_start, InputFieldIterator scalar_end, const std::size_t chunks_count)
Definition: multiexp.hpp:74
std::iterator_traits< InputBaseIterator >::value_type multiexp(InputBaseIterator vec_start, InputBaseIterator vec_end, InputFieldIterator scalar_start, InputFieldIterator scalar_end, const std::size_t chunks_count)
Definition: multiexp.hpp:43
std::vector< typename GroupType::value_type > batch_exp(const std::size_t scalar_size, const std::size_t window, const window_table< GroupType > &table, const InputRange &v)
Definition: multiexp.hpp:205
std::size_t get_exp_window_size(const std::size_t num_scalars)
Definition: multiexp.hpp:119
GroupType::value_type windowed_exp(const std::size_t scalar_size, const std::size_t window, const window_table< GroupType > &powers_of_g, const typename FieldType::value_type &pow)
Definition: multiexp.hpp:176
std::enable_if< std::is_same< typename InputRange::value_type, typename GroupType::value_type >::value, void >::type batch_to_special(InputRange &vec)
Definition: multiexp.hpp:239
constexpr T pow(T x, U n)
Definition: static_pow.hpp:32
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
Definition: curves/params/multiexp/alt_bn128.hpp:39