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: not started, auditors: [], date: YYYY-MM-DD }
3// external_1: { status: not started, auditors: [], date: YYYY-MM-DD }
4// external_2: { status: not started, auditors: [], date: YYYY-MM-DD }
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 const size_t num_rounds = static_cast<size_t>(numeric::get_msb(size));
39
40 round_roots.emplace_back(&roots[0]);
41 for (size_t i = 1; i < num_rounds - 1; ++i) {
42 round_roots.emplace_back(round_roots.back() + (1UL << i));
43 }
44
45 for (size_t i = 0; i < num_rounds - 1; ++i) {
46 const size_t m = 1UL << (i + 1);
47 const Fr round_root = input_root.pow(static_cast<uint64_t>(size / (2 * m)));
48 Fr* const current_round_roots = round_roots[i];
49 current_round_roots[0] = Fr::one();
50 for (size_t j = 1; j < m; ++j) {
51 current_round_roots[j] = current_round_roots[j - 1] * round_root;
52 }
53 }
54}
55} // namespace
56
57template <typename Fr>
58EvaluationDomain<Fr>::EvaluationDomain(const size_t domain_size, const size_t target_generator_size)
59 : size(domain_size)
60 , num_threads(compute_num_threads(domain_size))
61 , thread_size(domain_size / num_threads)
62 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
63 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
64 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
65 , generator_size(target_generator_size ? target_generator_size : domain_size)
66 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
67 , domain_inverse(domain.invert())
68 , generator(Fr::template coset_generator<0>())
69 , generator_inverse(Fr::template coset_generator<0>().invert())
70 , four_inverse(Fr(4).invert())
71 , roots(nullptr)
72{
73 // Grumpkin does not have many roots of unity and, given these are not used for Honk, we set it to one.
75 root = Fr::one();
76 } else {
78 }
79
81
82 BB_ASSERT((1UL << log2_size) == size || (size == 0));
83 BB_ASSERT((1UL << log2_thread_size) == thread_size || (size == 0));
84 BB_ASSERT((1UL << log2_num_threads) == num_threads || (size == 0));
85}
86
87template <typename Fr>
89 : size(other.size)
90 , num_threads(compute_num_threads(other.size))
91 , thread_size(other.size / num_threads)
92 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
93 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
94 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
95 , generator_size(other.generator_size)
96 , root(Fr::get_root_of_unity(log2_size))
97 , root_inverse(root.invert())
98 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
99 , domain_inverse(domain.invert())
100 , generator(other.generator)
101 , generator_inverse(other.generator_inverse)
102 , four_inverse(other.four_inverse)
103{
104 BB_ASSERT((1UL << log2_size) == size);
107 if (other.roots != nullptr) {
108 const size_t mem_size = sizeof(Fr) * size * 2;
110 memcpy(static_cast<void*>(roots.get()), static_cast<void*>(other.roots.get()), mem_size);
111 round_roots.resize(log2_size - 1);
112 inverse_round_roots.resize(log2_size - 1);
113 round_roots[0] = &roots[0];
114 inverse_round_roots[0] = &roots.get()[size];
115 for (size_t i = 1; i < log2_size - 1; ++i) {
116 round_roots[i] = round_roots[i - 1] + (1UL << i);
117 inverse_round_roots[i] = inverse_round_roots[i - 1] + (1UL << i);
118 }
119 } else {
120 roots = nullptr;
121 }
122}
123
124template <typename Fr>
126 : size(other.size)
127 , num_threads(compute_num_threads(other.size))
128 , thread_size(other.size / num_threads)
129 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
130 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
131 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
132 , generator_size(other.generator_size)
133 , root(Fr::get_root_of_unity(log2_size))
134 , root_inverse(root.invert())
135 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
136 , domain_inverse(domain.invert())
137 , generator(other.generator)
138 , generator_inverse(other.generator_inverse)
139 , four_inverse(other.four_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 Fr::__copy(other.four_inverse, four_inverse);
163 roots = nullptr;
164 if (other.roots != nullptr) {
165 roots = other.roots;
166 round_roots = std::move(other.round_roots);
167 inverse_round_roots = std::move(other.inverse_round_roots);
168 }
169 other.roots = nullptr;
170 return *this;
171}
172
174
176{
177 BB_ASSERT_EQ(roots, nullptr);
178 roots = std::make_shared<Fr[]>(size * 2);
179 compute_lookup_table_single(root, size, roots.get(), round_roots);
180 compute_lookup_table_single(root_inverse, size, &roots.get()[size], inverse_round_roots);
181}
182
183// explicitly instantiate both EvaluationDomain
184template class EvaluationDomain<bb::fr>;
185template class EvaluationDomain<grumpkin::fr>;
186
187} // namespace bb
#define BB_ASSERT(expression,...)
Definition assert.hpp:67
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:77
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:47
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