CppCommon  1.0.4.1
C++ Common Library
uint256.cpp
Go to the documentation of this file.
1 
9 #include "common/uint256.h"
10 
11 namespace CppCommon {
12 
13 uint256_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 
47 uint256_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 
65 uint256_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 
83 size_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 
110 std::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 
135 std::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 
160 std::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.
Definition: token_bucket.h:15
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:13
uint128_t operator>>(const uint128_t &value1, const uint128_t &value2) noexcept
Definition: uint128.cpp:76
Unsigned 256-bit integer type definition.