CppCommon 1.0.5.0
C++ Common Library
Loading...
Searching...
No Matches
uint256.cpp
Go to the documentation of this file.
1
9#include "common/uint256.h"
10
11namespace CppCommon {
12
13uint256_t operator*(const uint256_t& value1, const uint256_t& value2) noexcept
14{
15 // Split values into four 32-bit parts
16 uint128_t top[4] = { value1.upper().upper(), value1.upper().lower(), value1.lower().upper(), value1.lower().lower() };
17 uint128_t bottom[4] = { value2.upper().upper(), value2.upper().lower(), value2.lower().upper(), value2.lower().lower() };
18 uint128_t products[4][4];
19
20 // Multiply each component of the values
21 for (int y = 3; y > -1; --y)
22 for (int x = 3; x > -1; --x)
23 products[3 - x][y] = top[x] * bottom[y];
24
25 // First row
26 uint128_t fourth64 = uint128_t(products[0][3].lower());
27 uint128_t third64 = uint128_t(products[0][2].lower()) + uint128_t(products[0][3].upper());
28 uint128_t second64 = uint128_t(products[0][1].lower()) + uint128_t(products[0][2].upper());
29 uint128_t first64 = uint128_t(products[0][0].lower()) + uint128_t(products[0][1].upper());
30
31 // Second row
32 third64 += uint128_t(products[1][3].lower());
33 second64 += uint128_t(products[1][2].lower()) + uint128_t(products[1][3].upper());
34 first64 += uint128_t(products[1][1].lower()) + uint128_t(products[1][2].upper());
35
36 // Third row
37 second64 += uint128_t(products[2][3].lower());
38 first64 += uint128_t(products[2][2].lower()) + uint128_t(products[2][3].upper());
39
40 // Fourth row
41 first64 += uint128_t(products[3][3].lower());
42
43 // Combines the values, taking care of carry over
44 return uint256_t(first64 << 64, 0) + uint256_t(third64.upper(), third64 << 64) + uint256_t(second64, 0) + uint256_t(fourth64);
45}
46
47uint256_t operator<<(const uint256_t& value1, const uint256_t& value2) noexcept
48{
49 const uint128_t shift = value2._lower;
50
51 if (((bool)value2._upper) || (shift >= 256))
52 return 0;
53 else if (shift == 128)
54 return uint256_t(value1._lower, 0);
55 else if (shift == 0)
56 return value1;
57 else if (shift < 128)
58 return uint256_t((value1._upper << shift) + (value1._lower >> (128 - shift)), value1._lower << shift);
59 else if ((256 > shift) && (shift > 128))
60 return uint256_t(value1._lower << (shift - 128), 0);
61 else
62 return 0;
63}
64
65uint256_t operator>>(const uint256_t& value1, const uint256_t& value2) noexcept
66{
67 const uint128_t shift = value2._lower;
68
69 if (((bool)value2._upper) || (shift >= 256))
70 return 0;
71 else if (shift == 128)
72 return uint256_t(value1._upper);
73 else if (shift == 0)
74 return value1;
75 else if (shift < 128)
76 return uint256_t(value1._upper >> shift, (value1._upper << (128 - shift)) + (value1._lower >> shift));
77 else if ((256 > shift) && (shift > 128))
78 return uint256_t(value1._upper >> (shift - 128));
79 else
80 return 0;
81}
82
83size_t uint256_t::bits() const noexcept
84{
85 size_t result = 0;
86
87 if (_upper)
88 {
89 result = 128;
90 uint128_t upper = _upper;
91 while (upper)
92 {
93 upper >>= 1;
94 ++result;
95 }
96 }
97 else
98 {
99 uint128_t lower = _lower;
100 while (lower)
101 {
102 lower >>= 1;
103 ++result;
104 }
105 }
106
107 return result;
108}
109
110std::string uint256_t::string(size_t base, size_t length) const
111{
112 if ((base < 2) || (base > 16))
113 throw std::invalid_argument("Base must be in the range [2, 16]");
114
115 std::string out;
116
117 if (!(*this))
118 out = "0";
119 else
120 {
121 std::pair<uint256_t, uint256_t> qr(*this, 0);
122 do
123 {
124 qr = uint256_t::divmod(qr.first, uint256_t(base));
125 out = "0123456789abcdef"[(uint8_t)qr.second] + out;
126 } while (qr.first != 0);
127 }
128
129 if (out.size() < length)
130 out = std::string(length - out.size(), '0') + out;
131
132 return out;
133}
134
135std::wstring uint256_t::wstring(size_t base, size_t length) const
136{
137 if ((base < 2) || (base > 16))
138 throw std::invalid_argument("Base must be in the range [2, 16]");
139
140 std::wstring out;
141
142 if (!(*this))
143 out = L"0";
144 else
145 {
146 std::pair<uint256_t, uint256_t> qr(*this, 0);
147 do
148 {
149 qr = uint256_t::divmod(qr.first, uint256_t(base));
150 out = L"0123456789abcdef"[(uint8_t)qr.second] + out;
151 } while (qr.first != 0);
152 }
153
154 if (out.size() < length)
155 out = std::wstring(length - out.size(), L'0') + out;
156
157 return out;
158}
159
160std::pair<uint256_t, uint256_t> uint256_t::divmod(const uint256_t& x, const uint256_t& y)
161{
162 if (y == 0)
163 throw std::domain_error("Division by 0");
164 else if (y == 1)
165 return std::pair<uint256_t, uint256_t>(x, 0);
166 else if (x == y)
167 return std::pair<uint256_t, uint256_t>(1, 0);
168 else if ((x == 0) || (x < y))
169 return std::pair<uint256_t, uint256_t>(0, x);
170
171 std::pair<uint256_t, uint256_t> result(0, x);
172 uint256_t delta = uint256_t(x.bits() - y.bits());
173 uint256_t copyd = y << delta;
174 uint256_t adder = 1 << delta;
175
176 if (copyd > result.second)
177 {
178 copyd >>= 1;
179 adder >>= 1;
180 }
181
182 while (result.second >= y)
183 {
184 if (result.second >= copyd)
185 {
186 result.second -= copyd;
187 result.first |= adder;
188 }
189 copyd >>= 1;
190 adder >>= 1;
191 }
192
193 return result;
194}
195
196} // namespace CppCommon
Unsigned 128-bit integer type.
Definition uint128.h:28
uint64_t upper() const noexcept
Get the upper part of the 128-bit integer.
Definition uint128.h:258
Unsigned 256-bit integer type.
Definition uint256.h:21
size_t bits() const noexcept
Get the count of bits.
Definition uint256.cpp:83
uint128_t lower() const noexcept
Get the lower part of the 256-bit integer.
Definition uint256.h:304
uint128_t upper() const noexcept
Get the upper part of the 256-bit integer.
Definition uint256.h:302
std::wstring wstring(size_t base=10, size_t length=0) const
Get wide string from the current 128-bit integer.
Definition uint256.cpp:135
std::string string(size_t base=10, size_t length=0) const
Get string from the current 128-bit integer.
Definition uint256.cpp:110
static std::pair< uint256_t, uint256_t > divmod(const uint256_t &x, const uint256_t &y)
Calculate quotient and remainder when dividing X by Y.
Definition uint256.cpp:160
uint256_t() noexcept
Definition uint256.inl:11
C++ Common project definitions.
uint128_t operator*(const uint128_t &value1, const uint128_t &value2) noexcept
Definition uint128.cpp:13
std::ostream & operator<<(std::ostream &os, const uint128_t &value)
Definition uint128.inl:155
uint128_t operator>>(const uint128_t &value1, const uint128_t &value2) noexcept
Definition uint128.cpp:76
Unsigned 256-bit integer type definition.