Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
translator_selectors.hpp
Go to the documentation of this file.
1#pragma once
3#include <array>
4#include <cstddef>
5#include <span>
6
7namespace bb {
8
23template <typename FF, size_t LOG_MINI_CIRCUIT_SIZE> struct TranslatorSelectorEvaluations {
24 // Derived circuit geometry
25 static constexpr size_t LOG_CONCAT_GROUP_SIZE = 4; // log2(16)
26 static constexpr size_t LOG_N = LOG_MINI_CIRCUIT_SIZE + LOG_CONCAT_GROUP_SIZE;
27
28 // Row layout constants (structural, not size-dependent)
29 static constexpr size_t RESULT_ROW = 8;
30 static constexpr size_t NUM_MASKED_ROWS_END = 4;
31 static constexpr size_t RANDOMNESS_START = 2;
32 static constexpr size_t CONCATENATION_GROUP_SIZE = 1UL << LOG_CONCAT_GROUP_SIZE;
34
35 // Bit positions used in the subcube decompositions
36 static constexpr size_t LOG_NUM_MASKED = 2; // log2(NUM_MASKED_ROWS_END)
37 static constexpr size_t LOG_RESULT_ROW = 3; // log2(RESULT_ROW)
38 static constexpr size_t LOG_RANDOMNESS_START = 1; // log2(RANDOMNESS_START)
39 static constexpr size_t LOG_MAX_RANDOM = LOG_CONCAT_GROUP_SIZE + LOG_NUM_MASKED; // log2(64) = 6
40
41 static_assert((1UL << LOG_NUM_MASKED) == NUM_MASKED_ROWS_END);
42 static_assert((1UL << LOG_RESULT_ROW) == RESULT_ROW);
43 static_assert((1UL << LOG_RANDOMNESS_START) == RANDOMNESS_START);
44 static_assert(LOG_NUM_MASKED < LOG_RESULT_ROW, "NUM_MASKED_ROWS_END must be smaller than RESULT_ROW");
45 static_assert(LOG_RESULT_ROW < LOG_MINI_CIRCUIT_SIZE);
46 static_assert(LOG_MINI_CIRCUIT_SIZE > LOG_MAX_RANDOM, "Mini circuit must be larger than max random region");
47
48 // The 10 selector evaluations (order matches PrecomputedEntities in translator_flavor.hpp,
49 // skipping ordered_extra_range_constraints_numerator which cannot be efficiently computed)
60
68 {
69 // Notation (see class docstring for bit ordering):
70 // D = LOG_N (total number of sumcheck variables)
71 // M = LOG_MINI_CIRCUIT_SIZE (bits 0..M-1 = intra-block position)
72 // m = LOG_NUM_MASKED = 2 (last 2^m rows of each block are masking rows)
73 // r = LOG_RESULT_ROW = 3 (result row = 2^r)
74 // s = LOG_RANDOMNESS_START = 1
75 // R = LOG_MAX_RANDOM = 6 (last 2^R rows of circuit reserved for ordered masking)
76 constexpr size_t D = LOG_N;
77 constexpr size_t M = LOG_MINI_CIRCUIT_SIZE;
78 constexpr size_t m = LOG_NUM_MASKED;
79 constexpr size_t r = LOG_RESULT_ROW;
80 constexpr size_t s = LOG_RANDOMNESS_START;
81 constexpr size_t R = LOG_MAX_RANDOM;
82
83 BB_ASSERT(u.size() == D);
84
86
87 // c[k] = 1 - u[k] (complementary challenge values)
89 for (size_t k = 0; k < D; k++) {
90 c[k] = FF(1) - u[k];
91 }
92
93 // ---- Reusable partial products (built from smaller to larger, no inversions) ----
94
95 // Products of u[k]:
96 // u_mp1_M1 = ∏_{k=m+1}^{M-1} u[k] (bits above masking, within mini-circuit)
97 // u_m_M1 = ∏_{k=m}^{M-1} u[k] (full masking subcube indicator)
98 // u_Rp1_D1 = ∏_{k=R+1}^{D-1} u[k] (bits above max-random)
99 // u_R_D1 = ∏_{k=R}^{D-1} u[k] (ordered masking subcube indicator)
100 // u_0_R1 = ∏_{k=0}^{R-1} u[k] (low bits below max-random)
101 // u_0_m1 = ∏_{k=0}^{m-1} u[k] (low masking bits)
102 FF u_mp1_M1 = FF(1);
103 for (size_t k = m + 1; k < M; k++) {
104 u_mp1_M1 *= u[k];
105 }
106 FF u_m_M1 = u[m] * u_mp1_M1;
107
108 FF u_Rp1_D1 = FF(1);
109 for (size_t k = R + 1; k < D; k++) {
110 u_Rp1_D1 *= u[k];
111 }
112 FF u_R_D1 = u[R] * u_Rp1_D1;
113
114 FF u_0_R1 = FF(1);
115 for (size_t k = 0; k < R; k++) {
116 u_0_R1 *= u[k];
117 }
118
119 FF u_0_m1 = FF(1);
120 for (size_t k = 0; k < m; k++) {
121 u_0_m1 *= u[k];
122 }
123
124 // Products of c[k] = (1 - u[k]):
125 // c_rp1_M1 = ∏_{k=r+1}^{M-1} c[k]
126 // c_r_M1 = ∏_{k=r}^{M-1} c[k] (even/odd excluded-below indicator)
127 // c_M_D1 = ∏_{k=M}^{D-1} c[k] (block-0 indicator for top bits)
128 // c_r_D1 = ∏_{k=r}^{D-1} c[k]
129 // c_0_r1 = ∏_{k=0}^{r-1} c[k]
130 // c_s_r1 = ∏_{k=s}^{r-1} c[k] (gap between randomness start and result row)
131 FF c_rp1_M1 = FF(1);
132 for (size_t k = r + 1; k < M; k++) {
133 c_rp1_M1 *= c[k];
134 }
135 FF c_r_M1 = c[r] * c_rp1_M1;
136
137 FF c_M_D1 = FF(1);
138 for (size_t k = M; k < D; k++) {
139 c_M_D1 *= c[k];
140 }
141
142 FF c_r_D1 = c_r_M1 * c_M_D1;
143
144 FF c_0_r1 = FF(1);
145 for (size_t k = 0; k < r; k++) {
146 c_0_r1 *= c[k];
147 }
148
149 FF c_s_r1 = FF(1);
150 for (size_t k = s; k < r; k++) {
151 c_s_r1 *= c[k];
152 }
153
154 // ---- Single-point Lagrange bases ----
155
156 // lagrange_first: row 0 (all bits 0)
157 // eval = ∏_{k=0}^{D-1} (1 - u_k)
158 evals.lagrange_first = c_0_r1 * c_r_D1;
159
160 // lagrange_last: row 2^D - 1 (all bits 1)
161 // eval = ∏_{k=0}^{D-1} u_k
162 evals.lagrange_last = u_0_R1 * u_R_D1;
163
164 // lagrange_result_row: row 2^r (only bit r set)
165 // eval = u_r · ∏_{k≠r} (1 - u_k)
166 evals.lagrange_result_row = c_0_r1 * u[r] * c_rp1_M1 * c_M_D1;
167
168 // lagrange_last_in_minicircuit: row 2^M - 2^m - 1 (bits 0..m-1=1, bit m=0, bits m+1..M-1=1, bits M..D-1=0)
169 evals.lagrange_last_in_minicircuit = u_0_m1 * c[m] * u_mp1_M1 * c_M_D1;
170
171 // lagrange_real_last: row 2^D - 2^R - 1 (bits 0..R-1=1, bit R=0, bits R+1..D-1=1)
172 evals.lagrange_real_last = u_0_R1 * c[R] * u_Rp1_D1;
173
174 // ---- Subcube indicators ----
175
176 // lagrange_ordered_masking: rows with bits R..D-1 = 1, bits 0..R-1 free
177 // = ∏_{k=R}^{D-1} u_k
178 evals.lagrange_ordered_masking = u_R_D1;
179
180 // lagrange_masking: rows with bits m..M-1 = 1, bits 0..m-1 and M..D-1 free
181 // = ∏_{k=m}^{M-1} u_k
182 evals.lagrange_masking = u_m_M1;
183
184 // ---- Mini-masking (two disjoint blocks in block 0) ----
185
186 // lagrange_mini_masking: rows [RANDOMNESS_START .. RESULT_ROW-1] ∪ [MINI-NUM_MASKED .. MINI-1], block 0
187 //
188 // Part 1: rows [2^s .. 2^r - 1] = {rows [0,2^r-1]} minus {rows [0,2^s-1]}
189 // Row set [0, 2^r-1] has bits r..D-1 = 0 → sum = ∏_{k=r}^{D-1}(1-u_k) = c_r_D1
190 // Row set [0, 2^s-1] has bits s..D-1 = 0 → sum = ∏_{k=s}^{D-1}(1-u_k) = c_s_r1 · c_r_D1
191 // Difference = c_r_D1 · (1 - c_s_r1)
192 FF part1 = c_r_D1 * (FF(1) - c_s_r1);
193
194 // Part 2: rows [2^M - 2^m .. 2^M - 1] in block 0
195 // Subcube: bits m..M-1 = 1, bits 0..m-1 free, bits M..D-1 = 0
196 // = ∏_{k=m}^{M-1} u_k · ∏_{k=M}^{D-1}(1-u_k)
197 FF part2 = u_m_M1 * c_M_D1;
198
199 evals.lagrange_mini_masking = part1 + part2;
200
201 // ---- Even/odd alternating selectors ----
202
203 // lagrange_even_in_minicircuit: 1 at even rows in [RESULT_ROW, MINI-NUM_MASKED-2], block 0
204 // Condition: bit 0 = 0, bits M..D-1 = 0, half-index j ∈ [2^(r-1), 2^(M-1) - 2^(m-1) - 1]
205 //
206 // The full half-index range [0, 2^(M-1)-1] sums to 1. We subtract the excluded ends:
207 // - Excluded below: j < 2^(r-1) → original bits r..M-1 = 0 → sum = ∏_{k=r}^{M-1}(1-u_k) = c_r_M1
208 // - Excluded above: j >= 2^(M-1) - 2^(m-1) → original bits m..M-1 = 1 → sum = ∏_{k=m}^{M-1} u_k = u_m_M1
209 //
210 // eval = (1-u_0) · ∏_{k=M}^{D-1}(1-u_k) · (1 - c_r_M1 - u_m_M1)
211 FF inner_even_odd = FF(1) - c_r_M1 - u_m_M1;
212
213 evals.lagrange_even_in_minicircuit = c[0] * c_M_D1 * inner_even_odd;
214
215 // lagrange_odd_in_minicircuit: same structure with bit 0 = 1
216 evals.lagrange_odd_in_minicircuit = u[0] * c_M_D1 * inner_even_odd;
217
218 return evals;
219 }
220
225 template <typename Entities> void populate(Entities& target) const
226 {
227 target.lagrange_first = lagrange_first;
228 target.lagrange_last = lagrange_last;
229 target.lagrange_odd_in_minicircuit = lagrange_odd_in_minicircuit;
230 target.lagrange_even_in_minicircuit = lagrange_even_in_minicircuit;
231 target.lagrange_result_row = lagrange_result_row;
232 target.lagrange_last_in_minicircuit = lagrange_last_in_minicircuit;
233 target.lagrange_masking = lagrange_masking;
234 target.lagrange_mini_masking = lagrange_mini_masking;
235 target.lagrange_real_last = lagrange_real_last;
236 target.lagrange_ordered_masking = lagrange_ordered_masking;
237 }
238};
239
240} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
bb::field< bb::Bn254FrParams > FF
Definition field.cpp:24
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
Evaluates the 10 structured Translator precomputed selectors at a sumcheck challenge point.
static TranslatorSelectorEvaluations compute(std::span< const FF > u)
Compute evaluations of all 10 structured selectors at the sumcheck challenge.
static constexpr size_t LOG_CONCAT_GROUP_SIZE
static constexpr size_t LOG_RANDOMNESS_START
void populate(Entities &target) const
Write all 10 computed evaluations into any entity struct with matching named fields.
static constexpr size_t CONCATENATION_GROUP_SIZE
static constexpr size_t NUM_MASKED_ROWS_END
static constexpr size_t MAX_RANDOM_VALUES_PER_ORDERED