Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
tracegen_helper.cpp
Go to the documentation of this file.
2
3#include <array>
4#include <functional>
5#include <span>
6#include <string>
7#include <vector>
8
51
52namespace bb::avm2 {
53
54using namespace bb::avm2::simulation;
55using namespace bb::avm2::tracegen;
56
57namespace {
58
59auto build_precomputed_columns_jobs(TraceContainer& trace)
60{
61 return std::vector<std::function<void()>>{
62 [&]() {
64 AVM_TRACK_TIME("tracegen/precomputed/misc", precomputed_builder.process_misc(trace));
65 },
66 [&]() {
68 AVM_TRACK_TIME("tracegen/precomputed/bitwise", precomputed_builder.process_bitwise(trace));
69 },
70 [&]() {
72 AVM_TRACK_TIME("tracegen/precomputed/range_8", precomputed_builder.process_sel_range_8(trace));
73 AVM_TRACK_TIME("tracegen/precomputed/range_16", precomputed_builder.process_sel_range_16(trace));
74 AVM_TRACK_TIME("tracegen/precomputed/power_of_2", precomputed_builder.process_power_of_2(trace));
75 AVM_TRACK_TIME("tracegen/precomputed/sha256_round_constants",
77 AVM_TRACK_TIME("tracegen/precomputed/keccak_round_constants",
79 AVM_TRACK_TIME("tracegen/precomputed/tag_parameters", precomputed_builder.process_tag_parameters(trace));
80 AVM_TRACK_TIME("tracegen/precomputed/operand_dec_selectors",
82 AVM_TRACK_TIME("tracegen/precomputed/exec_instruction_spec",
84 AVM_TRACK_TIME("tracegen/precomputed/to_radix_safe_limbs",
86 AVM_TRACK_TIME("tracegen/precomputed/to_radix_p_decompositions",
88 AVM_TRACK_TIME("tracegen/precomputed/memory_tag_ranges",
90 AVM_TRACK_TIME("tracegen/precomputed/addressing_gas", precomputed_builder.process_addressing_gas(trace));
91 AVM_TRACK_TIME("tracegen/precomputed/phase_table", precomputed_builder.process_phase_table(trace));
92 AVM_TRACK_TIME("tracegen/precomputed/get_env_var_table",
94 AVM_TRACK_TIME("tracegen/precomputed/get_contract_instance_table",
96 },
97 };
98}
99
100auto build_public_inputs_columns_jobs(TraceContainer& trace, const PublicInputs& public_inputs)
101{
102 return std::vector<std::function<void()>>{
103 [&]() {
104 PublicInputsTraceBuilder public_inputs_builder;
105 public_inputs_builder.process_public_inputs(trace, public_inputs);
106 },
107 [&]() {
108 PublicInputsTraceBuilder public_inputs_builder;
109 public_inputs_builder.process_public_inputs_aux_precomputed(trace);
110 },
111 };
112}
113
114void execute_jobs(std::span<std::function<void()>> jobs)
115{
116 parallel_for(jobs.size(), [&](size_t i) { jobs[i](); });
117}
118
119template <typename T> inline void clear_events(T& c)
120{
121 c.clear();
122 c.shrink_to_fit();
123}
124
125void print_trace_stats(const TraceContainer& trace)
126{
127 constexpr auto main_relation_names = [] {
128 constexpr size_t size = std::tuple_size_v<AvmFlavor::MainRelations>;
130 constexpr_for<0, size, 1>(
131 [&names]<size_t i> { names[i] = std::tuple_element_t<i, AvmFlavor::MainRelations>::NAME; });
132 return names;
133 }();
134
135 unordered_flat_map<std::string, uint32_t> namespace_column_sizes;
136 uint64_t total_rows = 0;
137 for (size_t col = 0; col < trace.num_columns(); ++col) {
138 const auto& column_rows = trace.get_column_rows(static_cast<Column>(col));
139 const std::string& column_name = COLUMN_NAMES.at(col);
140 const std::string namespace_name = [&]() {
141 for (const auto& main_relation_name : main_relation_names) {
142 if (column_name.starts_with(main_relation_name)) {
143 return std::string(main_relation_name);
144 }
145 }
146 return column_name.substr(0, column_name.find_first_of('_'));
147 }();
148 namespace_column_sizes[namespace_name] = std::max(namespace_column_sizes[namespace_name], column_rows);
149 total_rows += column_rows;
150 }
151 vinfo("Column sizes per namespace:");
152 for (const auto& [namespace_name, column_size] : namespace_column_sizes) {
153 vinfo(" ",
154 namespace_name,
155 ": ",
156 column_size,
157 " (~2^",
159 ")");
160 }
161 info("Sum of all column rows: ", total_rows, " (~2^", numeric::get_msb(numeric::round_up_power_2(total_rows)), ")");
162}
163
164// Check that inverses have been set, if assertions are enabled.
165// WARNING: This will not warn you if the interaction is not exercised.
166void check_interactions([[maybe_unused]] const TraceContainer& trace)
167{
168#ifndef NDEBUG
169 bb::constexpr_for<0, std::tuple_size_v<typename AvmFlavor::LookupRelations>, 1>([&]<size_t i>() {
170 using Settings = typename std::tuple_element_t<i, typename AvmFlavor::LookupRelations>::Settings;
171 if (trace.get_column_rows(Settings::SRC_SELECTOR) != 0 && trace.get_column_rows(Settings::INVERSES) == 0) {
172 std::cerr << "Inverses not set for " << Settings::NAME << ". Did you forget to run a lookup builder?"
173 << std::endl;
174 std::abort();
175 }
176 });
177#endif
178}
179
180} // namespace
181
183{
185
186 fill_trace_columns(trace, std::move(events), public_inputs);
188
189 check_interactions(trace);
190 print_trace_stats(trace);
191
192 return trace;
193}
194
196 EventsContainer&& events,
197 const PublicInputs& public_inputs)
198{
199 // We process the events in parallel. Ideally the jobs should access disjoint column sets.
200 {
201 auto jobs = concatenate(
202 // Precomputed column jobs.
203 build_precomputed_columns_jobs(trace),
204 // Public inputs column jobs.
205 build_public_inputs_columns_jobs(trace, public_inputs),
206 // Subtrace jobs.
207 std::vector<std::function<void()>>{
208 [&]() {
209 TxTraceBuilder tx_builder;
210 AVM_TRACK_TIME("tracegen/tx", tx_builder.process(events.tx, trace));
211 clear_events(events.tx);
212 },
213 [&]() {
214 ExecutionTraceBuilder exec_builder;
215 AVM_TRACK_TIME("tracegen/execution", exec_builder.process(events.execution, trace));
216 clear_events(events.execution);
217 },
218 [&]() {
219 AddressDerivationTraceBuilder address_derivation_builder;
220 AVM_TRACK_TIME("tracegen/address_derivation",
221 address_derivation_builder.process(events.address_derivation, trace));
222 clear_events(events.address_derivation);
223 },
224 [&]() {
225 AluTraceBuilder alu_builder;
226 AVM_TRACK_TIME("tracegen/alu", alu_builder.process(events.alu, trace));
227 clear_events(events.alu);
228 },
229 [&]() {
230 BytecodeTraceBuilder bytecode_builder;
231 AVM_TRACK_TIME("tracegen/bytecode_decomposition",
232 bytecode_builder.process_decomposition(events.bytecode_decomposition, trace));
233 clear_events(events.bytecode_decomposition);
234 },
235 [&]() {
236 BytecodeTraceBuilder bytecode_builder;
237 AVM_TRACK_TIME("tracegen/bytecode_hashing",
238 bytecode_builder.process_hashing(events.bytecode_hashing, trace));
239 clear_events(events.bytecode_hashing);
240 },
241 [&]() {
242 ClassIdDerivationTraceBuilder class_id_builder;
243 AVM_TRACK_TIME("tracegen/class_id_derivation",
244 class_id_builder.process(events.class_id_derivation, trace));
245 clear_events(events.class_id_derivation);
246 },
247 [&]() {
248 BytecodeTraceBuilder bytecode_builder;
249 AVM_TRACK_TIME("tracegen/bytecode_retrieval",
250 bytecode_builder.process_retrieval(events.bytecode_retrieval, trace));
251 clear_events(events.bytecode_retrieval);
252 },
253 [&]() {
254 BytecodeTraceBuilder bytecode_builder;
255 AVM_TRACK_TIME("tracegen/instruction_fetching",
256 bytecode_builder.process_instruction_fetching(events.instruction_fetching, trace));
257 clear_events(events.instruction_fetching);
258 },
259 [&]() {
260 Sha256TraceBuilder sha256_builder;
261 AVM_TRACK_TIME("tracegen/sha256_compression",
262 sha256_builder.process(events.sha256_compression, trace));
263 clear_events(events.sha256_compression);
264 },
265 [&]() {
266 KeccakF1600TraceBuilder keccakf1600_builder;
267 AVM_TRACK_TIME("tracegen/keccak_f1600_permutation",
268 keccakf1600_builder.process_permutation(events.keccakf1600, trace));
269 AVM_TRACK_TIME("tracegen/keccak_f1600_memory_slices",
270 keccakf1600_builder.process_memory_slices(events.keccakf1600, trace));
271 clear_events(events.keccakf1600);
272 },
273 [&]() {
274 EccTraceBuilder ecc_builder;
275 AVM_TRACK_TIME("tracegen/ecc_add", ecc_builder.process_add(events.ecc_add, trace));
276 clear_events(events.ecc_add);
277 },
278 [&]() {
279 EccTraceBuilder ecc_builder;
280 AVM_TRACK_TIME("tracegen/scalar_mul", ecc_builder.process_scalar_mul(events.scalar_mul, trace));
281 clear_events(events.scalar_mul);
282 },
283 [&]() {
284 EccTraceBuilder ecc_builder;
285 AVM_TRACK_TIME("tracegen/ecc_add_memory",
286 ecc_builder.process_add_with_memory(events.ecc_add_mem, trace));
287 clear_events(events.ecc_add_mem);
288 },
289 [&]() {
290 Poseidon2TraceBuilder poseidon2_builder;
291 AVM_TRACK_TIME("tracegen/poseidon2_hash",
292 poseidon2_builder.process_hash(events.poseidon2_hash, trace));
293 clear_events(events.poseidon2_hash);
294 },
295 [&]() {
296 Poseidon2TraceBuilder poseidon2_builder;
297 AVM_TRACK_TIME("tracegen/poseidon2_permutation",
298 poseidon2_builder.process_permutation(events.poseidon2_permutation, trace));
299 clear_events(events.poseidon2_permutation);
300 },
301 [&]() {
302 Poseidon2TraceBuilder poseidon2_builder;
304 "tracegen/poseidon2_permutation_with_memory",
305 poseidon2_builder.process_permutation_with_memory(events.poseidon2_permutation_mem, trace));
306 clear_events(events.poseidon2_permutation_mem);
307 },
308 [&]() {
309 ToRadixTraceBuilder to_radix_builder;
310 AVM_TRACK_TIME("tracegen/to_radix", to_radix_builder.process(events.to_radix, trace));
311 clear_events(events.to_radix);
312 },
313 [&]() {
314 ToRadixTraceBuilder to_radix_builder;
315 AVM_TRACK_TIME("tracegen/to_radix_memory",
316 to_radix_builder.process_with_memory(events.to_radix_memory, trace));
317 clear_events(events.to_radix_memory);
318 },
319 [&]() {
321 AVM_TRACK_TIME("tracegen/field_gt", field_gt_builder.process(events.field_gt, trace));
322 clear_events(events.field_gt);
323 },
324 [&]() {
325 MerkleCheckTraceBuilder merkle_check_builder;
326 AVM_TRACK_TIME("tracegen/merkle_check", merkle_check_builder.process(events.merkle_check, trace));
327 clear_events(events.merkle_check);
328 },
329 [&]() {
331 AVM_TRACK_TIME("tracegen/range_check", range_check_builder.process(events.range_check, trace));
332 clear_events(events.range_check);
333 },
334 [&]() {
335 PublicDataTreeTraceBuilder public_data_tree_trace_builder;
336 AVM_TRACK_TIME("tracegen/public_data_tree_check",
337 public_data_tree_trace_builder.process(events.public_data_tree_check_events, trace));
338 clear_events(events.public_data_tree_check_events);
339 },
340 [&]() {
341 UpdateCheckTraceBuilder update_check_trace_builder;
342 AVM_TRACK_TIME("tracegen/update_check",
343 update_check_trace_builder.process(events.update_check_events, trace));
344 clear_events(events.update_check_events);
345 },
346 [&]() {
347 NullifierTreeCheckTraceBuilder nullifier_tree_check_trace_builder;
349 "tracegen/nullifier_tree_check",
350 nullifier_tree_check_trace_builder.process(events.nullifier_tree_check_events, trace));
351 clear_events(events.nullifier_tree_check_events);
352 },
353 [&]() {
354 MemoryTraceBuilder memory_trace_builder;
355 AVM_TRACK_TIME("tracegen/memory", memory_trace_builder.process(events.memory, trace));
356 clear_events(events.memory);
357 },
358 [&]() {
359 DataCopyTraceBuilder data_copy_trace_builder;
360 AVM_TRACK_TIME("tracegen/data_copy",
361 data_copy_trace_builder.process(events.data_copy_events, trace));
362 clear_events(events.data_copy_events);
363 },
364 [&]() {
365 BitwiseTraceBuilder bitwise_builder;
366 AVM_TRACK_TIME("tracegen/bitwise", bitwise_builder.process(events.bitwise, trace));
367 clear_events(events.bitwise);
368 },
369 [&]() {
370 CalldataTraceBuilder calldata_builder;
371 AVM_TRACK_TIME("tracegen/calldata_hashing",
372 calldata_builder.process_hashing(events.calldata_events, trace));
373 AVM_TRACK_TIME("tracegen/calldata_retrieval",
374 calldata_builder.process_retrieval(events.calldata_events, trace));
375 clear_events(events.calldata_events);
376 },
377 [&]() {
378 InternalCallStackBuilder internal_call_stack_builder;
379 AVM_TRACK_TIME("tracegen/internal_call_stack",
380 internal_call_stack_builder.process(events.internal_call_stack_events, trace));
381 clear_events(events.internal_call_stack_events);
382 },
383 [&]() {
384 ContextStackTraceBuilder context_stack_builder;
385 AVM_TRACK_TIME("tracegen/context_stack",
386 context_stack_builder.process(events.context_stack, trace));
387 clear_events(events.context_stack);
388 },
389 [&]() {
390 NoteHashTreeCheckTraceBuilder note_hash_tree_check_trace_builder;
392 "tracegen/note_hash_tree_check",
393 note_hash_tree_check_trace_builder.process(events.note_hash_tree_check_events, trace));
394 clear_events(events.note_hash_tree_check_events);
395 },
396 [&]() {
397 WrittenPublicDataSlotsTreeCheckTraceBuilder written_public_data_slots_tree_check_trace_builder;
398 AVM_TRACK_TIME("tracegen/written_public_data_slots_tree_check",
399 written_public_data_slots_tree_check_trace_builder.process(
400 events.written_public_data_slots_tree_check_events, trace));
401 clear_events(events.written_public_data_slots_tree_check_events);
402 },
403 [&]() {
405 AVM_TRACK_TIME("tracegen/gt", gt_builder.process(events.gt_events, trace));
406 clear_events(events.gt_events);
407 },
408 [&]() {
409 ContractInstanceRetrievalTraceBuilder contract_instance_retrieval_builder;
411 "tracegen/contract_instance_retrieval",
412 contract_instance_retrieval_builder.process(events.contract_instance_retrieval_events, trace));
413 clear_events(events.contract_instance_retrieval_events);
414 },
415 [&]() {
416 GetContractInstanceTraceBuilder get_contract_instance_builder;
417 AVM_TRACK_TIME("tracegen/get_contract_instance",
418 get_contract_instance_builder.process(events.get_contract_instance_events, trace));
419 clear_events(events.get_contract_instance_events);
420 },
421 [&]() {
422 L1ToL2MessageTreeCheckTraceBuilder l1_to_l2_message_tree_check_trace_builder;
423 AVM_TRACK_TIME("tracegen/l1_to_l2_message_tree_check",
424 l1_to_l2_message_tree_check_trace_builder.process(
425 events.l1_to_l2_msg_tree_check_events, trace));
426 clear_events(events.l1_to_l2_msg_tree_check_events);
427 },
428 [&]() {
429 EmitUnencryptedLogTraceBuilder emit_unencrypted_log_builder;
430 AVM_TRACK_TIME("tracegen/emit_unencrypted_log",
431 emit_unencrypted_log_builder.process(events.emit_unencrypted_log_events, trace));
432 clear_events(events.emit_unencrypted_log_events);
433 } });
434
435 AVM_TRACK_TIME("tracegen/traces", execute_jobs(jobs));
436 }
437}
438
440{
441 // Now we can compute lookups and permutations.
442 {
443 auto jobs_interactions =
445 TxTraceBuilder::interactions.get_all_jobs(),
447 AluTraceBuilder::interactions.get_all_jobs(),
455 EccTraceBuilder::interactions.get_all_jobs(),
472
473 AVM_TRACK_TIME("tracegen/interactions",
474 parallel_for(jobs_interactions.size(), [&](size_t i) { jobs_interactions[i]->process(trace); }));
475 }
476}
477
479{
481 auto jobs = build_precomputed_columns_jobs(trace);
482 execute_jobs(jobs);
483 return trace;
484}
485
486} // namespace bb::avm2
void fill_trace_columns(tracegen::TraceContainer &trace, simulation::EventsContainer &&events, const PublicInputs &public_inputs)
tracegen::TraceContainer generate_trace(simulation::EventsContainer &&events, const PublicInputs &public_inputs)
void fill_trace_interactions(tracegen::TraceContainer &trace)
tracegen::TraceContainer generate_precomputed_columns()
void process(const simulation::EventEmitterInterface< simulation::AddressDerivationEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
Definition alu_trace.hpp:16
void process(const simulation::EventEmitterInterface< simulation::AluEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::BitwiseEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_retrieval(const simulation::EventEmitterInterface< simulation::BytecodeRetrievalEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_decomposition(const simulation::EventEmitterInterface< simulation::BytecodeDecompositionEvent >::Container &events, TraceContainer &trace)
void process_hashing(const simulation::EventEmitterInterface< simulation::BytecodeHashingEvent >::Container &events, TraceContainer &trace)
void process_instruction_fetching(const simulation::EventEmitterInterface< simulation::InstructionFetchingEvent >::Container &events, TraceContainer &trace)
void process_hashing(const simulation::EventEmitterInterface< simulation::CalldataEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_retrieval(const simulation::EventEmitterInterface< simulation::CalldataEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::ClassIdDerivationEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::ContextStackEvent >::Container &ctx_stack_events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::ContractInstanceRetrievalEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::DataCopyEvent >::Container &events, TraceContainer &trace)
void process_add_with_memory(const simulation::EventEmitterInterface< simulation::EccAddMemoryEvent >::Container &events, TraceContainer &trace)
void process_add(const simulation::EventEmitterInterface< simulation::EccAddEvent >::Container &events, TraceContainer &trace)
Definition ecc_trace.cpp:51
void process_scalar_mul(const simulation::EventEmitterInterface< simulation::ScalarMulEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
Definition ecc_trace.hpp:23
void process(const simulation::EventEmitterInterface< simulation::EmitUnencryptedLogEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::ExecutionEvent >::Container &ex_events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::GetContractInstanceEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
Definition gt_trace.hpp:18
void process(const simulation::EventEmitterInterface< simulation::InternalCallStackEvent >::Container &events, TraceContainer &trace)
void process_memory_slices(const simulation::EventEmitterInterface< simulation::KeccakF1600Event >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_permutation(const simulation::EventEmitterInterface< simulation::KeccakF1600Event >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::L1ToL2MessageTreeCheckEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::MemoryEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::MerkleCheckEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::NoteHashTreeCheckEvent >::Container &events, TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::NullifierTreeCheckEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_permutation(const simulation::EventEmitterInterface< simulation::Poseidon2PermutationEvent >::Container &perm_events, TraceContainer &trace)
void process_permutation_with_memory(const simulation::EventEmitterInterface< simulation::Poseidon2PermutationMemoryEvent >::Container &perm_mem_events, TraceContainer &trace)
void process_hash(const simulation::EventEmitterInterface< simulation::Poseidon2HashEvent >::Container &hash_events, TraceContainer &trace)
void process_sha256_round_constants(TraceContainer &trace)
void process_to_radix_p_decompositions(TraceContainer &trace)
void process_wire_instruction_spec(TraceContainer &trace)
void process_keccak_round_constants(TraceContainer &trace)
void process_to_radix_safe_limbs(TraceContainer &trace)
void process_memory_tag_range(TraceContainer &trace)
void process_exec_instruction_spec(TraceContainer &trace)
void process_misc(TraceContainer &trace, const uint32_t num_rows=MAX_AVM_TRACE_SIZE)
void process_get_env_var_table(TraceContainer &trace)
void process_get_contract_instance_table(TraceContainer &trace)
void process(const simulation::EventEmitterInterface< simulation::PublicDataTreeCheckEvent >::Container &events, TraceContainer &trace)
void process_public_inputs(TraceContainer &trace, const PublicInputs &public_inputs)
void process_public_inputs_aux_precomputed(TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::Sha256CompressionEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::ToRadixEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process_with_memory(const simulation::EventEmitterInterface< simulation::ToRadixMemoryEvent >::Container &events, TraceContainer &trace)
static constexpr size_t num_columns()
uint32_t get_column_rows(Column col) const
void process(const simulation::EventEmitterInterface< simulation::TxEvent >::Container &events, TraceContainer &trace)
Definition tx_trace.cpp:469
static const InteractionDefinition interactions
Definition tx_trace.hpp:19
void process(const simulation::EventEmitterInterface< simulation::UpdateCheckEvent >::Container &events, TraceContainer &trace)
static const InteractionDefinition interactions
void process(const simulation::EventEmitterInterface< simulation::WrittenPublicDataSlotsTreeCheckEvent >::Container &events, TraceContainer &trace)
void vinfo(Args... args)
Definition log.hpp:76
void info(Args... args)
Definition log.hpp:70
RangeCheckTraceBuilder range_check_builder
Definition alu.test.cpp:120
PrecomputedTraceBuilder precomputed_builder
Definition alu.test.cpp:119
FieldGreaterThanTraceBuilder field_gt_builder
Definition alu.test.cpp:121
GreaterThanTraceBuilder gt_builder
Definition alu.test.cpp:122
TestTraceContainer trace
std::vector< T > concatenate_jobs(std::vector< T > &&first, auto &&... rest)
const std::vector< std::string > & COLUMN_NAMES
Definition columns.hpp:49
::ankerl::unordered_dense::map< Key, T > unordered_flat_map
Definition map.hpp:15
constexpr T get_msb(const T in)
Definition get_msb.hpp:47
constexpr T round_up_power_2(const T in)
Definition get_msb.hpp:52
RefArray< T,(Ns+...)> constexpr concatenate(const RefArray< T, Ns > &... ref_arrays)
Concatenates multiple RefArray objects into a single RefArray.
void parallel_for(size_t num_iterations, const std::function< void(size_t)> &func)
Definition thread.cpp:72
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
#define AVM_TRACK_TIME(key, body)
Definition stats.hpp:17