blueprint_linear_combination.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 
26 #ifndef CRYPTO3_ZK_BLUEPRINT_LINEAR_COMBINATION_HPP
27 #define CRYPTO3_ZK_BLUEPRINT_LINEAR_COMBINATION_HPP
28 
29 #include <vector>
30 
31 #include <nil/crypto3/multiprecision/integer.hpp>
32 #include <nil/crypto3/multiprecision/number.hpp>
33 
35 
36 namespace nil {
37  namespace crypto3 {
38  namespace zk {
39  namespace components {
40 
41  using lc_index_t = std::size_t;
42 
43  template<typename FieldType>
44  class blueprint;
45 
46  template<typename FieldType>
48  typedef FieldType field_type;
49  typedef typename field_type::value_type field_value_type;
50 
51  public:
54 
56  this->is_variable = false;
57  }
58 
60  this->is_variable = true;
61  this->index = var.index;
62  this->terms.emplace_back(snark::linear_term<field_type>(var));
63  }
64 
66  assert(this->is_variable == false);
67  this->index = bp.allocate_lc_index();
68  this->terms = lc.terms;
69  }
70 
71  void evaluate(blueprint<field_type> &bp) const {
72  if (this->is_variable) {
73  return; // do nothing
74  }
75 
76  field_value_type sum = 0;
77  for (auto term : this->terms) {
78  sum += term.coeff * bp.val(blueprint_variable<field_type>(term.index));
79  }
80 
81  bp.lc_val(*this) = sum;
82  }
83 
84  bool is_constant() const {
85  if (is_variable) {
86  return (index == 0);
87  } else {
88  for (auto term : this->terms) {
89  if (term.index != 0) {
90  return false;
91  }
92  }
93 
94  return true;
95  }
96  }
97 
98  field_value_type constant_term() const {
99  if (is_variable) {
100  return (index == 0 ? field_value_type::one() : field_value_type::zero());
101  } else {
102  field_value_type result = field_value_type::zero();
103  for (auto term : this->terms) {
104  if (term.index == 0) {
105  result += term.coeff;
106  }
107  }
108  return result;
109  }
110  }
111  };
112 
113  template<typename FieldType>
115  : private std::vector<blueprint_linear_combination<FieldType>> {
116 
117  typedef FieldType field_type;
118  typedef typename field_type::value_type field_value_type;
119  typedef std::vector<blueprint_linear_combination<field_type>> contents;
120 
121  public:
122  using typename contents::const_iterator;
123  using typename contents::const_reverse_iterator;
124  using typename contents::iterator;
125  using typename contents::reverse_iterator;
126 
127  using contents::begin;
128  using contents::emplace_back;
129  using contents::empty;
130  using contents::end;
131  using contents::insert;
132  using contents::rbegin;
133  using contents::rend;
134  using contents::reserve;
135  using contents::size;
136  using contents::operator[];
137  using contents::resize;
138 
141  for (auto &v : arr)
142  this->emplace_back(blueprint_linear_combination<field_type>(v));
143  };
144  blueprint_linear_combination_vector(std::size_t count) : contents(count) {};
147  contents(count, value) {};
148  blueprint_linear_combination_vector(typename contents::const_iterator first,
149  typename contents::const_iterator last) :
150  contents(first, last) {};
151  blueprint_linear_combination_vector(typename contents::const_reverse_iterator first,
152  typename contents::const_reverse_iterator last) :
153  contents(first, last) {};
154 
155  void evaluate(blueprint<field_type> &bp) const {
156  for (std::size_t i = 0; i < this->size(); ++i) {
157  (*this)[i].evaluate(bp);
158  }
159  }
160 
162  const std::vector<field_value_type> &vals) const {
163  assert(this->size() == vals.size());
164  for (std::size_t i = 0; i < vals.size(); ++i) {
165  bp.lc_val((*this)[i]) = vals[i];
166  }
167  }
168 
169  void fill_with_bits(blueprint<field_type> &bp, const std::vector<bool> &bits) const {
170  assert(this->size() == bits.size());
171  for (std::size_t i = 0; i < bits.size(); ++i) {
172  bp.lc_val((*this)[i]) = (bits[i] ? field_value_type::one() : field_value_type::zero());
173  }
174  }
175 
176  void fill_with_bits_of_ulong(blueprint<field_type> &bp, const unsigned long i) const {
177  this->fill_with_bits_of_field_element(bp, field_value_type(i));
178  }
179 
180  void fill_with_bits_of_field_element(blueprint<field_type> &bp, const field_value_type &r) const {
181  for (std::size_t i = 0; i < this->size(); ++i) {
182  bp.lc_val((*this)[i]) = multiprecision::bit_test(r.data, i) ? field_value_type::one() :
183  field_value_type::zero();
184  }
185  }
186 
187  std::vector<field_value_type> get_vals(const blueprint<field_type> &bp) const {
188  std::vector<field_value_type> result(this->size());
189  for (std::size_t i = 0; i < this->size(); ++i) {
190  result[i] = bp.lc_val((*this)[i]);
191  }
192  return result;
193  }
194 
195  std::vector<bool> get_bits(const blueprint<field_type> &bp) const {
196  std::vector<bool> result;
197  for (std::size_t i = 0; i < this->size(); ++i) {
198  const field_value_type v = bp.lc_val((*this)[i]);
199  assert(v.is_zero() || v.is_one());
200  result.push_back(v.is_one());
201  }
202  return result;
203  }
204 
205  field_value_type get_field_element_from_bits(const blueprint<field_type> &bp) const {
206  field_value_type result = field_value_type::zero();
207 
208  for (std::size_t i = 0; i < this->size(); ++i) {
209  /* push in the new bit */
210  const field_value_type v = bp.lc_val((*this)[this->size() - 1 - i]);
211  assert(v.is_zero() || v.is_one());
212  result += result + v;
213  }
214 
215  return result;
216  }
217  };
218 
219  template<typename FieldType>
222 
224  for (auto &term : v) {
225  result = result + term;
226  }
227 
228  return result;
229  }
230 
231  template<typename FieldType>
234 
235  typename FieldType::value_type twoi =
236  FieldType::value_type::one(); // will hold 2^i entering each iteration
237  std::vector<snark::linear_term<FieldType>> all_terms;
238  for (auto &lc : v) {
239  for (auto &term : lc.terms) {
240  all_terms.emplace_back(twoi * term);
241  }
242  twoi += twoi;
243  }
244 
245  return snark::linear_combination<FieldType>(all_terms);
246  }
247 
248  template<typename FieldType>
251  const std::vector<typename FieldType::value_type> &coeffs) {
252 
253  assert(v.size() == coeffs.size());
254  std::vector<snark::linear_term<FieldType>> all_terms;
255 
256  auto coeff_it = coeffs.begin();
257  for (auto &lc : v) {
258  for (auto &term : lc.terms) {
259  all_terms.emplace_back((*coeff_it) * term);
260  }
261  ++coeff_it;
262  }
263 
264  return snark::linear_combination<FieldType>(all_terms);
265  }
266  } // namespace components
267  } // namespace zk
268  } // namespace crypto3
269 } // namespace nil
270 
271 #endif // CRYPTO3_ZK_BLUEPRINT_LINEAR_COMBINATION_HPP
Definition: blueprint_linear_combination.hpp:115
blueprint_linear_combination_vector(typename contents::const_iterator first, typename contents::const_iterator last)
Definition: blueprint_linear_combination.hpp:148
field_value_type get_field_element_from_bits(const blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:205
void fill_with_bits(blueprint< field_type > &bp, const std::vector< bool > &bits) const
Definition: blueprint_linear_combination.hpp:169
std::vector< field_value_type > get_vals(const blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:187
blueprint_linear_combination_vector(typename contents::const_reverse_iterator first, typename contents::const_reverse_iterator last)
Definition: blueprint_linear_combination.hpp:151
std::vector< bool > get_bits(const blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:195
void fill_with_bits_of_ulong(blueprint< field_type > &bp, const unsigned long i) const
Definition: blueprint_linear_combination.hpp:176
blueprint_linear_combination_vector(std::size_t count)
Definition: blueprint_linear_combination.hpp:144
void fill_with_field_elements(blueprint< field_type > &bp, const std::vector< field_value_type > &vals) const
Definition: blueprint_linear_combination.hpp:161
void fill_with_bits_of_field_element(blueprint< field_type > &bp, const field_value_type &r) const
Definition: blueprint_linear_combination.hpp:180
blueprint_linear_combination_vector(std::size_t count, const blueprint_linear_combination< field_type > &value)
Definition: blueprint_linear_combination.hpp:145
blueprint_linear_combination_vector(const blueprint_variable_vector< field_type > &arr)
Definition: blueprint_linear_combination.hpp:140
blueprint_linear_combination_vector()
Definition: blueprint_linear_combination.hpp:139
void evaluate(blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:155
Definition: blueprint_linear_combination.hpp:47
void assign(blueprint< field_type > &bp, const snark::linear_combination< field_type > &lc)
Definition: blueprint_linear_combination.hpp:65
void evaluate(blueprint< field_type > &bp) const
Definition: blueprint_linear_combination.hpp:71
blueprint_linear_combination(const blueprint_variable< field_type > &var)
Definition: blueprint_linear_combination.hpp:59
bool is_variable
Definition: blueprint_linear_combination.hpp:52
lc_index_t index
Definition: blueprint_linear_combination.hpp:53
field_value_type constant_term() const
Definition: blueprint_linear_combination.hpp:98
bool is_constant() const
Definition: blueprint_linear_combination.hpp:84
blueprint_linear_combination()
Definition: blueprint_linear_combination.hpp:55
Definition: blueprint_variable.hpp:57
Definition: blueprint.hpp:46
FieldType::value_type & val(const blueprint_variable< FieldType > &var)
Definition: blueprint.hpp:70
FieldType::value_type & lc_val(const blueprint_linear_combination< FieldType > &lc)
Definition: blueprint.hpp:80
constexpr T sum(const vector< T, N > &v)
computes the sum of elements
Definition: algebra/include/nil/crypto3/algebra/vector/math.hpp:124
vector(T, U...) -> vector< std::enable_if_t<(std::is_same_v< T, U > &&...), T >, 1+sizeof...(U)>
deduction guide for uniform initialization
std::size_t lc_index_t
Definition: blueprint_linear_combination.hpp:41
snark::linear_combination< FieldType > blueprint_sum(const blueprint_linear_combination_vector< FieldType > &v)
Definition: blueprint_linear_combination.hpp:221
snark::linear_combination< FieldType > blueprint_coeff_sum(const blueprint_linear_combination_vector< FieldType > &v, const std::vector< typename FieldType::value_type > &coeffs)
Definition: blueprint_linear_combination.hpp:250
snark::linear_combination< FieldType > blueprint_packing_sum(const blueprint_linear_combination_vector< FieldType > &v)
Definition: blueprint_linear_combination.hpp:233
digest< DigestBits > resize(const digest< DigestBits > &od, std::size_t new_size)
Definition: block/include/nil/crypto3/detail/digest.hpp:131
digest< NewBits > reserve(const digest< OldBits > &od)
Definition: block/include/nil/crypto3/detail/digest.hpp:115
Definition: pair.hpp:31
std::vector< linear_term< FieldType > > terms
Definition: variable.hpp:233
Definition: variable.hpp:144
index_type index
Definition: variable.hpp:69