barretenberg
Loading...
Searching...
No Matches
uint256.hpp
1
12#pragma once
13
14#include "../uint128/uint128.hpp"
15#include "barretenberg/common/serialize.hpp"
16#include "barretenberg/common/throw_or_abort.hpp"
17#include <concepts>
18#include <cstdint>
19#include <iomanip>
20#include <iostream>
21#include <sstream>
22
23namespace numeric {
24
25class alignas(32) uint256_t {
26 public:
27 constexpr uint256_t(const uint64_t a = 0) noexcept
28 : data{ a, 0, 0, 0 }
29 {}
30
31 constexpr uint256_t(const uint64_t a, const uint64_t b, const uint64_t c, const uint64_t d) noexcept
32 : data{ a, b, c, d }
33 {}
34
35 constexpr uint256_t(const uint256_t& other) noexcept
36 : data{ other.data[0], other.data[1], other.data[2], other.data[3] }
37 {}
38 constexpr uint256_t(uint256_t&& other) noexcept = default;
39
40 explicit constexpr uint256_t(std::string input) noexcept
41 {
42 /* Quick and dirty conversion from a single character to its hex equivelent */
43 constexpr auto HexCharToInt = [](uint8_t Input) {
44 bool valid =
45 (Input >= 'a' && Input <= 'f') || (Input >= 'A' && Input <= 'F') || (Input >= '0' && Input <= '9');
46 if (!valid) {
47 throw_or_abort("Error, uint256 constructed from string_view with invalid hex parameter");
48 }
49 uint8_t res =
50 ((Input >= 'a') && (Input <= 'f')) ? (Input - (static_cast<uint8_t>('a') - static_cast<uint8_t>(10)))
51 : ((Input >= 'A') && (Input <= 'F')) ? (Input - (static_cast<uint8_t>('A') - static_cast<uint8_t>(10)))
52 : ((Input >= '0') && (Input <= '9')) ? (Input - static_cast<uint8_t>('0'))
53 : 0;
54 return res;
55 };
56
57 std::array<uint64_t, 4> limbs{ 0, 0, 0, 0 };
58 size_t start_index = 0;
59 if (input.size() == 66 && input[0] == '0' && input[1] == 'x') {
60 start_index = 2;
61 } else if (input.size() != 64) {
62 throw_or_abort("Error, uint256 constructed from string_view with invalid length");
63 }
64 for (size_t j = 0; j < 4; ++j) {
65
66 const size_t limb_index = start_index + j * 16;
67 for (size_t i = 0; i < 8; ++i) {
68 const size_t byte_index = limb_index + (i * 2);
69 uint8_t nibble_hi = HexCharToInt(static_cast<uint8_t>(input[byte_index]));
70 uint8_t nibble_lo = HexCharToInt(static_cast<uint8_t>(input[byte_index + 1]));
71 uint8_t byte = static_cast<uint8_t>((nibble_hi * 16) + nibble_lo);
72 limbs[j] <<= 8;
73 limbs[j] += byte;
74 }
75 }
76 data[0] = limbs[3];
77 data[1] = limbs[2];
78 data[2] = limbs[1];
79 data[3] = limbs[0];
80 }
81
82 static constexpr uint256_t from_uint128(const uint128_t a) noexcept
83 {
84 return { static_cast<uint64_t>(a), static_cast<uint64_t>(a >> 64), 0, 0 };
85 }
86
87 constexpr explicit operator uint128_t() { return (static_cast<uint128_t>(data[1]) << 64) + data[0]; }
88
89 constexpr uint256_t& operator=(const uint256_t& other) noexcept = default;
90 constexpr uint256_t& operator=(uint256_t&& other) noexcept = default;
91 constexpr ~uint256_t() noexcept = default;
92
93 explicit constexpr operator bool() const { return static_cast<bool>(data[0]); };
94
95 template <std::integral T> explicit constexpr operator T() const { return static_cast<T>(data[0]); };
96
97 [[nodiscard]] constexpr bool get_bit(uint64_t bit_index) const;
98 [[nodiscard]] constexpr uint64_t get_msb() const;
99
100 [[nodiscard]] constexpr uint256_t slice(uint64_t start, uint64_t end) const;
101 [[nodiscard]] constexpr uint256_t pow(const uint256_t& exponent) const;
102
103 constexpr uint256_t operator+(const uint256_t& other) const;
104 constexpr uint256_t operator-(const uint256_t& other) const;
105 constexpr uint256_t operator-() const;
106
107 constexpr uint256_t operator*(const uint256_t& other) const;
108 constexpr uint256_t operator/(const uint256_t& other) const;
109 constexpr uint256_t operator%(const uint256_t& other) const;
110
111 constexpr uint256_t operator>>(const uint256_t& other) const;
112 constexpr uint256_t operator<<(const uint256_t& other) 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 uint256_t& other) const;
117 constexpr uint256_t operator~() const;
118
119 constexpr bool operator==(const uint256_t& other) const;
120 constexpr bool operator!=(const uint256_t& other) const;
121 constexpr bool operator!() const;
122
123 constexpr bool operator>(const uint256_t& other) const;
124 constexpr bool operator<(const uint256_t& other) const;
125 constexpr bool operator>=(const uint256_t& other) const;
126 constexpr bool operator<=(const uint256_t& other) const;
127
128 static constexpr size_t length() { return 256; }
129
130 constexpr uint256_t& operator+=(const uint256_t& other)
131 {
132 *this = *this + other;
133 return *this;
134 };
135 constexpr uint256_t& operator-=(const uint256_t& other)
136 {
137 *this = *this - other;
138 return *this;
139 };
140 constexpr uint256_t& operator*=(const uint256_t& other)
141 {
142 *this = *this * other;
143 return *this;
144 };
145 constexpr uint256_t& operator/=(const uint256_t& other)
146 {
147 *this = *this / other;
148 return *this;
149 };
150 constexpr uint256_t& operator%=(const uint256_t& other)
151 {
152 *this = *this % other;
153 return *this;
154 };
155
156 constexpr uint256_t& operator++()
157 {
158 *this += uint256_t(1);
159 return *this;
160 };
161 constexpr uint256_t& operator--()
162 {
163 *this -= uint256_t(1);
164 return *this;
165 };
166
167 constexpr uint256_t& operator&=(const uint256_t& other)
168 {
169 *this = *this & other;
170 return *this;
171 };
172 constexpr uint256_t& operator^=(const uint256_t& other)
173 {
174 *this = *this ^ other;
175 return *this;
176 };
177 constexpr uint256_t& operator|=(const uint256_t& other)
178 {
179 *this = *this | other;
180 return *this;
181 };
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 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> mul_extended(const uint256_t& other) const;
195
196 uint64_t data[4]; // NOLINT
197
198 [[nodiscard]] constexpr std::pair<uint256_t, uint256_t> divmod(const uint256_t& b) const;
199
200 private:
201 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mul_wide(uint64_t a, uint64_t b);
202 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> addc(uint64_t a, uint64_t b, uint64_t carry_in);
203 [[nodiscard]] static constexpr uint64_t addc_discard_hi(uint64_t a, uint64_t b, uint64_t carry_in);
204 [[nodiscard]] static constexpr uint64_t sbb_discard_hi(uint64_t a, uint64_t b, uint64_t borrow_in);
205 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> sbb(uint64_t a, uint64_t b, uint64_t borrow_in);
206 [[nodiscard]] static constexpr uint64_t mac_discard_hi(uint64_t a, uint64_t b, uint64_t c, uint64_t carry_in);
207 [[nodiscard]] static constexpr std::pair<uint64_t, uint64_t> mac(uint64_t a,
208 uint64_t b,
209 uint64_t c,
210 uint64_t carry_in);
211};
212
213inline std::ostream& operator<<(std::ostream& os, uint256_t const& a)
214{
215 std::ios_base::fmtflags f(os.flags());
216 os << std::hex << "0x" << std::setfill('0') << std::setw(16) << a.data[3] << std::setw(16) << a.data[2]
217 << std::setw(16) << a.data[1] << std::setw(16) << a.data[0];
218 os.flags(f);
219 return os;
220}
221
222template <typename B> inline void read(B& it, uint256_t& value)
223{
224 using serialize::read;
225 uint64_t a = 0;
226 uint64_t b = 0;
227 uint64_t c = 0;
228 uint64_t d = 0;
229 read(it, d);
230 read(it, c);
231 read(it, b);
232 read(it, a);
233 value = uint256_t(a, b, c, d);
234}
235
236template <typename B> inline void write(B& it, uint256_t const& value)
237{
238 using serialize::write;
239 write(it, value.data[3]);
240 write(it, value.data[2]);
241 write(it, value.data[1]);
242 write(it, value.data[0]);
243}
244
245} // namespace numeric
246
247#include "./uint256_impl.hpp"
248
249// disable linter errors; we want to expose a global uint256_t type to mimic uint64_t, uint32_t etc
250// NOLINTNEXTLINE(tidymisc-unused-using-decls, google-global-names-in-headers, misc-unused-using-decls)
Definition: uint256.hpp:25
constexpr uint256_t slice(uint64_t start, uint64_t end) const
Definition: uint256_impl.hpp:157
Definition: field2_declarations.hpp:6