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
89template <typename Fr>
91 : size(other.size)
92 , num_threads(compute_num_threads(other.size))
93 , thread_size(other.size / num_threads)
94 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
95 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
96 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
97 , generator_size(other.generator_size)
98 , root(other.root)
99 , root_inverse(other.root_inverse)
100 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
101 , domain_inverse(domain.invert())
102 , generator(other.generator)
103 , generator_inverse(other.generator_inverse)
104{
105 BB_ASSERT((1UL << log2_size) == size);
108 if (other.roots != nullptr) {
109 const size_t mem_size = sizeof(Fr) * size * 2;
111 memcpy(static_cast<void*>(roots.get()), static_cast<void*>(other.roots.get()), mem_size);
112 round_roots.resize(log2_size - 1);
113 inverse_round_roots.resize(log2_size - 1);
114 round_roots[0] = &roots[0];
115 inverse_round_roots[0] = &roots.get()[size];
116 for (size_t i = 1; i < log2_size - 1; ++i) {
117 round_roots[i] = round_roots[i - 1] + (1UL << i);
118 inverse_round_roots[i] = inverse_round_roots[i - 1] + (1UL << i);
119 }
120 } else {
121 roots = nullptr;
122 }
123}
124
125template <typename Fr>
127 : size(other.size)
128 , num_threads(compute_num_threads(other.size))
129 , thread_size(other.size / num_threads)
130 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
131 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
132 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
133 , generator_size(other.generator_size)
134 , root(other.root)
135 , root_inverse(other.root_inverse)
136 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
137 , domain_inverse(domain.invert())
138 , generator(other.generator)
139 , generator_inverse(other.generator_inverse)
140{
141 roots = other.roots;
142 round_roots = std::move(other.round_roots);
143 inverse_round_roots = std::move(other.inverse_round_roots);
144 other.roots = nullptr;
145}
146
148{
149 size = other.size;
150 generator_size = other.generator_size;
151 num_threads = compute_num_threads(other.size);
152 thread_size = other.size / num_threads;
153 log2_size = static_cast<size_t>(numeric::get_msb(size));
154 log2_thread_size = static_cast<size_t>(numeric::get_msb(thread_size));
155 log2_num_threads = static_cast<size_t>(numeric::get_msb(num_threads));
156 Fr::__copy(other.root, root);
157 Fr::__copy(other.root_inverse, root_inverse);
158 Fr::__copy(other.domain, domain);
159 Fr::__copy(other.domain_inverse, domain_inverse);
160 Fr::__copy(other.generator, generator);
161 Fr::__copy(other.generator_inverse, generator_inverse);
162 roots = nullptr;
163 round_roots.clear();
164 inverse_round_roots.clear();
165 if (other.roots != nullptr) {
166 roots = other.roots;
167 round_roots = std::move(other.round_roots);
168 inverse_round_roots = std::move(other.inverse_round_roots);
169 }
170 other.roots = nullptr;
171 return *this;
172}
173
175
177{
178 BB_ASSERT_EQ(roots, nullptr);
179 roots = std::make_shared<Fr[]>(size * 2);
180 compute_lookup_table_single(root, size, roots.get(), round_roots);
181 compute_lookup_table_single(root_inverse, size, &roots.get()[size], inverse_round_roots);
182}
183
184// explicitly instantiate both EvaluationDomain
185template class EvaluationDomain<bb::fr>;
186template class EvaluationDomain<grumpkin::fr>;
187
188} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:70
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:83
std::vector< FF * > inverse_round_roots
std::vector< FF * > round_roots
EvaluationDomain & operator=(const EvaluationDomain &)=delete
std::shared_ptr< FF[]> roots
constexpr T get_msb(const T in)
Definition get_msb.hpp:49
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
Curve::ScalarField Fr
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