/** @file ***************************************************************************** * @author This file is part of libsnark, developed by SCIPR Lab * and contributors (see AUTHORS). * @copyright MIT license (see LICENSE file) *****************************************************************************/ #ifndef PB_VARIABLE_TCC_ #define PB_VARIABLE_TCC_ #include #include "gadgetlib1/protoboard.hpp" #include "common/utils.hpp" namespace libsnark { template void pb_variable::allocate(protoboard &pb, const std::string &annotation) { this->index = pb.allocate_var_index(annotation); } /* allocates pb_variable array in MSB->LSB order */ template void pb_variable_array::allocate(protoboard &pb, const size_t n, const std::string &annotation_prefix) { #ifdef DEBUG assert(annotation_prefix != ""); #endif (*this).resize(n); for (size_t i = 0; i < n; ++i) { (*this)[i].allocate(pb, FMT(annotation_prefix, "_%zu", i)); } } template void pb_variable_array::fill_with_field_elements(protoboard &pb, const std::vector& vals) const { assert(this->size() == vals.size()); for (size_t i = 0; i < vals.size(); ++i) { pb.val((*this)[i]) = vals[i]; } } template void pb_variable_array::fill_with_bits(protoboard &pb, const bit_vector& bits) const { assert(this->size() == bits.size()); for (size_t i = 0; i < bits.size(); ++i) { pb.val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero()); } } template void pb_variable_array::fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const { const bigint rint = r.as_bigint(); for (size_t i = 0; i < this->size(); ++i) { pb.val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero(); } } template void pb_variable_array::fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const { this->fill_with_bits_of_field_element(pb, FieldT(i, true)); } template std::vector pb_variable_array::get_vals(const protoboard &pb) const { std::vector result(this->size()); for (size_t i = 0; i < this->size(); ++i) { result[i] = pb.val((*this)[i]); } return result; } template bit_vector pb_variable_array::get_bits(const protoboard &pb) const { bit_vector result; for (size_t i = 0; i < this->size(); ++i) { const FieldT v = pb.val((*this)[i]); assert(v == FieldT::zero() || v == FieldT::one()); result.push_back(v == FieldT::one()); } return result; } template FieldT pb_variable_array::get_field_element_from_bits(const protoboard &pb) const { FieldT result = FieldT::zero(); for (size_t i = 0; i < this->size(); ++i) { /* push in the new bit */ const FieldT v = pb.val((*this)[this->size()-1-i]); assert(v == FieldT::zero() || v == FieldT::one()); result += result + v; } return result; } template pb_linear_combination::pb_linear_combination() { this->is_variable = false; this->index = 0; } template pb_linear_combination::pb_linear_combination(const pb_variable &var) { this->is_variable = true; this->index = var.index; this->terms.emplace_back(linear_term(var)); } template void pb_linear_combination::assign(protoboard &pb, const linear_combination &lc) { assert(this->is_variable == false); this->index = pb.allocate_lc_index(); this->terms = lc.terms; } template void pb_linear_combination::evaluate(protoboard &pb) const { if (this->is_variable) { return; // do nothing } FieldT sum = 0; for (auto term : this->terms) { sum += term.coeff * pb.val(pb_variable(term.index)); } pb.lc_val(*this) = sum; } template bool pb_linear_combination::is_constant() const { if (is_variable) { return (index == 0); } else { for (auto term : this->terms) { if (term.index != 0) { return false; } } return true; } } template FieldT pb_linear_combination::constant_term() const { if (is_variable) { return (index == 0 ? FieldT::one() : FieldT::zero()); } else { FieldT result = FieldT::zero(); for (auto term : this->terms) { if (term.index == 0) { result += term.coeff; } } return result; } } template void pb_linear_combination_array::evaluate(protoboard &pb) const { for (size_t i = 0; i < this->size(); ++i) { (*this)[i].evaluate(pb); } } template void pb_linear_combination_array::fill_with_field_elements(protoboard &pb, const std::vector& vals) const { assert(this->size() == vals.size()); for (size_t i = 0; i < vals.size(); ++i) { pb.lc_val((*this)[i]) = vals[i]; } } template void pb_linear_combination_array::fill_with_bits(protoboard &pb, const bit_vector& bits) const { assert(this->size() == bits.size()); for (size_t i = 0; i < bits.size(); ++i) { pb.lc_val((*this)[i]) = (bits[i] ? FieldT::one() : FieldT::zero()); } } template void pb_linear_combination_array::fill_with_bits_of_field_element(protoboard &pb, const FieldT &r) const { const bigint rint = r.as_bigint(); for (size_t i = 0; i < this->size(); ++i) { pb.lc_val((*this)[i]) = rint.test_bit(i) ? FieldT::one() : FieldT::zero(); } } template void pb_linear_combination_array::fill_with_bits_of_uint64(protoboard &pb, const uint64_t i) const { this->fill_with_bits_of_field_element(pb, FieldT(i)); } template std::vector pb_linear_combination_array::get_vals(const protoboard &pb) const { std::vector result(this->size()); for (size_t i = 0; i < this->size(); ++i) { result[i] = pb.lc_val((*this)[i]); } return result; } template bit_vector pb_linear_combination_array::get_bits(const protoboard &pb) const { bit_vector result; for (size_t i = 0; i < this->size(); ++i) { const FieldT v = pb.lc_val((*this)[i]); assert(v == FieldT::zero() || v == FieldT::one()); result.push_back(v == FieldT::one()); } return result; } template FieldT pb_linear_combination_array::get_field_element_from_bits(const protoboard &pb) const { FieldT result = FieldT::zero(); for (size_t i = 0; i < this->size(); ++i) { /* push in the new bit */ const FieldT v = pb.lc_val((*this)[this->size()-1-i]); assert(v == FieldT::zero() || v == FieldT::one()); result += result + v; } return result; } template linear_combination pb_sum(const pb_linear_combination_array &v) { linear_combination result; for (auto &term : v) { result = result + term; } return result; } template linear_combination pb_packing_sum(const pb_linear_combination_array &v) { FieldT twoi = FieldT::one(); // will hold 2^i entering each iteration std::vector > all_terms; for (auto &lc : v) { for (auto &term : lc.terms) { all_terms.emplace_back(twoi * term); } twoi += twoi; } return linear_combination(all_terms); } template linear_combination pb_coeff_sum(const pb_linear_combination_array &v, const std::vector &coeffs) { assert(v.size() == coeffs.size()); std::vector > all_terms; auto coeff_it = coeffs.begin(); for (auto &lc : v) { for (auto &term : lc.terms) { all_terms.emplace_back((*coeff_it) * term); } ++coeff_it; } return linear_combination(all_terms); } } // libsnark #endif // PB_VARIABLE_TCC