Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
evaluation_domain.cpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Nishat], commit: 94f596f8b3bbbc216f9ad7dc33253256141156b2 }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
14#include <memory.h>
15#include <memory>
16
17namespace bb {
18
19namespace {
20constexpr size_t MIN_GROUP_PER_THREAD = 4;
21
22size_t compute_num_threads(const size_t size)
23{
24 size_t num_threads = get_num_cpus_pow2();
25 if (size <= (num_threads * MIN_GROUP_PER_THREAD)) {
26 num_threads = 1;
27 }
28
29 return num_threads;
30}
31
32template <typename Fr>
33void compute_lookup_table_single(const Fr& input_root,
34 const size_t size,
35 Fr* const roots,
36 std::vector<Fr*>& round_roots)
37{
38 // num_rounds = 0 results in underflow in the loop below, so we require num_rounds >= 1, which is equivalent to size
39 // >= 2.
40 BB_ASSERT(size >= 2);
41 const size_t num_rounds = static_cast<size_t>(numeric::get_msb(size));
42
43 round_roots.emplace_back(&roots[0]);
44 for (size_t i = 1; i < num_rounds - 1; ++i) {
45 round_roots.emplace_back(round_roots.back() + (1UL << i));
46 }
47
48 for (size_t i = 0; i < num_rounds - 1; ++i) {
49 const size_t m = 1UL << (i + 1);
50 const Fr round_root = input_root.pow(static_cast<uint64_t>(size / (2 * m)));
51 Fr* const current_round_roots = round_roots[i];
52 current_round_roots[0] = Fr::one();
53 for (size_t j = 1; j < m; ++j) {
54 current_round_roots[j] = current_round_roots[j - 1] * round_root;
55 }
56 }
57}
58} // namespace
59
60template <typename Fr>
61EvaluationDomain<Fr>::EvaluationDomain(const size_t domain_size, const size_t target_generator_size)
62 : size(domain_size)
63 , num_threads(compute_num_threads(domain_size))
64 , thread_size(domain_size / num_threads)
65 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
66 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
67 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
68 , generator_size(target_generator_size ? target_generator_size : domain_size)
69 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
70 , domain_inverse(domain.invert())
71 , generator(Fr::coset_generator())
72 , generator_inverse(Fr::coset_generator().invert())
73 , roots(nullptr)
74{
75 // Grumpkin does not have many roots of unity and, given these are not used for Honk, we set it to one.
77 root = Fr::one();
78 } else {
80 }
81
83
84 BB_ASSERT((1UL << log2_size) == size || (size == 0));
85 BB_ASSERT((1UL << log2_thread_size) == thread_size || (size == 0));
86 BB_ASSERT((1UL << log2_num_threads) == num_threads || (size == 0));
87}
88
90{
91 // Prevent self-corruption of data
92 if (this == &other) {
93 return *this;
94 }
95 // Steal-and-zero the source's invariant-gating scalar fields. All validity checks on an
96 // EvaluationDomain gate on `size > 0`, so zeroing it on move makes the source visibly empty
97 // (matching the default-constructed state) rather than partially valid (size > 0 but
98 // roots == nullptr).
99 size = std::exchange(other.size, 0);
100 generator_size = std::exchange(other.generator_size, 0);
101 num_threads = std::exchange(other.num_threads, 0);
102 thread_size = std::exchange(other.thread_size, 0);
103 log2_size = std::exchange(other.log2_size, 0);
104 log2_thread_size = std::exchange(other.log2_thread_size, 0);
105 log2_num_threads = std::exchange(other.log2_num_threads, 0);
106 Fr::__copy(other.root, root);
107 Fr::__copy(other.root_inverse, root_inverse);
108 Fr::__copy(other.domain, domain);
109 Fr::__copy(other.domain_inverse, domain_inverse);
110 Fr::__copy(other.generator, generator);
111 Fr::__copy(other.generator_inverse, generator_inverse);
112 roots = std::move(other.roots);
113 round_roots = std::move(other.round_roots);
114 inverse_round_roots = std::move(other.inverse_round_roots);
115 other.roots = nullptr;
116 return *this;
117}
118
120
122{
123 BB_ASSERT_EQ(roots, nullptr);
124 roots = std::make_shared<Fr[]>(size * 2);
125 compute_lookup_table_single(root, size, roots.get(), round_roots);
126 compute_lookup_table_single(root_inverse, size, &roots.get()[size], inverse_round_roots);
127}
128
129// explicitly instantiate both EvaluationDomain
130template class EvaluationDomain<bb::fr>;
131template class EvaluationDomain<grumpkin::fr>;
132
133} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
EvaluationDomain & operator=(const EvaluationDomain &)=delete
constexpr T get_msb(const T in)
Definition get_msb.hpp:50
Entry point for Barretenberg command-line interface.
Definition api.hpp:5
size_t get_num_cpus_pow2()
Definition thread.hpp:25
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
static constexpr field get_root_of_unity(size_t subgroup_size) noexcept
static constexpr field one()
BB_INLINE constexpr field pow(const uint256_t &exponent) const noexcept
constexpr field invert() const noexcept
static BB_INLINE void __copy(const field &a, field &r) noexcept