barretenberg
Loading...
Searching...
No Matches
bit_array.hpp
1#pragma once
2#include "../circuit_builders/circuit_builders_fwd.hpp"
3#include "../uint/uint.hpp"
4#include <algorithm>
5
6namespace proof_system::plonk {
7namespace stdlib {
8
9template <typename Builder> class bit_array {
10 public:
11 bit_array(Builder* parent_context, const size_t n);
12 bit_array(Builder* parent_context, const std::string& input);
13 bit_array(Builder* parent_context, const std::vector<uint8_t>& input);
14 bit_array(const std::vector<uint32<Builder>>& input);
15 bit_array(uint32<Builder> const& input);
16 bit_array(byte_array<Builder> const& input)
17 : context(input.get_context())
18 , length(input.size() * 8)
19 {
20 const auto bytes = input.bytes();
21 const size_t num_bits = bytes.size() * 8;
22 values.resize(num_bits);
23 for (size_t i = 0; i < bytes.size(); ++i) {
24 const auto byte = bytes[i];
25 field_t<Builder> accumulator(0);
26 for (size_t j = 0; j < 8; ++j) {
27 const auto bit_witness = uint256_t((uint256_t(byte.get_value()) >> (7 - j)) & uint256_t(1));
28 bool_t<Builder> bit = witness_t<Builder>(context, bit_witness);
29 values[i * 8 + j] = bit;
30 accumulator *= 2;
31 accumulator += bit;
32 }
33 byte.assert_equal(accumulator);
34 }
35 std::reverse(values.begin(), values.end());
36 }
37
38 template <size_t N> bit_array(const std::array<uint32<Builder>, N>& input)
39 {
40 context = nullptr;
41 for (const auto& x : input) {
42 if (x.get_context() != nullptr) {
43 context = x.get_context();
44 break;
45 }
46 }
47
48 size_t num_words = static_cast<size_t>(N);
49 values.resize(num_words * 32);
50 for (size_t i = 0; i < num_words; ++i) {
51 size_t input_index = num_words - 1 - i;
52 for (size_t j = 0; j < 32; ++j) {
53 values[i * 32 + j] = input[input_index].at(j);
54 }
55 }
56 length = num_words * 32;
57 }
58
59 bit_array(const bit_array& other);
60 bit_array(bit_array&& other);
61
62 bit_array& operator=(const bit_array& other);
63 bit_array& operator=(bit_array&& other);
64
65 bool_t<Builder>& operator[](const size_t idx);
66 bool_t<Builder> operator[](const size_t idx) const;
67
68 explicit operator byte_array<Builder>() const
69 {
70
71 std::vector<bool_t<Builder>> rbits(values.rbegin(), values.rend());
72
73 const size_t num_bits = rbits.size();
74 const size_t num_bytes = (num_bits / 8) + (num_bits % 8 != 0);
75
76 std::vector<field_t<Builder>> values(num_bytes);
77
78 for (size_t i = 0; i < num_bytes; ++i) {
79 size_t end = 8;
80 if (i == num_bytes - 1 && (num_bits % 8 != 0)) {
81 end = num_bits % 8;
82 }
83 field_t<Builder> accumulator(0);
84 for (size_t j = 0; j < end; ++j) {
85 const auto bit = rbits[i * 8 + j];
86 const uint256_t scaling_factor = uint256_t(1) << (end - j - 1);
87 accumulator += field_t<Builder>(bit) * barretenberg::fr(scaling_factor);
88 }
89 values[i] = accumulator;
90 }
91 return byte_array(context, values);
92 };
93
94 template <size_t N> operator std::array<uint32<Builder>, N>()
95 {
96 // ASSERT(N * 32 == length);
97 std::array<uint32<Builder>, N> output;
98 for (size_t i = 0; i < N; ++i) {
99 std::array<bool_t<Builder>, 32> bools;
100 size_t end;
101 size_t start;
102 start = ((N - i) * 32) - 32;
103 end = start + 32 > length ? length : start + 32;
104 for (size_t j = start; j < end; ++j) {
105 bools[j - start] = values[j];
106 }
107 if (start + 32 > length) {
108 for (size_t j = end; j < start + 32; ++j) {
109 bools[j - start] = bool_t<Builder>(context, false);
110 }
111 }
112 output[i] = uint32<Builder>(context, bools);
113 }
114 return output;
115 }
116
117 std::vector<uint32<Builder>> to_uint32_vector();
118
119 template <size_t N> void populate_uint32_array(const size_t starting_index, std::array<uint32<Builder>, N>& output)
120 {
121 // ASSERT(N * 32 == (length - starting_index));
122
123 size_t num_uint32s = (length / 32) + (length % 32 != 0);
124 size_t num_selected_uint32s = N;
125
126 size_t count = 0;
127 for (size_t i = (0); i < num_selected_uint32s; ++i) {
128 std::array<bool_t<Builder>, 32> bools;
129 size_t end;
130 size_t start;
131 start = ((num_uint32s - i) * 32) - 32;
132 end = start + 32 > length ? length : start + 32;
133 for (size_t j = start; j < end; ++j) {
134 bools[j - start] = values[j - starting_index];
135 }
136 if (start + 32 > length) {
137 for (size_t j = end; j < start + 32; ++j) {
138 bools[j - start] = bool_t<Builder>(context, false);
139 }
140 }
141
142 output[count] = uint32<Builder>(context, bools);
143 ++count;
144 }
145 }
146
147 std::string get_witness_as_string() const;
148
149 size_t size() const { return length; }
150
151 Builder* get_context() const { return context; }
152
153 void print() const
154 {
155 size_t num_ulongs = (length / 32) + (length % 32 != 0);
156 std::vector<uint32_t> ulong_vector(num_ulongs, 0);
157 for (size_t i = 0; i < length; ++i) {
158 size_t ulong_index = i / 32;
159 uint32_t shift = static_cast<uint32_t>(i - (ulong_index * 32));
160 ulong_vector[num_ulongs - 1 - ulong_index] =
161 ulong_vector[num_ulongs - 1 - ulong_index] + (static_cast<uint32_t>(values[i].get_value()) << shift);
162 }
163 printf("[");
164 for (size_t i = 0; i < num_ulongs; ++i) {
165 printf(" %x", (ulong_vector[i]));
166 }
167 printf(" ]\n");
168 }
169
170 std::vector<bool_t<Builder>> get_bits() const
171 {
172 const std::vector<bool_t<Builder>> result(values.begin(), values.end());
173 return result;
174 }
175
176 private:
177 Builder* context;
178 size_t length;
179 std::vector<bool_t<Builder>> values;
180};
181
182EXTERN_STDLIB_TYPE(bit_array);
183
184} // namespace stdlib
185} // namespace proof_system::plonk
Definition: uint256.hpp:25
Definition: standard_circuit_builder.hpp:12
Definition: bit_array.hpp:9
Definition: byte_array.hpp:9
Definition: field.hpp:10
Definition: witness.hpp:10
Definition: widget.bench.cpp:13