diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-04-20 01:03:19 +0200 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-05-09 16:39:48 +0200 |
commit | a7031507e647da0723bf289dadba10ef1a50f278 (patch) | |
tree | e9917535b5264cac098fe89ced31b9570007f2b5 /src/uint256.h | |
parent | 4d480c8a3fe3c58eeb083ea544c6f9e991606692 (diff) |
Add multiplication and division to uint160/uint256
Diffstat (limited to 'src/uint256.h')
-rw-r--r-- | src/uint256.h | 70 |
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); |