Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
uint256.hpp
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
18#pragma once
19
20#include "../uint128/uint128.hpp"
24#include <concepts>
25#include <cstdint>
26#include <iomanip>
27#include <iostream>
28#include <sstream>
29
30namespace bb::numeric {
31
32class alignas(32) uint256_t {
33
34 public:
35#if defined(__wasm__) || !defined(__SIZEOF_INT128__)
36#define WASM_NUM_LIMBS 9
37#define WASM_LIMB_BITS 29
38#endif
39 constexpr uint256_t(const uint64_t a = 0) noexcept
40 : data{ a, 0, 0, 0 }
41 {}
42
43 constexpr uint256_t(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
44 : data{ a, b, c, d }
45 {}
46
47 constexpr uint256_t(const uint256_t& other) noexcept
48 : data{ other.data[0], other.data[1], other.data[2], other.data[3] }
49 {}
50 constexpr uint256_t(uint256_t&& other) noexcept = default;
51
52 explicit constexpr uint256_t(std::string input) noexcept
53 {
54 /* Quick and dirty conversion from a single character to its hex equivelent */
55 constexpr auto HexCharToInt = [](uint8_t Input) {
56 bool valid =
57 (Input >= 'a' && Input <= 'f') || (Input >= 'A' && Input <= 'F') || (Input >= '0' && Input <= '9');
58 if (!valid) {
59 throw_or_abort("Error, uint256 constructed from string_view with invalid hex parameter");
60 }
61 uint8_t res =
62 ((Input >= 'a') && (Input <= 'f')) ? (Input - (static_cast<uint8_t>('a') - static_cast<uint8_t>(10)))
63 : ((Input >= 'A') && (Input <= 'F')) ? (Input - (static_cast<uint8_t>('A') - static_cast<uint8_t>(10)))
64 : ((Input >= '0') && (Input <= '9')) ? (Input - static_cast<uint8_t>('0'))
65 : 0;
66 return res;
67 };
68
69 std::array<uint64_t, 4> limbs{ 0, 0, 0, 0 };
70 size_t start_index = 0;
71 if (input.size() == 66 && input[0] == '0' && input[1] == 'x') {
72 start_index = 2;
73 } else if (input.size() != 64) {
74 throw_or_abort("Error, uint256 constructed from string_view with invalid length");
75 }
76 for (size_t j = 0; j < 4; ++j) {
77
78 const size_t limb_index = start_index + j * 16;
79 for (size_t i = 0; i < 8; ++i) {
80 const size_t byte_index = limb_index + (i * 2);
81 uint8_t nibble_hi = HexCharToInt(static_cast<uint8_t>(input[byte_index]));
82 uint8_t nibble_lo = HexCharToInt(static_cast<uint8_t>(input[byte_index + 1]));
83 uint8_t byte = static_cast<uint8_t>((nibble_hi * 16) + nibble_lo);
84 limbs[j] <<= 8;
85 limbs[j] += byte;
86 }
87 }
88 data[0] = limbs[3];
89 data[1] = limbs[2];
90 data[2] = limbs[1];
91 data[3] = limbs[0];
92 }
93
94 static constexpr uint256_t from_uint128(const uint128_t a) noexcept
95 {
96 return { static_cast<uint64_t>(a), static_cast<uint64_t>(a >> 64), 0, 0 };
97 }
98
99 constexpr uint256_t& operator=(const uint256_t& other) noexcept = default;
100 constexpr uint256_t& operator=(uint256_t&& other) noexcept = default;
101 constexpr ~uint256_t() noexcept = default;
102
103 explicit constexpr operator bool() const { return static_cast<bool>(data[0]); };
104
105 constexpr explicit operator uint128_t() { return (static_cast<uint128_t>(data[1]) << 64) + data[0]; }
106 template <std::integral T> explicit constexpr operator T() const { return static_cast<T>(data[0]); };
107
108 [[nodiscard]] constexpr bool get_bit(uint64_t bit_index) const;
109 [[nodiscard]] constexpr uint64_t get_msb() const;
110
111 [[nodiscard]] constexpr uint256_t slice(uint64_t start, uint64_t end) const;
112 [[nodiscard]] constexpr uint256_t pow(const uint256_t& exponent) const;
113
114 constexpr uint256_t operator+(const uint256_t& other) const;
115 constexpr uint256_t operator-(const uint256_t& other) const;
116 constexpr uint256_t operator-() const;
117
118 constexpr uint256_t operator*(const uint256_t& other) const;
119 constexpr uint256_t operator/(const uint256_t& other) const;
120 constexpr uint256_t operator%(const uint256_t& other) const;
121
122 constexpr uint256_t operator>>(const uint256_t& other) const;
123 constexpr uint256_t operator<<(const uint256_t& other) const;
124
125 constexpr uint256_t operator&(const uint256_t& other) const;
126 constexpr uint256_t operator^(const uint256_t& other) const;
127 constexpr uint256_t operator|(const uint256_t& other) const;
128 constexpr uint256_t operator~() const;
129
130 constexpr bool operator==(const uint256_t& other) const;
131 constexpr bool operator!=(const uint256_t& other) const;
132 constexpr bool operator!() const;
133
134 constexpr bool operator>(const uint256_t& other) const;
135 constexpr bool operator<(const uint256_t& other) const;
136 constexpr bool operator>=(const uint256_t& other) const;
137 constexpr bool operator<=(const uint256_t& other) const;
138
139 static constexpr size_t length() { return 256; }
140
141 constexpr uint256_t& operator+=(const uint256_t& other)
142 {
143 *this = *this + other;
144 return *this;
145 };
146 constexpr uint256_t& operator-=(const uint256_t& other)
147 {
148 *this = *this - other;
149 return *this;
150 };
151 constexpr uint256_t& operator*=(const uint256_t& other)
152 {
153 *this = *this * other;
154 return *this;
155 };
156 constexpr uint256_t& operator/=(const uint256_t& other)
157 {
158 *this = *this / other;
159 return *this;
160 };
161 constexpr uint256_t& operator%=(const uint256_t& other)
162 {
163 *this = *this % other;
164 return *this;
165 };
166
168 {
169 *this += uint256_t(1);
170 return *this;
171 };
173 {
174 *this -= uint256_t(1);
175 return *this;
176 };
177
178 constexpr uint256_t& operator&=(const uint256_t& other)
179 {
180 *this = *this & other;
181 return *this;
182 };
183 constexpr uint256_t& operator^=(const uint256_t& other)
184 {
185 *this = *this ^ other;
186 return *this;
187 };
188 constexpr uint256_t& operator|=(const uint256_t& other)
189 {
190 *this = *this | other;
191 return *this;
192 };
193
194 constexpr uint256_t& operator>>=(const uint256_t& other)
195 {
196 *this = *this >> other;
197 return *this;
198 };
199 constexpr uint256_t& operator<<=(const uint256_t& other)
200 {
201 *this = *this << other;
202 return *this;
203 };
204
205 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> mul_extended(const uint256_t& other) const;
206
207 uint64_t data[4]; // NOLINT
208
209 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> divmod(const uint256_t& b) const;
210
211 size_t hash() const noexcept { return utils::hash_as_tuple(data[0], data[1], data[2], data[3]); }
212
213 // For serialization
214 void msgpack_pack(auto& packer) const;
215 void msgpack_unpack(auto o);
216 void msgpack_schema(auto& packer) const { packer.pack_alias("uint256_t", "bin32"); }
217
218 private:
219 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mul_wide(uint64_t a, uint64_t b);
220 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> addc(uint64_t a, uint64_t b, uint64_t carry_in);
221 [[nodiscard]] static constexpr uint64_t addc_discard_hi(uint64_t a, uint64_t b, uint64_t carry_in);
222 [[nodiscard]] static constexpr uint64_t sbb_discard_hi(uint64_t a, uint64_t b, uint64_t borrow_in);
223 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> sbb(uint64_t a, uint64_t b, uint64_t borrow_in);
224 [[nodiscard]] static constexpr uint64_t mac_discard_hi(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in);
225 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mac(uint64_t a,
226 uint64_t b,
227 uint64_t c,
228 uint64_t carry_in);
229#if defined(__wasm__) || !defined(__SIZEOF_INT128__)
230 static constexpr void wasm_madd(const uint64_t& left_limb,
231 const uint64_t* right_limbs,
232 uint64_t& result_0,
233 uint64_t& result_1,
234 uint64_t& result_2,
235 uint64_t& result_3,
236 uint64_t& result_4,
237 uint64_t& result_5,
238 uint64_t& result_6,
239 uint64_t& result_7,
240 uint64_t& result_8);
241 [[nodiscard]] static constexpr std::array<uint64_t, WASM_NUM_LIMBS> wasm_convert(const uint64_t* data);
242#endif
243};
244
245inline std::ostream& operator<<(std::ostream& os, uint256_t const& a)
246{
247 std::ios_base::fmtflags f(os.flags());
248 os << std::hex << "0x" << std::setfill('0') << std::setw(16) << a.data[3] << std::setw(16) << a.data[2]
249 << std::setw(16) << a.data[1] << std::setw(16) << a.data[0];
250 os.flags(f);
251 return os;
252}
253
254template <typename B> inline void read(B& it, uint256_t& value)
255{
256 using serialize::read;
257 uint64_t a = 0;
258 uint64_t b = 0;
259 uint64_t c = 0;
260 uint64_t d = 0;
261 read(it, d);
262 read(it, c);
263 read(it, b);
264 read(it, a);
265 value = uint256_t(a, b, c, d);
266}
267
268template <typename B> inline void write(B& it, uint256_t const& value)
269{
270 using serialize::write;
271 write(it, value.data[3]);
272 write(it, value.data[2]);
273 write(it, value.data[1]);
274 write(it, value.data[0]);
275}
276
277} // namespace bb::numeric
278
279#include "./uint256_impl.hpp"
280
281// disable linter errors; we want to expose a global uint256_t type to mimic uint64_t, uint32_t etc
282// NOLINTNEXTLINE(tidymisc-unused-using-decls, google-global-names-in-headers, misc-unused-using-decls)
constexpr std::pair< uint256_t, uint256_t > mul_extended(const uint256_t &other) const
Compute the result of multiplication modulu 2**512.
constexpr uint256_t operator^(const uint256_t &other) const
constexpr uint256_t operator~() const
constexpr uint256_t(const uint64_t a=0) noexcept
Definition uint256.hpp:39
constexpr uint256_t & operator>>=(const uint256_t &other)
Definition uint256.hpp:194
constexpr uint256_t operator%(const uint256_t &other) const
constexpr uint256_t(uint256_t &&other) noexcept=default
static constexpr std::pair< uint64_t, uint64_t > addc(uint64_t a, uint64_t b, uint64_t carry_in)
constexpr uint256_t operator*(const uint256_t &other) const
constexpr uint256_t & operator<<=(const uint256_t &other)
Definition uint256.hpp:199
constexpr uint256_t & operator++()
Definition uint256.hpp:167
constexpr uint256_t operator+(const uint256_t &other) const
constexpr uint256_t & operator*=(const uint256_t &other)
Definition uint256.hpp:151
static constexpr uint64_t sbb_discard_hi(uint64_t a, uint64_t b, uint64_t borrow_in)
void msgpack_schema(auto &packer) const
Definition uint256.hpp:216
static constexpr std::array< uint64_t, WASM_NUM_LIMBS > wasm_convert(const uint64_t *data)
Convert from 4 64-bit limbs to 9 29-bit limbs.
size_t hash() const noexcept
Definition uint256.hpp:211
constexpr bool get_bit(uint64_t bit_index) const
constexpr uint256_t & operator&=(const uint256_t &other)
Definition uint256.hpp:178
constexpr uint256_t & operator%=(const uint256_t &other)
Definition uint256.hpp:161
constexpr uint256_t operator<<(const uint256_t &other) const
constexpr bool operator!() const
constexpr uint256_t & operator-=(const uint256_t &other)
Definition uint256.hpp:146
constexpr bool operator==(const uint256_t &other) const
constexpr uint256_t operator&(const uint256_t &other) const
constexpr uint256_t & operator=(const uint256_t &other) noexcept=default
static constexpr void wasm_madd(const uint64_t &left_limb, const uint64_t *right_limbs, uint64_t &result_0, uint64_t &result_1, uint64_t &result_2, uint64_t &result_3, uint64_t &result_4, uint64_t &result_5, uint64_t &result_6, uint64_t &result_7, uint64_t &result_8)
Multiply one limb by 9 limbs and add to resulting limbs.
constexpr bool operator>(const uint256_t &other) const
static constexpr std::pair< uint64_t, uint64_t > mac(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in)
constexpr bool operator<(const uint256_t &other) const
constexpr uint256_t & operator^=(const uint256_t &other)
Definition uint256.hpp:183
static constexpr std::pair< uint64_t, uint64_t > sbb(uint64_t a, uint64_t b, uint64_t borrow_in)
constexpr bool operator>=(const uint256_t &other) const
constexpr uint256_t operator|(const uint256_t &other) const
constexpr bool operator!=(const uint256_t &other) const
constexpr uint256_t operator-() const
constexpr uint256_t & operator|=(const uint256_t &other)
Definition uint256.hpp:188
static constexpr uint64_t mac_discard_hi(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in)
constexpr uint256_t operator/(const uint256_t &other) const
constexpr uint256_t pow(const uint256_t &exponent) const
constexpr uint256_t slice(uint64_t start, uint64_t end) const
static constexpr std::pair< uint64_t, uint64_t > mul_wide(uint64_t a, uint64_t b)
static constexpr uint64_t addc_discard_hi(uint64_t a, uint64_t b, uint64_t carry_in)
constexpr bool operator<=(const uint256_t &other) const
constexpr ~uint256_t() noexcept=default
constexpr std::pair< uint256_t, uint256_t > divmod(const uint256_t &b) const
constexpr uint256_t & operator/=(const uint256_t &other)
Definition uint256.hpp:156
constexpr uint256_t operator>>(const uint256_t &other) const
static constexpr uint256_t from_uint128(const uint128_t a) noexcept
Definition uint256.hpp:94
constexpr uint256_t & operator=(uint256_t &&other) noexcept=default
constexpr uint256_t(const uint256_t &other) noexcept
Definition uint256.hpp:47
constexpr uint64_t get_msb() const
constexpr uint256_t & operator--()
Definition uint256.hpp:172
constexpr uint256_t(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
Definition uint256.hpp:43
void msgpack_pack(auto &packer) const
constexpr uint256_t(std::string input) noexcept
Definition uint256.hpp:52
constexpr uint256_t & operator+=(const uint256_t &other)
Definition uint256.hpp:141
static constexpr size_t length()
Definition uint256.hpp:139
FF a
FF b
void read(B &it, uint256_t &value)
Definition uint256.hpp:254
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:245
void write(B &it, uint256_t const &value)
Definition uint256.hpp:268
size_t hash_as_tuple(const Ts &... ts)
Definition utils.hpp:22
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by MSGPACK_FIEL...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by MSGPACK_FIE...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13
unsigned __int128 uint128_t
Definition serialize.hpp:44
void throw_or_abort(std::string const &err)