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 explicit operator uint128_t() { return (static_cast<uint128_t>(data[1]) << 64) + data[0]; }
100
101 constexpr uint256_t& operator=(const uint256_t& other) noexcept = default;
102 constexpr uint256_t& operator=(uint256_t&& other) noexcept = default;
103 constexpr ~uint256_t() noexcept = default;
104
105 explicit constexpr operator bool() const { return static_cast<bool>(data[0]); };
106
107 template <std::integral T> explicit constexpr operator T() const { return static_cast<T>(data[0]); };
108
109 [[nodiscard]] constexpr bool get_bit(uint64_t bit_index) const;
110 [[nodiscard]] constexpr uint64_t get_msb() const;
111
112 [[nodiscard]] constexpr uint256_t slice(uint64_t start, uint64_t end) const;
113 [[nodiscard]] constexpr uint256_t pow(const uint256_t& exponent) const;
114
115 constexpr uint256_t operator+(const uint256_t& other) const;
116 constexpr uint256_t operator-(const uint256_t& other) const;
117 constexpr uint256_t operator-() const;
118
119 constexpr uint256_t operator*(const uint256_t& other) const;
120 constexpr uint256_t operator/(const uint256_t& other) const;
121 constexpr uint256_t operator%(const uint256_t& other) const;
122
123 constexpr uint256_t operator>>(const uint256_t& other) const;
124 constexpr uint256_t operator<<(const uint256_t& other) const;
125
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 uint256_t& other) const;
129 constexpr uint256_t operator~() const;
130
131 constexpr bool operator==(const uint256_t& other) const;
132 constexpr bool operator!=(const uint256_t& other) const;
133 constexpr bool operator!() const;
134
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 constexpr bool operator<=(const uint256_t& other) const;
139
140 static constexpr size_t length() { return 256; }
141
142 constexpr uint256_t& operator+=(const uint256_t& other)
143 {
144 *this = *this + other;
145 return *this;
146 };
147 constexpr uint256_t& operator-=(const uint256_t& other)
148 {
149 *this = *this - other;
150 return *this;
151 };
152 constexpr uint256_t& operator*=(const uint256_t& other)
153 {
154 *this = *this * other;
155 return *this;
156 };
157 constexpr uint256_t& operator/=(const uint256_t& other)
158 {
159 *this = *this / other;
160 return *this;
161 };
162 constexpr uint256_t& operator%=(const uint256_t& other)
163 {
164 *this = *this % other;
165 return *this;
166 };
167
169 {
170 *this += uint256_t(1);
171 return *this;
172 };
174 {
175 *this -= uint256_t(1);
176 return *this;
177 };
178
179 constexpr uint256_t& operator&=(const uint256_t& other)
180 {
181 *this = *this & other;
182 return *this;
183 };
184 constexpr uint256_t& operator^=(const uint256_t& other)
185 {
186 *this = *this ^ other;
187 return *this;
188 };
189 constexpr uint256_t& operator|=(const uint256_t& other)
190 {
191 *this = *this | other;
192 return *this;
193 };
194
195 constexpr uint256_t& operator>>=(const uint256_t& other)
196 {
197 *this = *this >> other;
198 return *this;
199 };
200 constexpr uint256_t& operator<<=(const uint256_t& other)
201 {
202 *this = *this << other;
203 return *this;
204 };
205
206 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> mul_extended(const uint256_t& other) const;
207
208 uint64_t data[4]; // NOLINT
209
210 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> divmod(const uint256_t& b) const;
211
212 size_t hash() const noexcept { return utils::hash_as_tuple(data[0], data[1], data[2], data[3]); }
213
214 // For serialization
215 void msgpack_pack(auto& packer) const;
216 void msgpack_unpack(auto o);
217 void msgpack_schema(auto& packer) const { packer.pack_alias("uint256_t", "bin32"); }
218
219 private:
220 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mul_wide(uint64_t a, uint64_t b);
221 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> addc(uint64_t a, uint64_t b, uint64_t carry_in);
222 [[nodiscard]] static constexpr uint64_t addc_discard_hi(uint64_t a, uint64_t b, uint64_t carry_in);
223 [[nodiscard]] static constexpr uint64_t sbb_discard_hi(uint64_t a, uint64_t b, uint64_t borrow_in);
224 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> sbb(uint64_t a, uint64_t b, uint64_t borrow_in);
225 [[nodiscard]] static constexpr uint64_t mac_discard_hi(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in);
226 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mac(uint64_t a,
227 uint64_t b,
228 uint64_t c,
229 uint64_t carry_in);
230#if defined(__wasm__) || !defined(__SIZEOF_INT128__)
231 static constexpr void wasm_madd(const uint64_t& left_limb,
232 const uint64_t* right_limbs,
233 uint64_t& result_0,
234 uint64_t& result_1,
235 uint64_t& result_2,
236 uint64_t& result_3,
237 uint64_t& result_4,
238 uint64_t& result_5,
239 uint64_t& result_6,
240 uint64_t& result_7,
241 uint64_t& result_8);
242 [[nodiscard]] static constexpr std::array<uint64_t, WASM_NUM_LIMBS> wasm_convert(const uint64_t* data);
243#endif
244};
245
246inline std::ostream& operator<<(std::ostream& os, uint256_t const& a)
247{
248 std::ios_base::fmtflags f(os.flags());
249 os << std::hex << "0x" << std::setfill('0') << std::setw(16) << a.data[3] << std::setw(16) << a.data[2]
250 << std::setw(16) << a.data[1] << std::setw(16) << a.data[0];
251 os.flags(f);
252 return os;
253}
254
255template <typename B> inline void read(B& it, uint256_t& value)
256{
257 using serialize::read;
258 uint64_t a = 0;
259 uint64_t b = 0;
260 uint64_t c = 0;
261 uint64_t d = 0;
262 read(it, d);
263 read(it, c);
264 read(it, b);
265 read(it, a);
266 value = uint256_t(a, b, c, d);
267}
268
269template <typename B> inline void write(B& it, uint256_t const& value)
270{
271 using serialize::write;
272 write(it, value.data[3]);
273 write(it, value.data[2]);
274 write(it, value.data[1]);
275 write(it, value.data[0]);
276}
277
278} // namespace bb::numeric
279
280#include "./uint256_impl.hpp"
281
282// disable linter errors; we want to expose a global uint256_t type to mimic uint64_t, uint32_t etc
283// 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:195
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:200
constexpr uint256_t & operator++()
Definition uint256.hpp:168
constexpr uint256_t operator+(const uint256_t &other) const
constexpr uint256_t & operator*=(const uint256_t &other)
Definition uint256.hpp:152
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:217
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:212
constexpr bool get_bit(uint64_t bit_index) const
constexpr uint256_t & operator&=(const uint256_t &other)
Definition uint256.hpp:179
constexpr uint256_t & operator%=(const uint256_t &other)
Definition uint256.hpp:162
constexpr uint256_t operator<<(const uint256_t &other) const
constexpr bool operator!() const
constexpr uint256_t & operator-=(const uint256_t &other)
Definition uint256.hpp:147
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:184
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:189
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:157
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:173
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:142
static constexpr size_t length()
Definition uint256.hpp:140
FF a
FF b
void read(B &it, uint256_t &value)
Definition uint256.hpp:255
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:246
void write(B &it, uint256_t const &value)
Definition uint256.hpp:269
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)