1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
 
    3 // SPDX-License-Identifier: LGPL-3.0+
 
    5 #ifndef __ZETH_CIRCUITS_CIRCUITS_UTILS_TCC__
 
    6 #define __ZETH_CIRCUITS_CIRCUITS_UTILS_TCC__
 
    8 #include <libsnark/gadgetlib1/pb_variable.hpp>
 
   14 // This define directive is useless/redundant, as ONE is defined here:
 
   15 // libsnark/gadgetlib1/pb_variable.hpp#74
 
   19 #define ONE libsnark::pb_variable<FieldT>(0)
 
   21 // We know that a pb_variable takes an index in the constructor:
 
   22 // See: libsnark/gadgetlib1/pb_variable.hpp#29
 
   23 // Then the pb_variable can be allocated on the protoboard
 
   24 // See here for the allocation function: libsnark/gadgetlib1/pb_variable.tcc#19
 
   25 // This function calls the allocation function of the protoboard:
 
   26 // libsnark/gadgetlib1/protoboard.tcc#38 This function basically allocates the
 
   27 // variable on the protoboard at the index defined by the variable
 
   28 // "next_free_var". It then returns the index the variable was allocated at,
 
   29 // and, we can see in libsnark/gadgetlib1/pb_variable.tcc#19 that the index of
 
   30 // the variable is given by the index where the variable was allocated on the
 
   31 // protoboard. MOREOVER, we see in: libsnark/gadgetlib1/protoboard.tcc#19 (the
 
   32 // constructor of the protoboard) that "next_free_var = 1;" to account for
 
   33 // constant 1 term. Thus, the variable at index 0 on the protoboard is the
 
   34 // constant_term variable, which value is FieldT::one() (which basically is the
 
   35 // multiplicative identity of the field FieldT) Thus we are safe here. The ONE
 
   36 // is well equal to the value FieldT::one()
 
   38 // Pack input binary strings into F_r and add the resulting field elements
 
   40 template<typename FieldT>
 
   41 libsnark::linear_combination<FieldT> packed_addition(
 
   42     const libsnark::pb_variable_array<FieldT> &inputs)
 
   44     // We use `inputs.rbegin(), inputs.rend()` otherwise the resulting linear
 
   45     // combination is built by interpreting our bit string as little endian.
 
   46     // Thus here, we make sure our binary string is interpreted correctly.
 
   47     return libsnark::pb_packing_sum<FieldT>(
 
   48         libsnark::pb_variable_array<FieldT>(inputs.rbegin(), inputs.rend()));
 
   51 // Allocate an array of variables on a given protoboard, and set the values to
 
   52 // zero or one based on a vector of bits.
 
   53 template<typename FieldT>
 
   54 libsnark::pb_variable_array<FieldT> pb_variable_array_from_bit_vector(
 
   55     libsnark::protoboard<FieldT> &pb,
 
   56     const std::vector<bool> &bits,
 
   57     const std::string &annotation_prefix)
 
   59     libsnark::pb_variable_array<FieldT> vars;
 
   60     vars.allocate(pb, bits.size(), annotation_prefix);
 
   61     vars.fill_with_bits(pb, bits);
 
   65 } // namespace libzeth
 
   67 #endif // __ZETH_CIRCUITS_CIRCUITS_UTILS_TCC__