Barretenberg
The ZK-SNARK library at the core of Aztec
Loading...
Searching...
No Matches
uintx.hpp
Go to the documentation of this file.
1// === AUDIT STATUS ===
2// internal: { status: Complete, auditors: [Luke], commit: }
3// external_1: { status: not started, auditors: [], commit: }
4// external_2: { status: not started, auditors: [], commit: }
5// =====================
6
17#pragma once
18
19#include "../uint256/uint256.hpp"
22#include <cstdint>
23#include <iomanip>
24#include <iostream>
25
26namespace bb::numeric {
27
28template <class base_uint> class uintx {
29 public:
30 constexpr uintx(const uint64_t& data = 0)
31 : lo(data)
32 , hi(base_uint(0))
33 {}
34
35 constexpr uintx(const uint256_t& data)
37 : lo(data)
38 , hi(base_uint(0))
39
40 {}
41 constexpr uintx(const base_uint input_lo)
42 : lo(input_lo)
43 , hi(base_uint(0))
44 {}
45
46 constexpr uintx(const base_uint input_lo, const base_uint input_hi)
47 : lo(input_lo)
48 , hi(input_hi)
49 {}
50
51 constexpr uintx(const uintx& other) = default;
52 constexpr uintx(uintx&& other) noexcept = default;
53
54 static constexpr size_t length() { return 2 * base_uint::length(); }
55 uintx& operator=(const uintx& other) = default;
56 uintx& operator=(uintx&& other) noexcept = default;
57
58 ~uintx() = default;
59 constexpr explicit operator bool() const { return static_cast<bool>(lo) || static_cast<bool>(hi); };
60 constexpr explicit operator uint8_t() const { return static_cast<uint8_t>(lo); };
61 constexpr explicit operator uint16_t() const { return static_cast<uint16_t>(lo); };
62 constexpr explicit operator uint32_t() const { return static_cast<uint32_t>(lo); };
63 constexpr explicit operator uint64_t() const { return static_cast<uint64_t>(lo); };
64
65 constexpr explicit operator base_uint() const { return lo; }
66
67 [[nodiscard]] bool get_bit(uint64_t bit_index) const;
68 [[nodiscard]] constexpr uint64_t get_msb() const
69 {
70 uint64_t hi_idx = hi.get_msb();
71 uint64_t lo_idx = lo.get_msb();
72 return (hi_idx || (hi > base_uint(0))) ? (hi_idx + base_uint::length()) : lo_idx;
73 }
74
81 constexpr uintx slice(const uint64_t start, const uint64_t end) const
82 {
83 // Plain assert is used here because BB_ASSERT_DEBUG defines a std::ostringstream, which is
84 // a non-literal type and therefore disallowed in the body of a constexpr function before C++23.
85 assert(start <= end);
86 const uint64_t range = end - start;
87 const uintx mask = (uintx(1) << range) - 1;
88 return ((*this) >> start) & mask;
89 }
90
91 // constexpr to be used in constant calculation.
92 constexpr uintx operator-(const uintx& other) const
93 {
94 base_uint res_lo = lo - other.lo;
95 bool borrow = res_lo > lo;
96 base_uint res_hi = hi - other.hi - ((borrow) ? base_uint(1) : base_uint(0));
97 return { res_lo, res_hi };
98 }
99
100 // constexpr to be used in constant calculation.
101 constexpr uintx operator<<(const uint64_t other) const
102 {
103 const uint64_t total_shift = other;
104 if (total_shift >= length()) {
105 return uintx(0);
106 }
107 if (total_shift == 0) {
108 return *this;
109 }
110 const uint64_t num_shifted_limbs = total_shift >> (base_uint(base_uint::length()).get_msb());
111 const uint64_t limb_shift = total_shift & static_cast<uint64_t>(base_uint::length() - 1);
112
113 std::array<base_uint, 2> shifted_limbs = { 0, 0 };
114 if (limb_shift == 0) {
115 shifted_limbs[0] = lo;
116 shifted_limbs[1] = hi;
117 } else {
118 const uint64_t remainder_shift = static_cast<uint64_t>(base_uint::length()) - limb_shift;
119
120 shifted_limbs[0] = lo << limb_shift;
121
122 base_uint remainder = lo >> remainder_shift;
123
124 shifted_limbs[1] = (hi << limb_shift) + remainder;
125 }
126 uintx result(0);
127 if (num_shifted_limbs == 0) {
128 result.hi = shifted_limbs[1];
129 result.lo = shifted_limbs[0];
130 } else {
131 result.hi = shifted_limbs[0];
132 }
133 return result;
134 }
135
136 // constexpr to be used in constant calculation.
137 constexpr uintx operator>>(const uint64_t other) const
138 {
139 const uint64_t total_shift = other;
140 if (total_shift >= length()) {
141 return uintx(0);
142 }
143 if (total_shift == 0) {
144 return *this;
145 }
146 const uint64_t num_shifted_limbs = total_shift >> (base_uint(base_uint::length()).get_msb());
147
148 const uint64_t limb_shift = total_shift & static_cast<uint64_t>(base_uint::length() - 1);
149
150 std::array<base_uint, 2> shifted_limbs = { 0, 0 };
151 if (limb_shift == 0) {
152 shifted_limbs[0] = lo;
153 shifted_limbs[1] = hi;
154 } else {
155 const uint64_t remainder_shift = static_cast<uint64_t>(base_uint::length()) - limb_shift;
156
157 shifted_limbs[1] = hi >> limb_shift;
158
159 base_uint remainder = (hi) << remainder_shift;
160
161 shifted_limbs[0] = (lo >> limb_shift) + remainder;
162 }
163 uintx result(0);
164 if (num_shifted_limbs == 0) {
165 result.hi = shifted_limbs[1];
166 result.lo = shifted_limbs[0];
167 } else {
168 result.lo = shifted_limbs[1];
169 }
170 return result;
171 }
172
173 // constexpr to be used in constant calculation.
174 constexpr uintx operator+(const uintx& other) const
175 {
176 base_uint res_lo = lo + other.lo;
177 bool carry = res_lo < lo;
178 base_uint res_hi = hi + other.hi + ((carry) ? base_uint(1) : base_uint(0));
179 return { res_lo, res_hi };
180 };
181 uintx operator-() const;
182
183 uintx operator*(const uintx& other) const;
184 uintx operator/(const uintx& other) const;
185 uintx operator%(const uintx& other) const;
186
187 std::pair<uintx, uintx> mul_extended(const uintx& other) const;
188
189 // constexpr to be used in constant calculation.
190 constexpr uintx operator&(const uintx& other) const { return { lo & other.lo, hi & other.hi }; }
191
192 uintx operator^(const uintx& other) const;
193 uintx operator|(const uintx& other) const;
194 uintx operator~() const;
195
196 bool operator==(const uintx& other) const;
197 bool operator!=(const uintx& other) const;
198 bool operator!() const;
199
200 bool operator>(const uintx& other) const;
201 bool operator<(const uintx& other) const;
202 bool operator>=(const uintx& other) const;
203 bool operator<=(const uintx& other) const;
204
205 uintx& operator+=(const uintx& other)
206 {
207 *this = *this + other;
208 return *this;
209 };
210 uintx& operator-=(const uintx& other)
211 {
212 *this = *this - other;
213 return *this;
214 };
215 uintx& operator*=(const uintx& other)
216 {
217 *this = *this * other;
218 return *this;
219 };
220 uintx& operator/=(const uintx& other)
221
222 {
223 *this = *this / other;
224 return *this;
225 };
226 uintx& operator%=(const uintx& other)
227
228 {
229 *this = *this % other;
230 return *this;
231 };
232
234 {
235 *this += uintx(1);
236 return *this;
237 };
239 {
240 *this -= uintx(1);
241 return *this;
242 };
243
244 uintx& operator&=(const uintx& other)
245 {
246 *this = *this & other;
247 return *this;
248 };
249 uintx& operator^=(const uintx& other)
250 {
251 *this = *this ^ other;
252 return *this;
253 };
254 uintx& operator|=(const uintx& other)
255 {
256 *this = *this | other;
257 return *this;
258 };
259
260 uintx& operator>>=(const uint64_t other)
261 {
262 *this = *this >> other;
263 return *this;
264 };
265 uintx& operator<<=(const uint64_t other)
266 {
267 *this = *this << other;
268 return *this;
269 };
270
271 uintx invmod(const uintx& modulus) const;
272 uintx unsafe_invmod(const uintx& modulus) const;
273
274 base_uint lo;
275 base_uint hi;
276
277 template <base_uint modulus> std::pair<uintx, uintx> barrett_reduction() const;
278
279 // This only works (and is only used) for uint256_t
281 // This only works (and is only used) for uint256_t
283};
284
285template <typename B, typename Params> inline void read(B& it, uintx<Params>& value)
286{
287 using serialize::read;
288 Params a;
289 Params b;
290 read(it, b);
291 read(it, a);
293}
294
295template <typename B, typename Params> inline void write(B& it, uintx<Params> const& value)
296{
297 using serialize::write;
298 write(it, value.hi);
299 write(it, value.lo);
300}
301
302template <class base_uint> inline std::ostream& operator<<(std::ostream& os, uintx<base_uint> const& a)
303{
304 os << a.lo << ", " << a.hi << std::endl;
305 return os;
306}
307
308extern template class uintx<uint256_t>;
310extern template class uintx<uint512_t>;
312
313// Pin the [class.mem]/19 alignment-propagation rule: uintx<uint256_t> must inherit alignas(32).
314static_assert(alignof(uint512_t) >= 32);
315static_assert(alignof(uint1024_t) >= 32);
316
317} // namespace bb::numeric
318
319using bb::numeric::uint1024_t; // NOLINT
320using bb::numeric::uint512_t; // NOLINT
constexpr uintx(uintx &&other) noexcept=default
constexpr uintx(const uint256_t &data)
Definition uintx.hpp:35
constexpr uintx operator+(const uintx &other) const
Definition uintx.hpp:174
uintx operator%(const uintx &other) const
uintx & operator|=(const uintx &other)
Definition uintx.hpp:254
uintx & operator*=(const uintx &other)
Definition uintx.hpp:215
std::pair< uintx, uintx > divmod(const uintx &b) const
constexpr uintx(const base_uint input_lo, const base_uint input_hi)
Definition uintx.hpp:46
constexpr uintx slice(const uint64_t start, const uint64_t end) const
Definition uintx.hpp:81
uintx & operator>>=(const uint64_t other)
Definition uintx.hpp:260
bool operator!=(const uintx &other) const
bool operator<(const uintx &other) const
uintx operator*(const uintx &other) const
uintx & operator&=(const uintx &other)
Definition uintx.hpp:244
static constexpr size_t length()
Definition uintx.hpp:54
uintx unsafe_invmod(const uintx &modulus) const
constexpr uintx operator-(const uintx &other) const
Definition uintx.hpp:92
uintx & operator+=(const uintx &other)
Definition uintx.hpp:205
uintx & operator=(uintx &&other) noexcept=default
uintx operator-() const
std::pair< uintx, uintx > divmod_base(const uintx &b) const
bool operator!() const
bool operator==(const uintx &other) const
uintx & operator^=(const uintx &other)
Definition uintx.hpp:249
bool operator>(const uintx &other) const
bool operator<=(const uintx &other) const
uintx operator~() const
bool get_bit(uint64_t bit_index) const
constexpr uint64_t get_msb() const
Definition uintx.hpp:68
uintx & operator-=(const uintx &other)
Definition uintx.hpp:210
std::pair< uintx, uintx > barrett_reduction() const
uintx & operator<<=(const uint64_t other)
Definition uintx.hpp:265
uintx & operator++()
Definition uintx.hpp:233
constexpr uintx operator&(const uintx &other) const
Definition uintx.hpp:190
uintx & operator--()
Definition uintx.hpp:238
uintx operator|(const uintx &other) const
uintx & operator=(const uintx &other)=default
bool operator>=(const uintx &other) const
uintx operator/(const uintx &other) const
uintx & operator/=(const uintx &other)
Definition uintx.hpp:220
std::pair< uintx, uintx > mul_extended(const uintx &other) const
constexpr uintx(const uint64_t &data=0)
Definition uintx.hpp:30
constexpr uintx operator>>(const uint64_t other) const
Definition uintx.hpp:137
uintx invmod(const uintx &modulus) const
uintx operator^(const uintx &other) const
constexpr uintx operator<<(const uint64_t other) const
Definition uintx.hpp:101
uintx & operator%=(const uintx &other)
Definition uintx.hpp:226
constexpr uintx(const uintx &other)=default
constexpr uintx(const base_uint input_lo)
Definition uintx.hpp:41
const std::vector< MemoryValue > data
FF a
FF b
crypto::Poseidon2Bn254ScalarFieldParams Params
void read(B &it, uint256_t &value)
Definition uint256.hpp:267
std::ostream & operator<<(std::ostream &os, uint256_t const &a)
Definition uint256.hpp:258
uintx< uint256_t > uint512_t
Definition uintx.hpp:309
void write(B &it, uint256_t const &value)
Definition uint256.hpp:281
uintx< uint512_t > uint1024_t
Definition uintx.hpp:311
void read(auto &it, msgpack_concepts::HasMsgPack auto &obj)
Automatically derived read for any object that defines .msgpack() (implicitly defined by SERIALIZATIO...
void write(auto &buf, const msgpack_concepts::HasMsgPack auto &obj)
Automatically derived write for any object that defines .msgpack() (implicitly defined by SERIALIZATI...
constexpr decltype(auto) get(::tuplet::tuple< T... > &&t) noexcept
Definition tuple.hpp:13