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
15#include <memory.h>
16#include <memory>
17
18namespace bb {
19
20namespace {
21constexpr size_t MIN_GROUP_PER_THREAD = 4;
22
23size_t compute_num_threads(const size_t size)
24{
25 size_t num_threads = get_num_cpus_pow2();
26 if (size <= (num_threads * MIN_GROUP_PER_THREAD)) {
27 num_threads = 1;
28 }
29
30 return num_threads;
31}
32
33template <typename Fr>
34void compute_lookup_table_single(const Fr& input_root,
35 const size_t size,
36 Fr* const roots,
37 std::vector<Fr*>& round_roots)
38{
39 const size_t num_rounds = static_cast<size_t>(numeric::get_msb(size));
40
41 round_roots.emplace_back(&roots[0]);
42 for (size_t i = 1; i < num_rounds - 1; ++i) {
43 round_roots.emplace_back(round_roots.back() + (1UL << i));
44 }
45
46 for (size_t i = 0; i < num_rounds - 1; ++i) {
47 const size_t m = 1UL << (i + 1);
48 const Fr round_root = input_root.pow(static_cast<uint64_t>(size / (2 * m)));
49 Fr* const current_round_roots = round_roots[i];
50 current_round_roots[0] = Fr::one();
51 for (size_t j = 1; j < m; ++j) {
52 current_round_roots[j] = current_round_roots[j - 1] * round_root;
53 }
54 }
55}
56} // namespace
57
58template <typename Fr>
59EvaluationDomain<Fr>::EvaluationDomain(const size_t domain_size, const size_t target_generator_size)
60 : size(domain_size)
61 , num_threads(compute_num_threads(domain_size))
62 , thread_size(domain_size / num_threads)
63 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
64 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
65 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
66 , generator_size(target_generator_size ? target_generator_size : domain_size)
67 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
68 , domain_inverse(domain.invert())
69 , generator(Fr::template coset_generator<0>())
70 , generator_inverse(Fr::template coset_generator<0>().invert())
71 , four_inverse(Fr(4).invert())
72 , roots(nullptr)
73{
74 // Grumpkin does not have many roots of unity and, given these are not used for Honk, we set it to one.
76 root = Fr::one();
77 } else {
79 }
80
81 root_inverse = root.invert();
82
83 ASSERT((1UL << log2_size) == size || (size == 0));
84 ASSERT((1UL << log2_thread_size) == thread_size || (size == 0));
85 ASSERT((1UL << log2_num_threads) == num_threads || (size == 0));
86}
87
88template <typename Fr>
90 : size(other.size)
91 , num_threads(compute_num_threads(other.size))
92 , thread_size(other.size / num_threads)
93 , log2_size(static_cast<size_t>(numeric::get_msb(size)))
94 , log2_thread_size(static_cast<size_t>(numeric::get_msb(thread_size)))
95 , log2_num_threads(static_cast<size_t>(numeric::get_msb(num_threads)))
96 , generator_size(other.generator_size)
97 , root(Fr::get_root_of_unity(log2_size))
98 , root_inverse(root.invert())
99 , domain(Fr{ size, 0, 0, 0 }.to_montgomery_form())
100 , domain_inverse(domain.invert())
101 , generator(other.generator)
102 , generator_inverse(other.generator_inverse)
103 , four_inverse(other.four_inverse)
104{
105 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(Fr::get_root_of_unity(log2_size))
135 , root_inverse(root.invert())
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 , four_inverse(other.four_inverse)
141{
142 roots = other.roots;
143 round_roots = std::move(other.round_roots);
144 inverse_round_roots = std::move(other.inverse_round_roots);
145 other.roots = nullptr;
146}
147
149{
150 size = other.size;
151 generator_size = other.generator_size;
152 num_threads = compute_num_threads(other.size);
153 thread_size = other.size / num_threads;
154 log2_size = static_cast<size_t>(numeric::get_msb(size));
155 log2_thread_size = static_cast<size_t>(numeric::get_msb(thread_size));
156 log2_num_threads = static_cast<size_t>(numeric::get_msb(num_threads));
157 Fr::__copy(other.root, root);
158 Fr::__copy(other.root_inverse, root_inverse);
159 Fr::__copy(other.domain, domain);
160 Fr::__copy(other.domain_inverse, domain_inverse);
161 Fr::__copy(other.generator, generator);
162 Fr::__copy(other.generator_inverse, generator_inverse);
163 Fr::__copy(other.four_inverse, four_inverse);
164 roots = nullptr;
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 = (Fr*)(aligned_alloc(32, sizeof(Fr) * size * 2));
180 roots = std::static_pointer_cast<Fr[]>(get_mem_slab(sizeof(Fr) * size * 2));
181 compute_lookup_table_single(root, size, roots.get(), round_roots);
182 compute_lookup_table_single(root_inverse, size, &roots.get()[size], inverse_round_roots);
183}
184
185// explicitly instantiate both EvaluationDomain
186template class EvaluationDomain<bb::fr>;
187template class EvaluationDomain<grumpkin::fr>;
188
189} // namespace bb
#define BB_ASSERT_EQ(actual, expected,...)
Definition assert.hpp:59
#define ASSERT(expression,...)
Definition assert.hpp:49
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.
size_t get_num_cpus_pow2()
Definition thread.hpp:18
std::shared_ptr< void > get_mem_slab(size_t size)
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
static BB_INLINE void __copy(const field &a, field &r) noexcept