26 #ifndef CRYPTO3_ZK_KC_MULTIEXP_HPP
27 #define CRYPTO3_ZK_KC_MULTIEXP_HPP
46 template<
typename T1,
typename T2,
typename Backend,
47 multiprecision::expression_template_option ExpressionTemplates>
50 const multiprecision::number<Backend, ExpressionTemplates> &scalar,
51 const std::size_t scalar_bits) {
57 template<
typename MultiexpMethod,
typename T1,
typename T2,
typename InputFieldIterator>
60 const std::size_t min_idx,
const std::size_t max_idx,
61 InputFieldIterator scalar_start, InputFieldIterator scalar_end,
62 const std::size_t chunks) {
63 typedef typename std::iterator_traits<InputFieldIterator>::value_type field_value_type;
64 typedef typename std::iterator_traits<InputFieldIterator>::value_type::field_type field_type;
66 const size_t scalar_length = std::distance(scalar_start, scalar_end);
69 auto index_it = std::lower_bound(vec.
indices.begin(), vec.
indices.end(), min_idx);
70 const std::size_t offset = index_it - vec.
indices.begin();
72 auto value_it = vec.
values.begin() + offset;
74 const field_value_type zero = field_value_type::zero();
75 const field_value_type one = field_value_type::one();
77 std::vector<field_value_type> p;
78 std::vector<typename knowledge_commitment<T1, T2>::value_type> g;
83 while (index_it != vec.
indices.end() && *index_it < max_idx) {
84 const std::size_t scalar_position = (*index_it) - min_idx;
85 assert(scalar_position < scalar_length);
87 const field_value_type scalar = *(scalar_start + scalar_position);
91 }
else if (scalar == one) {
92 #ifdef USE_MIXED_ADDITION
93 acc.
g = acc.
g.mixed_add(value_it->g);
94 acc.
h = acc.
h.mixed_add(value_it->h);
96 acc.
g = acc.
g + value_it->g;
97 acc.
h = acc.
h + value_it->h;
100 p.emplace_back(scalar);
101 g.emplace_back(*value_it);
108 return acc + algebra::multiexp<MultiexpMethod>(g.begin(), g.end(), p.begin(), p.end(), chunks);
111 template<
typename T1,
typename T2,
typename FieldType>
112 knowledge_commitment_vector<T1, T2>
114 const std::size_t T1_window,
115 const std::size_t T2_window,
118 const typename FieldType::value_type &T1_coeff,
119 const typename FieldType::value_type &T2_coeff,
120 const std::vector<typename FieldType::value_type> &v,
121 const std::size_t start_pos,
122 const std::size_t end_pos,
123 const std::size_t expected_size) {
126 res.
values.reserve(expected_size);
127 res.
indices.reserve(expected_size);
129 for (std::size_t pos = start_pos; pos != end_pos; ++pos) {
132 algebra::windowed_exp<T1, FieldType>(scalar_size, T1_window, T1_table, T1_coeff * v[pos]),
133 algebra::windowed_exp<T2, FieldType>(scalar_size, T2_window, T2_table, T2_coeff * v[pos])));
141 template<
typename T1,
typename T2,
typename FieldType>
143 const std::size_t T1_window,
144 const std::size_t T2_window,
147 const typename FieldType::value_type &T1_coeff,
148 const typename FieldType::value_type &T2_coeff,
149 const std::vector<typename FieldType::value_type> &v,
150 const std::size_t suggested_num_chunks) {
154 std::size_t nonzero = 0;
155 for (std::size_t i = 0; i < v.size(); ++i) {
156 nonzero += (v[i].is_zero() ? 0 : 1);
159 const std::size_t num_chunks =
std::max((std::size_t)1,
std::min(nonzero, suggested_num_chunks));
161 std::vector<knowledge_commitment_vector<T1, T2>> tmp(num_chunks);
162 std::vector<std::size_t> chunk_pos(num_chunks + 1);
164 const std::size_t chunk_size = nonzero / num_chunks;
165 const std::size_t last_chunk = nonzero - chunk_size * (num_chunks - 1);
170 std::size_t chunkno = 1;
172 for (std::size_t i = 0; i < v.size(); ++i) {
173 cnt += (v[i].is_zero() ? 0 : 1);
174 if (cnt == chunk_size && chunkno < num_chunks) {
175 chunk_pos[chunkno] = i;
181 chunk_pos[num_chunks] = v.size();
184 #pragma omp parallel for
186 for (std::size_t i = 0; i < num_chunks; ++i) {
187 tmp[i] = kc_batch_exp_internal<T1, T2, FieldType>(
188 scalar_size, T1_window, T2_window, T1_table, T2_table, T1_coeff, T2_coeff, v, chunk_pos[i],
189 chunk_pos[i + 1], i == num_chunks - 1 ? last_chunk : chunk_size);
190 #ifdef USE_MIXED_ADDITION
191 algebra::batch_to_special<typename commitments<T1, T2>::value_type>(tmp[i].values);
195 if (num_chunks == 1) {
196 tmp[0].domain_size_ = v.size();
199 for (std::size_t i = 0; i < num_chunks; ++i) {
200 res.
values.insert(res.
values.end(), tmp[i].values.begin(), tmp[i].values.end());
201 res.
indices.insert(res.
indices.end(), tmp[i].indices.begin(), tmp[i].indices.end());
constexpr T min(const vector< T, N > &v)
computes the minimum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:135
constexpr T max(const vector< T, N > &v)
computes the maximum valued element
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:146
std::vector< std::vector< typename GroupType::value_type > > window_table
Definition: multiexp.hpp:116
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
knowledge_commitment< T1, T2 >::value_type opt_window_wnaf_exp(const typename knowledge_commitment< T1, T2 >::value_type &base, const multiprecision::number< Backend, ExpressionTemplates > &scalar, const std::size_t scalar_bits)
Definition: knowledge_commitment_multiexp.hpp:49
knowledge_commitment< T1, T2 >::value_type kc_multiexp_with_mixed_addition(const knowledge_commitment_vector< T1, T2 > &vec, const std::size_t min_idx, const std::size_t max_idx, InputFieldIterator scalar_start, InputFieldIterator scalar_end, const std::size_t chunks)
Definition: knowledge_commitment_multiexp.hpp:59
knowledge_commitment_vector< T1, T2 > kc_batch_exp(const std::size_t scalar_size, const std::size_t T1_window, const std::size_t T2_window, const algebra::window_table< T1 > &T1_table, const algebra::window_table< T2 > &T2_table, const typename FieldType::value_type &T1_coeff, const typename FieldType::value_type &T2_coeff, const std::vector< typename FieldType::value_type > &v, const std::size_t suggested_num_chunks)
Definition: knowledge_commitment_multiexp.hpp:142
knowledge_commitment_vector< T1, T2 > kc_batch_exp_internal(const std::size_t scalar_size, const std::size_t T1_window, const std::size_t T2_window, const algebra::window_table< T1 > &T1_table, const algebra::window_table< T2 > &T2_table, const typename FieldType::value_type &T1_coeff, const typename FieldType::value_type &T2_coeff, const std::vector< typename FieldType::value_type > &v, const std::size_t start_pos, const std::size_t end_pos, const std::size_t expected_size)
Definition: knowledge_commitment_multiexp.hpp:113
Definition: element_knowledge_commitment.hpp:54
Type1::value_type g
Definition: element_knowledge_commitment.hpp:58
Type2::value_type h
Definition: element_knowledge_commitment.hpp:59
static element_kc zero()
Definition: element_knowledge_commitment.hpp:97
detail::element_kc< Type1, Type2 > value_type
Definition: knowledge_commitment.hpp:52
Definition: sparse_vector.hpp:48
std::vector< underlying_value_type > values
Definition: sparse_vector.hpp:58
std::vector< std::size_t > indices
Definition: sparse_vector.hpp:57
std::size_t domain_size_
Definition: sparse_vector.hpp:59