1 // Copyright (c) 2015-2022 Clearmatics Technologies Ltd
3 // SPDX-License-Identifier: LGPL-3.0+
5 #ifndef __ZETH_CORE_BITS_TCC__
6 #define __ZETH_CORE_BITS_TCC__
8 #include "libzeth/core/bits.hpp"
16 uint8_t char_to_nibble(char);
22 std::vector<bool> array_to_vector(const std::array<bool, Size> &arr)
24 std::vector<bool> vect(Size);
25 std::copy(arr.begin(), arr.end(), vect.begin());
31 template<size_t numBits> bits<numBits>::bits()
33 for (size_t i = 0; i < numBits; ++i) {
38 template<size_t numBits>
39 template<typename... boolList>
40 bits<numBits>::bits(const boolList &...bits)
41 : std::array<bool, numBits>{std::forward<bool>(bits)...}
45 template<size_t numBits> std::vector<bool> bits<numBits>::to_vector() const
47 return array_to_vector(*this);
50 template<size_t numBits>
51 bits<numBits> bits<numBits>::from_vector(const std::vector<bool> &bin)
53 if (bin.size() != numBits) {
54 throw std::invalid_argument("invalid vector size");
56 return bits(bin.begin());
59 template<size_t numBits>
60 bits<numBits> bits<numBits>::from_hex(const std::string &hex)
62 if (hex.size() != numBits / 4) {
63 throw std::invalid_argument("invalid hex string length");
67 for (const char c : hex) {
68 const uint8_t nibble = char_to_nibble(c);
69 result[i++] = (nibble & 8) != 0;
70 result[i++] = (nibble & 4) != 0;
71 result[i++] = (nibble & 2) != 0;
72 result[i++] = (nibble & 1) != 0;
78 template<size_t numBits>
79 bits<numBits> bits<numBits>::from_size_t(size_t address)
81 // cppcheck-suppress shiftTooManyBits
82 // cppcheck-suppress knownConditionTrueFalse
83 if ((numBits < 64) && (address >= (1ull << numBits))) {
84 throw std::invalid_argument("Address overflow");
87 // Initialize one bit at a time, earlying out if address turns to 0. Set
88 // all remaining bits to 0.
91 for (i = 0; i < numBits && address != 0; ++i, address >>= 1) {
92 result[i] = address & 0x1;
94 for (; i < numBits; ++i) {
98 return bits_addr<numBits>(result);
101 template<size_t numBits> bool bits<numBits>::is_zero() const
104 this->begin(), this->end(), [](const bool b) { return b != 0; });
107 template<size_t numBits>
108 template<typename FieldT>
109 void bits<numBits>::fill_pb_variable_array(
110 libsnark::protoboard<FieldT> &pb,
111 libsnark::pb_variable_array<FieldT> &var_array) const
113 if (var_array.size() != numBits) {
114 throw std::invalid_argument("invalid pb_variable_array size");
116 for (size_t i = 0; i < numBits; ++i) {
117 pb.val(var_array[i]) = ((*this)[i]) ? FieldT::one() : FieldT::zero();
121 template<size_t numBits>
122 template<typename boolIt>
123 bits<numBits>::bits(boolIt it)
125 fill_from_iterator(it);
128 template<size_t numBits>
129 template<typename boolIt>
130 void bits<numBits>::fill_from_iterator(boolIt it)
132 // (Internal function) Caller expected to check that enough elements are
133 // present before passing an iterator in.
134 for (size_t i = 0; i < numBits; ++i, ++it) {
139 template<size_t numBits>
140 bits<numBits> bits_xor(const bits<numBits> &a, const bits<numBits> &b)
142 bits<numBits> result;
143 for (size_t i = 0; i < numBits; ++i) {
144 result[i] = a[i] ^ b[i];
149 template<size_t numBits>
150 bits<numBits> bits_add(
151 const bits<numBits> &as, const bits<numBits> &bs, bool with_carry)
153 bits<numBits> result;
159 // (r, carry) = a + carry,
160 // (result[i], carry) = r + b
161 const bool a = as[i];
162 const bool b = bs[i];
166 carry = carry || (r && b);
169 // If we ask for the last carry to be taken into account
170 // (with_carry=true) and that the last carry is 1, then we raise an
172 if (with_carry && carry) {
173 throw std::overflow_error("Overflow: The sum of the binary addition "
174 "cannot be encoded on <BitLen> bits");
180 } // namespace libzeth
182 #endif // __ZETH_CORE_BITS_TCC__