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 const uint64_t range = end - start;
84 const uintx mask = (uintx(1) << range) - 1;
85 return ((*this) >> start) & mask;
86 }
87
88 // constexpr to be used in constant calculation.
89 constexpr uintx operator-(const uintx& other) const
90 {
91 base_uint res_lo = lo - other.lo;
92 bool borrow = res_lo > lo;
93 base_uint res_hi = hi - other.hi - ((borrow) ? base_uint(1) : base_uint(0));
94 return { res_lo, res_hi };
95 }
96
97 // constexpr to be used in constant calculation.
98 constexpr uintx operator<<(const uint64_t other) const
99 {
100 const uint64_t total_shift = other;
101 if (total_shift >= length()) {
102 return uintx(0);
103 }
104 if (total_shift == 0) {
105 return *this;
106 }
107 const uint64_t num_shifted_limbs = total_shift >> (base_uint(base_uint::length()).get_msb());
108 const uint64_t limb_shift = total_shift & static_cast<uint64_t>(base_uint::length() - 1);
109
110 std::array<base_uint, 2> shifted_limbs = { 0, 0 };
111 if (limb_shift == 0) {
112 shifted_limbs[0] = lo;
113 shifted_limbs[1] = hi;
114 } else {
115 const uint64_t remainder_shift = static_cast<uint64_t>(base_uint::length()) - limb_shift;
116
117 shifted_limbs[0] = lo << limb_shift;
118
119 base_uint remainder = lo >> remainder_shift;
120
121 shifted_limbs[1] = (hi << limb_shift) + remainder;
122 }
123 uintx result(0);
124 if (num_shifted_limbs == 0) {
125 result.hi = shifted_limbs[1];
126 result.lo = shifted_limbs[0];
127 } else {
128 result.hi = shifted_limbs[0];
129 }
130 return result;
131 }
132
133 // constexpr to be used in constant calculation.
134 constexpr uintx operator>>(const uint64_t other) const
135 {
136 const uint64_t total_shift = other;
137 if (total_shift >= length()) {
138 return uintx(0);
139 }
140 if (total_shift == 0) {
141 return *this;
142 }
143 const uint64_t num_shifted_limbs = total_shift >> (base_uint(base_uint::length()).get_msb());
144
145 const uint64_t limb_shift = total_shift & static_cast<uint64_t>(base_uint::length() - 1);
146
147 std::array<base_uint, 2> shifted_limbs = { 0, 0 };
148 if (limb_shift == 0) {
149 shifted_limbs[0] = lo;
150 shifted_limbs[1] = hi;
151 } else {
152 const uint64_t remainder_shift = static_cast<uint64_t>(base_uint::length()) - limb_shift;
153
154 shifted_limbs[1] = hi >> limb_shift;
155
156 base_uint remainder = (hi) << remainder_shift;
157
158 shifted_limbs[0] = (lo >> limb_shift) + remainder;
159 }
160 uintx result(0);
161 if (num_shifted_limbs == 0) {
162 result.hi = shifted_limbs[1];
163 result.lo = shifted_limbs[0];
164 } else {
165 result.lo = shifted_limbs[1];
166 }
167 return result;
168 }
169
170 // constexpr to be used in constant calculation.
171 constexpr uintx operator+(const uintx& other) const
172 {
173 base_uint res_lo = lo + other.lo;
174 bool carry = res_lo < lo;
175 base_uint res_hi = hi + other.hi + ((carry) ? base_uint(1) : base_uint(0));
176 return { res_lo, res_hi };
177 };
178 uintx operator-() const;
179
180 uintx operator*(const uintx& other) const;
181 uintx operator/(const uintx& other) const;
182 uintx operator%(const uintx& other) const;
183
184 std::pair<uintx, uintx> mul_extended(const uintx& other) const;
185
186 // constexpr to be used in constant calculation.
187 constexpr uintx operator&(const uintx& other) const { return { lo & other.lo, hi & other.hi }; }
188
189 uintx operator^(const uintx& other) const;
190 uintx operator|(const uintx& other) const;
191 uintx operator~() const;
192
193 bool operator==(const uintx& other) const;
194 bool operator!=(const uintx& other) const;
195 bool operator!() const;
196
197 bool operator>(const uintx& other) const;
198 bool operator<(const uintx& other) const;
199 bool operator>=(const uintx& other) const;
200 bool operator<=(const uintx& other) const;
201
202 uintx& operator+=(const uintx& other)
203 {
204 *this = *this + other;
205 return *this;
206 };
207 uintx& operator-=(const uintx& other)
208 {
209 *this = *this - other;
210 return *this;
211 };
212 uintx& operator*=(const uintx& other)
213 {
214 *this = *this * other;
215 return *this;
216 };
217 uintx& operator/=(const uintx& other)
218
219 {
220 *this = *this / other;
221 return *this;
222 };
223 uintx& operator%=(const uintx& other)
224
225 {
226 *this = *this % other;
227 return *this;
228 };
229
231 {
232 *this += uintx(1);
233 return *this;
234 };
236 {
237 *this -= uintx(1);
238 return *this;
239 };
240
241 uintx& operator&=(const uintx& other)
242 {
243 *this = *this & other;
244 return *this;
245 };
246 uintx& operator^=(const uintx& other)
247 {
248 *this = *this ^ other;
249 return *this;
250 };
251 uintx& operator|=(const uintx& other)
252 {
253 *this = *this | other;
254 return *this;
255 };
256
257 uintx& operator>>=(const uint64_t other)
258 {
259 *this = *this >> other;
260 return *this;
261 };
262 uintx& operator<<=(const uint64_t other)
263 {
264 *this = *this << other;
265 return *this;
266 };
267
268 uintx invmod(const uintx& modulus) const;
269 uintx unsafe_invmod(const uintx& modulus) const;
270
271 base_uint lo;
272 base_uint hi;
273
274 template <base_uint modulus> std::pair<uintx, uintx> barrett_reduction() const;
275
276 // This only works (and is only used) for uint256_t
278 // This only works (and is only used) for uint256_t
280};
281
282template <typename B, typename Params> inline void read(B& it, uintx<Params>& value)
283{
284 using serialize::read;
285 Params a;
286 Params b;
287 read(it, b);
288 read(it, a);
290}
291
292template <typename B, typename Params> inline void write(B& it, uintx<Params> const& value)
293{
294 using serialize::write;
295 write(it, value.hi);
296 write(it, value.lo);
297}
298
299template <class base_uint> inline std::ostream& operator<<(std::ostream& os, uintx<base_uint> const& a)
300{
301 os << a.lo << ", " << a.hi << std::endl;
302 return os;
303}
304
305extern template class uintx<uint256_t>;
307extern template class uintx<uint512_t>;
309
310} // namespace bb::numeric
311
312using bb::numeric::uint1024_t; // NOLINT
313using 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:171
uintx operator%(const uintx &other) const
uintx & operator|=(const uintx &other)
Definition uintx.hpp:251
uintx & operator*=(const uintx &other)
Definition uintx.hpp:212
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:257
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:241
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:89
uintx & operator+=(const uintx &other)
Definition uintx.hpp:202
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:246
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:207
std::pair< uintx, uintx > barrett_reduction() const
uintx & operator<<=(const uint64_t other)
Definition uintx.hpp:262
uintx & operator++()
Definition uintx.hpp:230
constexpr uintx operator&(const uintx &other) const
Definition uintx.hpp:187
uintx & operator--()
Definition uintx.hpp:235
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:217
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:134
uintx invmod(const uintx &modulus) const
uintx operator^(const uintx &other) const
constexpr uintx operator<<(const uint64_t other) const
Definition uintx.hpp:98
uintx & operator%=(const uintx &other)
Definition uintx.hpp:223
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
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
void write(B &it, uint256_t const &value)
Definition uint256.hpp:281
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