aboutsummaryrefslogtreecommitdiff
path: root/src/uint256.h
diff options
context:
space:
mode:
authorPieter Wuille <pieter.wuille@gmail.com>2014-04-20 01:03:19 +0200
committerPieter Wuille <pieter.wuille@gmail.com>2014-05-09 16:39:48 +0200
commita7031507e647da0723bf289dadba10ef1a50f278 (patch)
treee9917535b5264cac098fe89ced31b9570007f2b5 /src/uint256.h
parent4d480c8a3fe3c58eeb083ea544c6f9e991606692 (diff)
Add multiplication and division to uint160/uint256
Diffstat (limited to 'src/uint256.h')
-rw-r--r--src/uint256.h70
1 files changed, 70 insertions, 0 deletions
diff --git a/src/uint256.h b/src/uint256.h
index b6365bb36b..7b17694eb2 100644
--- a/src/uint256.h
+++ b/src/uint256.h
@@ -222,6 +222,57 @@ public:
return *this;
}
+ base_uint& operator*=(uint32_t b32)
+ {
+ uint64_t carry = 0;
+ for (int i = 0; i < WIDTH; i++)
+ {
+ uint64_t n = carry + (uint64_t)b32 * pn[i];
+ pn[i] = n & 0xffffffff;
+ carry = n >> 32;
+ }
+ return *this;
+ }
+
+ base_uint& operator*=(const base_uint& b)
+ {
+ base_uint a = *this;
+ *this = 0;
+ for (int j = 0; j < WIDTH; j++) {
+ uint64_t carry = 0;
+ for (int i = 0; i + j < WIDTH; i++) {
+ uint64_t n = carry + pn[i + j] + (uint64_t)a.pn[j] * b.pn[i];
+ pn[i + j] = n & 0xffffffff;
+ carry = n >> 32;
+ }
+ }
+ return *this;
+ }
+
+ base_uint& operator/=(const base_uint& b)
+ {
+ base_uint div = b; // make a copy, so we can shift.
+ base_uint num = *this; // make a copy, so we can subtract.
+ *this = 0; // the quotient.
+ int num_bits = num.bits();
+ int div_bits = div.bits();
+ if (div_bits == 0)
+ throw uint_error("Division by zero");
+ if (div_bits > num_bits) // the result is certainly 0.
+ return *this;
+ int shift = num_bits - div_bits;
+ div <<= shift; // shift so that div and nun align.
+ while (shift >= 0) {
+ if (num >= div) {
+ num -= div;
+ pn[shift / 32] |= (1 << (shift & 31)); // set a bit of the result.
+ }
+ div >>= 1; // shift back.
+ shift--;
+ }
+ // num now contains the remainder of the division.
+ return *this;
+ }
base_uint& operator++()
{
@@ -338,11 +389,14 @@ public:
friend inline const base_uint operator+(const base_uint& a, const base_uint& b) { return base_uint(a) += b; }
friend inline const base_uint operator-(const base_uint& a, const base_uint& b) { return base_uint(a) -= b; }
+ friend inline const base_uint operator*(const base_uint& a, const base_uint& b) { return base_uint(a) *= b; }
+ friend inline const base_uint operator/(const base_uint& a, const base_uint& b) { return base_uint(a) /= b; }
friend inline const base_uint operator|(const base_uint& a, const base_uint& b) { return base_uint(a) |= b; }
friend inline const base_uint operator&(const base_uint& a, const base_uint& b) { return base_uint(a) &= b; }
friend inline const base_uint operator^(const base_uint& a, const base_uint& b) { return base_uint(a) ^= b; }
friend inline const base_uint operator>>(const base_uint& a, int shift) { return base_uint(a) >>= shift; }
friend inline const base_uint operator<<(const base_uint& a, int shift) { return base_uint(a) <<= shift; }
+ friend inline const base_uint operator*(const base_uint& a, uint32_t b) { return base_uint(a) *= b; }
std::string GetHex() const
{
@@ -417,6 +471,22 @@ public:
return sizeof(pn);
}
+ // Returns the position of the highest bit set plus one, or zero if the
+ // value is zero.
+ unsigned int bits() const
+ {
+ for (int pos = WIDTH-1; pos >= 0; pos--) {
+ if (pn[pos]) {
+ for (int bits = 31; bits > 0; bits--) {
+ if (pn[pos] & 1<<bits)
+ return 32*pos + bits + 1;
+ }
+ return 32*pos + 1;
+ }
+ }
+ return 0;
+ }
+
uint64_t GetLow64() const
{
assert(WIDTH >= 2);