barretenberg
Loading...
Searching...
No Matches
field_declarations.hpp
1#pragma once
2#include "barretenberg/common/assert.hpp"
3#include "barretenberg/common/compiler_hints.hpp"
4#include "barretenberg/numeric/random/engine.hpp"
5#include "barretenberg/numeric/uint128/uint128.hpp"
6#include "barretenberg/numeric/uint256/uint256.hpp"
7#include <array>
8#include <cstdint>
9#include <iostream>
10#include <random>
11#include <span>
12
13#ifndef DISABLE_SHENANIGANS
14#ifdef __BMI2__
15#define BBERG_NO_ASM 0
16#else
17#define BBERG_NO_ASM 1
18#endif
19#else
20#define BBERG_NO_ASM 1
21#endif
22
23namespace barretenberg {
24template <class Params_> struct alignas(32) field {
25 public:
26 using View = field;
27 using Params = Params_;
28 using in_buf = const uint8_t*;
29 using vec_in_buf = const uint8_t*;
30 using out_buf = uint8_t*;
31 using vec_out_buf = uint8_t**;
32
33 // We don't initialize data in the default constructor since we'd lose a lot of time on huge array initializations.
34 // Other alternatives have been noted, such as casting to get around constructors where they matter,
35 // however it is felt that sanitizer tools (e.g. MSAN) can detect garbage well, whereas doing
36 // hacky casts where needed would require rework to critical algos like MSM, FFT, Sumcheck.
37 // Instead, the recommended solution is use an explicit {} where initialization is important:
38 // field f; // not initialized
39 // field f{}; // zero-initialized
40 // std::array<field, N> arr; // not initialized, good for huge N
41 // std::array<field, N> arr {}; // zero-initialized, preferable for moderate N
42 field() = default;
43
44 constexpr field(const numeric::uint256_t& input) noexcept
45 : data{ input.data[0], input.data[1], input.data[2], input.data[3] }
46 {
47 self_to_montgomery_form();
48 }
49
50 // NOLINTNEXTLINE (unsigned long is platform dependent, which we want in this case)
51 constexpr field(const unsigned long input) noexcept
52 : data{ input, 0, 0, 0 }
53 {
54 self_to_montgomery_form();
55 }
56
57 constexpr field(const unsigned int input) noexcept
58 : data{ input, 0, 0, 0 }
59 {
60 self_to_montgomery_form();
61 }
62
63 // NOLINTNEXTLINE (unsigned long long is platform dependent, which we want in this case)
64 constexpr field(const unsigned long long input) noexcept
65 : data{ input, 0, 0, 0 }
66 {
67 self_to_montgomery_form();
68 }
69
70 constexpr field(const int input) noexcept
71 : data{ 0, 0, 0, 0 }
72 {
73 if (input < 0) {
74 data[0] = static_cast<uint64_t>(-input);
75 data[1] = 0;
76 data[2] = 0;
77 data[3] = 0;
78 self_to_montgomery_form();
79 self_neg();
80 self_reduce_once();
81 } else {
82 data[0] = static_cast<uint64_t>(input);
83 data[1] = 0;
84 data[2] = 0;
85 data[3] = 0;
86 self_to_montgomery_form();
87 }
88 }
89
90 constexpr field(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
91 : data{ a, b, c, d } {};
92
99 constexpr explicit field(const uint512_t& input) noexcept
100 {
101 uint256_t value = (input % modulus).lo;
102 data[0] = value.data[0];
103 data[1] = value.data[1];
104 data[2] = value.data[2];
105 data[3] = value.data[3];
106 self_to_montgomery_form();
107 }
108
109 constexpr explicit field(std::string input) noexcept
110 {
111 uint256_t value(input);
112 *this = field(value);
113 }
114
115 constexpr explicit operator uint32_t() const
116 {
117 field out = from_montgomery_form();
118 return static_cast<uint32_t>(out.data[0]);
119 }
120
121 constexpr explicit operator uint64_t() const
122 {
123 field out = from_montgomery_form();
124 return out.data[0];
125 }
126
127 constexpr explicit operator uint128_t() const
128 {
129 field out = from_montgomery_form();
130 uint128_t lo = out.data[0];
131 uint128_t hi = out.data[1];
132 return (hi << 64) | lo;
133 }
134
135 constexpr operator uint256_t() const noexcept
136 {
137 field out = from_montgomery_form();
138 return uint256_t(out.data[0], out.data[1], out.data[2], out.data[3]);
139 }
140
141 [[nodiscard]] constexpr uint256_t uint256_t_no_montgomery_conversion() const noexcept
142 {
143 return { data[0], data[1], data[2], data[3] };
144 }
145
146 constexpr field(const field& other) noexcept = default;
147 constexpr field(field&& other) noexcept = default;
148 constexpr field& operator=(const field& other) noexcept = default;
149 constexpr field& operator=(field&& other) noexcept = default;
150 constexpr ~field() noexcept = default;
151 alignas(32) uint64_t data[4]; // NOLINT
152
153 static constexpr uint256_t modulus =
154 uint256_t{ Params::modulus_0, Params::modulus_1, Params::modulus_2, Params::modulus_3 };
155
156 static constexpr field cube_root_of_unity()
157 {
158 // endomorphism i.e. lambda * [P] = (beta * x, y)
159 if constexpr (Params::cube_root_0 != 0) {
160 constexpr field result{
161 Params::cube_root_0, Params::cube_root_1, Params::cube_root_2, Params::cube_root_3
162 };
163 return result;
164 } else {
165 constexpr field two_inv = field(2).invert();
166 constexpr field numerator = (-field(3)).sqrt() - field(1);
167 constexpr field result = two_inv * numerator;
168 return result;
169 }
170 }
171
172 static constexpr field zero() { return field(0, 0, 0, 0); }
173 static constexpr field neg_one() { return -field(1); }
174 static constexpr field one() { return field(1); }
175
176 static constexpr field external_coset_generator()
177 {
178 const field result{
179 Params::coset_generators_0[7],
180 Params::coset_generators_1[7],
181 Params::coset_generators_2[7],
182 Params::coset_generators_3[7],
183 };
184 return result;
185 }
186
187 static constexpr field tag_coset_generator()
188 {
189 const field result{
190 Params::coset_generators_0[6],
191 Params::coset_generators_1[6],
192 Params::coset_generators_2[6],
193 Params::coset_generators_3[6],
194 };
195 return result;
196 }
197
198 static constexpr field coset_generator(const size_t idx)
199 {
200 ASSERT(idx < 7);
201 const field result{
202 Params::coset_generators_0[idx],
203 Params::coset_generators_1[idx],
204 Params::coset_generators_2[idx],
205 Params::coset_generators_3[idx],
206 };
207 return result;
208 }
209
210 BBERG_INLINE constexpr field operator*(const field& other) const noexcept;
211 BBERG_INLINE constexpr field operator+(const field& other) const noexcept;
212 BBERG_INLINE constexpr field operator-(const field& other) const noexcept;
213 BBERG_INLINE constexpr field operator-() const noexcept;
214 constexpr field operator/(const field& other) const noexcept;
215
216 // prefix increment (++x)
217 BBERG_INLINE constexpr field operator++() noexcept;
218 // postfix increment (x++)
219 // NOLINTNEXTLINE
220 BBERG_INLINE constexpr field operator++(int) noexcept;
221
222 BBERG_INLINE constexpr field& operator*=(const field& other) noexcept;
223 BBERG_INLINE constexpr field& operator+=(const field& other) noexcept;
224 BBERG_INLINE constexpr field& operator-=(const field& other) noexcept;
225 constexpr field& operator/=(const field& other) noexcept;
226
227 // NOTE: comparison operators exist so that `field` is comparible with stl methods that require them.
228 // (e.g. std::sort)
229 // Finite fields do not have an explicit ordering, these should *NEVER* be used in algebraic algorithms.
230 BBERG_INLINE constexpr bool operator>(const field& other) const noexcept;
231 BBERG_INLINE constexpr bool operator<(const field& other) const noexcept;
232 BBERG_INLINE constexpr bool operator==(const field& other) const noexcept;
233 BBERG_INLINE constexpr bool operator!=(const field& other) const noexcept;
234
235 BBERG_INLINE constexpr field to_montgomery_form() const noexcept;
236 BBERG_INLINE constexpr field from_montgomery_form() const noexcept;
237
238 BBERG_INLINE constexpr field sqr() const noexcept;
239 BBERG_INLINE constexpr void self_sqr() noexcept;
240
241 BBERG_INLINE constexpr field pow(const uint256_t& exponent) const noexcept;
242 BBERG_INLINE constexpr field pow(uint64_t exponent) const noexcept;
243 static constexpr uint256_t modulus_minus_two =
244 uint256_t(Params::modulus_0 - 2ULL, Params::modulus_1, Params::modulus_2, Params::modulus_3);
245 constexpr field invert() const noexcept;
246 static void batch_invert(std::span<field> coeffs) noexcept;
247 static void batch_invert(field* coeffs, size_t n) noexcept;
253 constexpr std::pair<bool, field> sqrt() const noexcept;
254
255 BBERG_INLINE constexpr void self_neg() noexcept;
256
257 BBERG_INLINE constexpr void self_to_montgomery_form() noexcept;
258 BBERG_INLINE constexpr void self_from_montgomery_form() noexcept;
259
260 BBERG_INLINE constexpr void self_conditional_negate(uint64_t predicate) noexcept;
261
262 BBERG_INLINE constexpr field reduce_once() const noexcept;
263 BBERG_INLINE constexpr void self_reduce_once() noexcept;
264
265 BBERG_INLINE constexpr void self_set_msb() noexcept;
266 [[nodiscard]] BBERG_INLINE constexpr bool is_msb_set() const noexcept;
267 [[nodiscard]] BBERG_INLINE constexpr uint64_t is_msb_set_word() const noexcept;
268
269 [[nodiscard]] BBERG_INLINE constexpr bool is_zero() const noexcept;
270
271 static constexpr field get_root_of_unity(size_t subgroup_size) noexcept;
272
273 static void serialize_to_buffer(const field& value, uint8_t* buffer) { write(buffer, value); }
274
275 static field serialize_from_buffer(const uint8_t* buffer) { return from_buffer<field>(buffer); }
276
277 [[nodiscard]] BBERG_INLINE std::vector<uint8_t> to_buffer() const { return ::to_buffer(*this); }
278
279 struct wide_array {
280 uint64_t data[8]; // NOLINT
281 };
282 BBERG_INLINE constexpr wide_array mul_512(const field& other) const noexcept;
283 BBERG_INLINE constexpr wide_array sqr_512() const noexcept;
284
285 BBERG_INLINE constexpr field conditionally_subtract_from_double_modulus(const uint64_t predicate) const noexcept
286 {
287 if (predicate != 0) {
288 constexpr field p{
289 twice_modulus.data[0], twice_modulus.data[1], twice_modulus.data[2], twice_modulus.data[3]
290 };
291 return p - *this;
292 }
293 return *this;
294 }
295
320 static void split_into_endomorphism_scalars(const field& k, field& k1, field& k2)
321 {
322 // if the modulus is a 256-bit integer, we need to use a basis where g1, g2 have been shifted by 2^384
323 if constexpr (Params::modulus_3 >= 0x4000000000000000ULL) {
324 split_into_endomorphism_scalars_384(k, k1, k2);
325 return;
326 }
327 field input = k.reduce_once();
328
329 constexpr field endo_g1 = { Params::endo_g1_lo, Params::endo_g1_mid, Params::endo_g1_hi, 0 };
330
331 constexpr field endo_g2 = { Params::endo_g2_lo, Params::endo_g2_mid, 0, 0 };
332
333 constexpr field endo_minus_b1 = { Params::endo_minus_b1_lo, Params::endo_minus_b1_mid, 0, 0 };
334
335 constexpr field endo_b2 = { Params::endo_b2_lo, Params::endo_b2_mid, 0, 0 };
336
337 // compute c1 = (g2 * k) >> 256
338 wide_array c1 = endo_g2.mul_512(input);
339 // compute c2 = (g1 * k) >> 256
340 wide_array c2 = endo_g1.mul_512(input);
341
342 // (the bit shifts are implicit, as we only utilize the high limbs of c1, c2
343
344 field c1_hi = {
345 c1.data[4], c1.data[5], c1.data[6], c1.data[7]
346 }; // *(field*)((uintptr_t)(&c1) + (4 * sizeof(uint64_t)));
347 field c2_hi = {
348 c2.data[4], c2.data[5], c2.data[6], c2.data[7]
349 }; // *(field*)((uintptr_t)(&c2) + (4 * sizeof(uint64_t)));
350
351 // compute q1 = c1 * -b1
352 wide_array q1 = c1_hi.mul_512(endo_minus_b1);
353 // compute q2 = c2 * b2
354 wide_array q2 = c2_hi.mul_512(endo_b2);
355
356 // FIX: Avoid using 512-bit multiplication as its not necessary.
357 // c1_hi, c2_hi can be uint256_t's and the final result (without montgomery reduction)
358 // could be casted to a field.
359 field q1_lo{ q1.data[0], q1.data[1], q1.data[2], q1.data[3] };
360 field q2_lo{ q2.data[0], q2.data[1], q2.data[2], q2.data[3] };
361
362 field t1 = (q2_lo - q1_lo).reduce_once();
363 field beta = cube_root_of_unity();
364 field t2 = (t1 * beta + input).reduce_once();
365 k2.data[0] = t1.data[0];
366 k2.data[1] = t1.data[1];
367 k1.data[0] = t2.data[0];
368 k1.data[1] = t2.data[1];
369 }
370
371 static void split_into_endomorphism_scalars_384(const field& input, field& k1_out, field& k2_out)
372 {
373
374 constexpr field minus_b1f{
375 Params::endo_minus_b1_lo,
376 Params::endo_minus_b1_mid,
377 0,
378 0,
379 };
380 constexpr field b2f{
381 Params::endo_b2_lo,
382 Params::endo_b2_mid,
383 0,
384 0,
385 };
386 constexpr uint256_t g1{
387 Params::endo_g1_lo,
388 Params::endo_g1_mid,
389 Params::endo_g1_hi,
390 Params::endo_g1_hihi,
391 };
392 constexpr uint256_t g2{
393 Params::endo_g2_lo,
394 Params::endo_g2_mid,
395 Params::endo_g2_hi,
396 Params::endo_g2_hihi,
397 };
398
399 field kf = input.reduce_once();
400 uint256_t k{ kf.data[0], kf.data[1], kf.data[2], kf.data[3] };
401
402 uint512_t c1 = (uint512_t(k) * static_cast<uint512_t>(g1)) >> 384;
403 uint512_t c2 = (uint512_t(k) * static_cast<uint512_t>(g2)) >> 384;
404
405 field c1f{ c1.lo.data[0], c1.lo.data[1], c1.lo.data[2], c1.lo.data[3] };
406 field c2f{ c2.lo.data[0], c2.lo.data[1], c2.lo.data[2], c2.lo.data[3] };
407
408 c1f.self_to_montgomery_form();
409 c2f.self_to_montgomery_form();
410 c1f = c1f * minus_b1f;
411 c2f = c2f * b2f;
412 field r2f = c1f - c2f;
413 field beta = cube_root_of_unity();
414 field r1f = input.reduce_once() - r2f * beta;
415 k1_out = r1f;
416 k2_out = -r2f;
417 }
418
419 // static constexpr auto coset_generators = compute_coset_generators();
420 // static constexpr std::array<field, 15> coset_generators = compute_coset_generators((1 << 30U));
421
422 friend std::ostream& operator<<(std::ostream& os, const field& a)
423 {
424 field out = a.from_montgomery_form();
425 std::ios_base::fmtflags f(os.flags());
426 os << std::hex << "0x" << std::setfill('0') << std::setw(16) << out.data[3] << std::setw(16) << out.data[2]
427 << std::setw(16) << out.data[1] << std::setw(16) << out.data[0];
428 os.flags(f);
429 return os;
430 }
431
432 BBERG_INLINE static void __copy(const field& a, field& r) noexcept { r = a; } // NOLINT
433 BBERG_INLINE static void __swap(field& src, field& dest) noexcept // NOLINT
434 {
435 field T = dest;
436 dest = src;
437 src = T;
438 }
439
440 static field random_element(numeric::random::Engine* engine = nullptr) noexcept;
441
442 static constexpr field multiplicative_generator() noexcept;
443
444 // For serialization
445 void msgpack_pack(auto& packer) const;
446 void msgpack_unpack(auto o);
447 void msgpack_schema(auto& packer) const { packer.pack_alias(Params::schema_name, "bin32"); }
448
449 private:
450 static constexpr uint256_t twice_modulus = modulus + modulus;
451 static constexpr uint256_t not_modulus = -modulus;
452 static constexpr uint256_t twice_not_modulus = -twice_modulus;
453
454 struct wnaf_table {
455 uint8_t windows[64]; // NOLINT
456
457 constexpr wnaf_table(const uint256_t& target)
458 : windows{
459 static_cast<uint8_t>(target.data[0] & 15), static_cast<uint8_t>((target.data[0] >> 4) & 15),
460 static_cast<uint8_t>((target.data[0] >> 8) & 15), static_cast<uint8_t>((target.data[0] >> 12) & 15),
461 static_cast<uint8_t>((target.data[0] >> 16) & 15), static_cast<uint8_t>((target.data[0] >> 20) & 15),
462 static_cast<uint8_t>((target.data[0] >> 24) & 15), static_cast<uint8_t>((target.data[0] >> 28) & 15),
463 static_cast<uint8_t>((target.data[0] >> 32) & 15), static_cast<uint8_t>((target.data[0] >> 36) & 15),
464 static_cast<uint8_t>((target.data[0] >> 40) & 15), static_cast<uint8_t>((target.data[0] >> 44) & 15),
465 static_cast<uint8_t>((target.data[0] >> 48) & 15), static_cast<uint8_t>((target.data[0] >> 52) & 15),
466 static_cast<uint8_t>((target.data[0] >> 56) & 15), static_cast<uint8_t>((target.data[0] >> 60) & 15),
467 static_cast<uint8_t>(target.data[1] & 15), static_cast<uint8_t>((target.data[1] >> 4) & 15),
468 static_cast<uint8_t>((target.data[1] >> 8) & 15), static_cast<uint8_t>((target.data[1] >> 12) & 15),
469 static_cast<uint8_t>((target.data[1] >> 16) & 15), static_cast<uint8_t>((target.data[1] >> 20) & 15),
470 static_cast<uint8_t>((target.data[1] >> 24) & 15), static_cast<uint8_t>((target.data[1] >> 28) & 15),
471 static_cast<uint8_t>((target.data[1] >> 32) & 15), static_cast<uint8_t>((target.data[1] >> 36) & 15),
472 static_cast<uint8_t>((target.data[1] >> 40) & 15), static_cast<uint8_t>((target.data[1] >> 44) & 15),
473 static_cast<uint8_t>((target.data[1] >> 48) & 15), static_cast<uint8_t>((target.data[1] >> 52) & 15),
474 static_cast<uint8_t>((target.data[1] >> 56) & 15), static_cast<uint8_t>((target.data[1] >> 60) & 15),
475 static_cast<uint8_t>(target.data[2] & 15), static_cast<uint8_t>((target.data[2] >> 4) & 15),
476 static_cast<uint8_t>((target.data[2] >> 8) & 15), static_cast<uint8_t>((target.data[2] >> 12) & 15),
477 static_cast<uint8_t>((target.data[2] >> 16) & 15), static_cast<uint8_t>((target.data[2] >> 20) & 15),
478 static_cast<uint8_t>((target.data[2] >> 24) & 15), static_cast<uint8_t>((target.data[2] >> 28) & 15),
479 static_cast<uint8_t>((target.data[2] >> 32) & 15), static_cast<uint8_t>((target.data[2] >> 36) & 15),
480 static_cast<uint8_t>((target.data[2] >> 40) & 15), static_cast<uint8_t>((target.data[2] >> 44) & 15),
481 static_cast<uint8_t>((target.data[2] >> 48) & 15), static_cast<uint8_t>((target.data[2] >> 52) & 15),
482 static_cast<uint8_t>((target.data[2] >> 56) & 15), static_cast<uint8_t>((target.data[2] >> 60) & 15),
483 static_cast<uint8_t>(target.data[3] & 15), static_cast<uint8_t>((target.data[3] >> 4) & 15),
484 static_cast<uint8_t>((target.data[3] >> 8) & 15), static_cast<uint8_t>((target.data[3] >> 12) & 15),
485 static_cast<uint8_t>((target.data[3] >> 16) & 15), static_cast<uint8_t>((target.data[3] >> 20) & 15),
486 static_cast<uint8_t>((target.data[3] >> 24) & 15), static_cast<uint8_t>((target.data[3] >> 28) & 15),
487 static_cast<uint8_t>((target.data[3] >> 32) & 15), static_cast<uint8_t>((target.data[3] >> 36) & 15),
488 static_cast<uint8_t>((target.data[3] >> 40) & 15), static_cast<uint8_t>((target.data[3] >> 44) & 15),
489 static_cast<uint8_t>((target.data[3] >> 48) & 15), static_cast<uint8_t>((target.data[3] >> 52) & 15),
490 static_cast<uint8_t>((target.data[3] >> 56) & 15), static_cast<uint8_t>((target.data[3] >> 60) & 15)
491 }
492 {}
493 };
494
495 BBERG_INLINE static constexpr std::pair<uint64_t, uint64_t> mul_wide(uint64_t a, uint64_t b) noexcept;
496
497 BBERG_INLINE static constexpr uint64_t mac(
498 uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in, uint64_t& carry_out) noexcept;
499
500 BBERG_INLINE static constexpr void mac(
501 uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in, uint64_t& out, uint64_t& carry_out) noexcept;
502
503 BBERG_INLINE static constexpr uint64_t mac_mini(uint64_t a, uint64_t b, uint64_t c, uint64_t& out) noexcept;
504
505 BBERG_INLINE static constexpr void mac_mini(
506 uint64_t a, uint64_t b, uint64_t c, uint64_t& out, uint64_t& carry_out) noexcept;
507
508 BBERG_INLINE static constexpr uint64_t mac_discard_lo(uint64_t a, uint64_t b, uint64_t c) noexcept;
509
510 BBERG_INLINE static constexpr uint64_t addc(uint64_t a,
511 uint64_t b,
512 uint64_t carry_in,
513 uint64_t& carry_out) noexcept;
514
515 BBERG_INLINE static constexpr uint64_t sbb(uint64_t a,
516 uint64_t b,
517 uint64_t borrow_in,
518 uint64_t& borrow_out) noexcept;
519
520 BBERG_INLINE static constexpr uint64_t square_accumulate(uint64_t a,
521 uint64_t b,
522 uint64_t c,
523 uint64_t carry_in_lo,
524 uint64_t carry_in_hi,
525 uint64_t& carry_lo,
526 uint64_t& carry_hi) noexcept;
527 BBERG_INLINE constexpr field reduce() const noexcept;
528 BBERG_INLINE constexpr field add(const field& other) const noexcept;
529 BBERG_INLINE constexpr field subtract(const field& other) const noexcept;
530 BBERG_INLINE constexpr field subtract_coarse(const field& other) const noexcept;
531 BBERG_INLINE constexpr field montgomery_mul(const field& other) const noexcept;
532 BBERG_INLINE constexpr field montgomery_mul_big(const field& other) const noexcept;
533 BBERG_INLINE constexpr field montgomery_square() const noexcept;
534
535#if (BBERG_NO_ASM == 0)
536 BBERG_INLINE static field asm_mul(const field& a, const field& b) noexcept;
537 BBERG_INLINE static field asm_sqr(const field& a) noexcept;
538 BBERG_INLINE static field asm_add(const field& a, const field& b) noexcept;
539 BBERG_INLINE static field asm_sub(const field& a, const field& b) noexcept;
540 BBERG_INLINE static field asm_mul_with_coarse_reduction(const field& a, const field& b) noexcept;
541 BBERG_INLINE static field asm_sqr_with_coarse_reduction(const field& a) noexcept;
542 BBERG_INLINE static field asm_add_with_coarse_reduction(const field& a, const field& b) noexcept;
543 BBERG_INLINE static field asm_sub_with_coarse_reduction(const field& a, const field& b) noexcept;
544 BBERG_INLINE static field asm_add_without_reduction(const field& a, const field& b) noexcept;
545 BBERG_INLINE static void asm_self_sqr(const field& a) noexcept;
546 BBERG_INLINE static void asm_self_add(const field& a, const field& b) noexcept;
547 BBERG_INLINE static void asm_self_sub(const field& a, const field& b) noexcept;
548 BBERG_INLINE static void asm_self_mul_with_coarse_reduction(const field& a, const field& b) noexcept;
549 BBERG_INLINE static void asm_self_sqr_with_coarse_reduction(const field& a) noexcept;
550 BBERG_INLINE static void asm_self_add_with_coarse_reduction(const field& a, const field& b) noexcept;
551 BBERG_INLINE static void asm_self_sub_with_coarse_reduction(const field& a, const field& b) noexcept;
552 BBERG_INLINE static void asm_self_add_without_reduction(const field& a, const field& b) noexcept;
553
554 BBERG_INLINE static void asm_conditional_negate(field& r, uint64_t predicate) noexcept;
555 BBERG_INLINE static field asm_reduce_once(const field& a) noexcept;
556 BBERG_INLINE static void asm_self_reduce_once(const field& a) noexcept;
557 static constexpr uint64_t zero_reference = 0x00ULL;
558#endif
559 static constexpr size_t COSET_GENERATOR_SIZE = 15;
560 constexpr field tonelli_shanks_sqrt() const noexcept;
561 static constexpr size_t primitive_root_log_size() noexcept;
562 static constexpr std::array<field, COSET_GENERATOR_SIZE> compute_coset_generators() noexcept;
563
564#if defined(__SIZEOF_INT128__) && !defined(__wasm__)
565 static constexpr uint128_t lo_mask = 0xffffffffffffffffUL;
566#endif
567};
568
569template <typename B, typename Params> void read(B& it, field<Params>& value)
570{
571 using serialize::read;
572 field<Params> result{ 0, 0, 0, 0 };
573 read(it, result.data[3]);
574 read(it, result.data[2]);
575 read(it, result.data[1]);
576 read(it, result.data[0]);
577 value = result.to_montgomery_form();
578}
579template <typename B, typename Params> void write(B& buf, field<Params> const& value)
580{
581 using serialize::write;
582 const field input = value.from_montgomery_form();
583 write(buf, input.data[3]);
584 write(buf, input.data[2]);
585 write(buf, input.data[1]);
586 write(buf, input.data[0]);
587}
588
589} // namespace barretenberg
Definition: engine.hpp:10
Definition: uint256.hpp:25
constexpr_utils defines some helper methods that perform some stl-equivalent operations but in a cons...
Definition: constexpr_utils.hpp:16
Definition: field_declarations.hpp:279
Definition: field_declarations.hpp:24
BBERG_INLINE constexpr field sqr() const noexcept
Definition: field_impl.hpp:61
constexpr std::pair< bool, field > sqrt() const noexcept
Compute square root of the field element.
Definition: field_impl.hpp:507
constexpr field(const uint512_t &input) noexcept
Convert a 512-bit big integer into a field element.
Definition: field_declarations.hpp:99
static void split_into_endomorphism_scalars(const field &k, field &k1, field &k2)
Definition: field_declarations.hpp:320
BBERG_INLINE constexpr field operator+(const field &other) const noexcept
Definition: field_impl.hpp:93
BBERG_INLINE constexpr field operator*(const field &other) const noexcept
Definition: field_impl.hpp:26
BBERG_INLINE constexpr field operator-(const field &other) const noexcept
Definition: field_impl.hpp:139