diff options
author | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-06-30 11:26:55 +0200 |
---|---|---|
committer | Wladimir J. van der Laan <laanwj@gmail.com> | 2014-06-30 11:27:46 +0200 |
commit | ac26571d2b118b5df9e7fd2585ecac1eeb7ed94d (patch) | |
tree | 811cace235d41a40fe2a1eacce734df9c1ac9f55 /src | |
parent | eba8c44fdd62f42cb69088c5a03dcf5db9fcc8a8 (diff) | |
parent | de79aaa7a9ad07664461ee8735299aa68c630969 (diff) |
Merge pull request #4437
de79aaa Move non-trivial uint256.h methods to uint256.cpp (Pieter Wuille)
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/uint256.cpp | 292 | ||||
-rw-r--r-- | src/uint256.h | 262 | ||||
-rw-r--r-- | src/util.cpp | 5 | ||||
-rw-r--r-- | src/util.h | 1 |
5 files changed, 316 insertions, 245 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 3643e60201..9c7b294d35 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -192,6 +192,7 @@ libbitcoin_util_a_SOURCES = \ chainparamsbase.cpp \ rpcprotocol.cpp \ sync.cpp \ + uint256.cpp \ util.cpp \ version.cpp \ compat/glibc_sanity.cpp \ diff --git a/src/uint256.cpp b/src/uint256.cpp new file mode 100644 index 0000000000..3392f1e9bc --- /dev/null +++ b/src/uint256.cpp @@ -0,0 +1,292 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT/X11 software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "uint256.h" +#include "util.h" + +#include <stdio.h> +#include <string.h> + +template<unsigned int BITS> +base_uint<BITS>::base_uint(const std::string& str) +{ + SetHex(str); +} + +template<unsigned int BITS> +base_uint<BITS>::base_uint(const std::vector<unsigned char>& vch) +{ + if (vch.size() != sizeof(pn)) + throw uint_error("Converting vector of wrong size to base_uint"); + memcpy(pn, &vch[0], sizeof(pn)); +} + +template<unsigned int BITS> +base_uint<BITS>& base_uint<BITS>::operator<<=(unsigned int shift) +{ + base_uint<BITS> a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i+k+1 < WIDTH && shift != 0) + pn[i+k+1] |= (a.pn[i] >> (32-shift)); + if (i+k < WIDTH) + pn[i+k] |= (a.pn[i] << shift); + } + return *this; +} + +template<unsigned int BITS> +base_uint<BITS>& base_uint<BITS>::operator>>=(unsigned int shift) +{ + base_uint<BITS> a(*this); + for (int i = 0; i < WIDTH; i++) + pn[i] = 0; + int k = shift / 32; + shift = shift % 32; + for (int i = 0; i < WIDTH; i++) { + if (i-k-1 >= 0 && shift != 0) + pn[i-k-1] |= (a.pn[i] << (32-shift)); + if (i-k >= 0) + pn[i-k] |= (a.pn[i] >> shift); + } + return *this; +} + +template<unsigned int BITS> +base_uint<BITS>& base_uint<BITS>::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; +} + +template<unsigned int BITS> +base_uint<BITS>& base_uint<BITS>::operator*=(const base_uint& b) +{ + base_uint<BITS> 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; +} + +template<unsigned int BITS> +base_uint<BITS>& base_uint<BITS>::operator/=(const base_uint& b) +{ + base_uint<BITS> div = b; // make a copy, so we can shift. + base_uint<BITS> 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; +} + +template<unsigned int BITS> +int base_uint<BITS>::CompareTo(const base_uint<BITS>& b) const { + for (int i = WIDTH-1; i >= 0; i--) { + if (pn[i] < b.pn[i]) + return -1; + if (pn[i] > b.pn[i]) + return 1; + } + return 0; +} + +template<unsigned int BITS> +bool base_uint<BITS>::EqualTo(uint64_t b) const { + for (int i = WIDTH-1; i >= 2; i--) { + if (pn[i]) + return false; + } + if (pn[1] != (b >> 32)) + return false; + if (pn[0] != (b & 0xfffffffful)) + return false; + return true; +} + +template<unsigned int BITS> +double base_uint<BITS>::getdouble() const +{ + double ret = 0.0; + double fact = 1.0; + for (int i = 0; i < WIDTH; i++) { + ret += fact * pn[i]; + fact *= 4294967296.0; + } + return ret; +} + +template<unsigned int BITS> +std::string base_uint<BITS>::GetHex() const +{ + char psz[sizeof(pn)*2 + 1]; + for (unsigned int i = 0; i < sizeof(pn); i++) + sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); + return std::string(psz, psz + sizeof(pn)*2); +} + +template<unsigned int BITS> +void base_uint<BITS>::SetHex(const char* psz) +{ + memset(pn,0,sizeof(pn)); + + // skip leading spaces + while (isspace(*psz)) + psz++; + + // skip 0x + if (psz[0] == '0' && tolower(psz[1]) == 'x') + psz += 2; + + // hex string to uint + const char* pbegin = psz; + while (::HexDigit(*psz) != -1) + psz++; + psz--; + unsigned char* p1 = (unsigned char*)pn; + unsigned char* pend = p1 + WIDTH * 4; + while (psz >= pbegin && p1 < pend) { + *p1 = ::HexDigit(*psz--); + if (psz >= pbegin) { + *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); + p1++; + } + } +} + +template<unsigned int BITS> +void base_uint<BITS>::SetHex(const std::string& str) +{ + SetHex(str.c_str()); +} + +template<unsigned int BITS> +std::string base_uint<BITS>::ToString() const +{ + return (GetHex()); +} + +template<unsigned int BITS> +unsigned int base_uint<BITS>::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; +} + +// Explicit instantiations for base_uint<160> +template base_uint<160>::base_uint(const std::string&); +template base_uint<160>::base_uint(const std::vector<unsigned char>&); +template base_uint<160>& base_uint<160>::operator<<=(unsigned int); +template base_uint<160>& base_uint<160>::operator>>=(unsigned int); +template base_uint<160>& base_uint<160>::operator*=(uint32_t b32); +template base_uint<160>& base_uint<160>::operator*=(const base_uint<160>& b); +template base_uint<160>& base_uint<160>::operator/=(const base_uint<160>& b); +template int base_uint<160>::CompareTo(const base_uint<160>&) const; +template bool base_uint<160>::EqualTo(uint64_t) const; +template double base_uint<160>::getdouble() const; +template std::string base_uint<160>::GetHex() const; +template std::string base_uint<160>::ToString() const; +template void base_uint<160>::SetHex(const char*); +template void base_uint<160>::SetHex(const std::string&); +template unsigned int base_uint<160>::bits() const; + +// Explicit instantiations for base_uint<256> +template base_uint<256>::base_uint(const std::string&); +template base_uint<256>::base_uint(const std::vector<unsigned char>&); +template base_uint<256>& base_uint<256>::operator<<=(unsigned int); +template base_uint<256>& base_uint<256>::operator>>=(unsigned int); +template base_uint<256>& base_uint<256>::operator*=(uint32_t b32); +template base_uint<256>& base_uint<256>::operator*=(const base_uint<256>& b); +template base_uint<256>& base_uint<256>::operator/=(const base_uint<256>& b); +template int base_uint<256>::CompareTo(const base_uint<256>&) const; +template bool base_uint<256>::EqualTo(uint64_t) const; +template double base_uint<256>::getdouble() const; +template std::string base_uint<256>::GetHex() const; +template std::string base_uint<256>::ToString() const; +template void base_uint<256>::SetHex(const char*); +template void base_uint<256>::SetHex(const std::string&); +template unsigned int base_uint<256>::bits() const; + +// This implementation directly uses shifts instead of going +// through an intermediate MPI representation. +uint256& uint256::SetCompact(uint32_t nCompact, bool *pfNegative, bool *pfOverflow) +{ + int nSize = nCompact >> 24; + uint32_t nWord = nCompact & 0x007fffff; + if (nSize <= 3) { + nWord >>= 8*(3-nSize); + *this = nWord; + } else { + *this = nWord; + *this <<= 8*(nSize-3); + } + if (pfNegative) + *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; + if (pfOverflow) + *pfOverflow = nWord != 0 && ((nSize > 34) || + (nWord > 0xff && nSize > 33) || + (nWord > 0xffff && nSize > 32)); + return *this; +} + +uint32_t uint256::GetCompact(bool fNegative) const +{ + int nSize = (bits() + 7) / 8; + uint32_t nCompact = 0; + if (nSize <= 3) { + nCompact = GetLow64() << 8*(3-nSize); + } else { + uint256 bn = *this >> 8*(nSize-3); + nCompact = bn.GetLow64(); + } + // The 0x00800000 bit denotes the sign. + // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. + if (nCompact & 0x00800000) { + nCompact >>= 8; + nSize++; + } + assert((nCompact & ~0x007fffff) == 0); + assert(nSize < 256); + nCompact |= nSize << 24; + nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); + return nCompact; +} diff --git a/src/uint256.h b/src/uint256.h index 1acedd14bf..82db7758c9 100644 --- a/src/uint256.h +++ b/src/uint256.h @@ -9,18 +9,9 @@ #include <assert.h> #include <stdexcept> #include <stdint.h> -#include <stdio.h> #include <string> -#include <string.h> #include <vector> -extern const signed char p_util_hexdigit[256]; // defined in util.cpp - -inline signed char HexDigit(char c) -{ - return p_util_hexdigit[(unsigned char)c]; -} - class uint_error : public std::runtime_error { public: explicit uint_error(const std::string& str) : std::runtime_error(str) {} @@ -62,17 +53,8 @@ public: pn[i] = 0; } - explicit base_uint(const std::string& str) - { - SetHex(str); - } - - explicit base_uint(const std::vector<unsigned char>& vch) - { - if (vch.size() != sizeof(pn)) - throw uint_error("Converting vector of wrong size to base_uint"); - memcpy(pn, &vch[0], sizeof(pn)); - } + explicit base_uint(const std::string& str); + explicit base_uint(const std::vector<unsigned char>& vch); bool operator!() const { @@ -99,16 +81,7 @@ public: return ret; } - double getdouble() const - { - double ret = 0.0; - double fact = 1.0; - for (int i = 0; i < WIDTH; i++) { - ret += fact * pn[i]; - fact *= 4294967296.0; - } - return ret; - } + double getdouble() const; base_uint& operator=(uint64_t b) { @@ -154,39 +127,8 @@ public: return *this; } - base_uint& operator<<=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i+k+1 < WIDTH && shift != 0) - pn[i+k+1] |= (a.pn[i] >> (32-shift)); - if (i+k < WIDTH) - pn[i+k] |= (a.pn[i] << shift); - } - return *this; - } - - base_uint& operator>>=(unsigned int shift) - { - base_uint a(*this); - for (int i = 0; i < WIDTH; i++) - pn[i] = 0; - int k = shift / 32; - shift = shift % 32; - for (int i = 0; i < WIDTH; i++) - { - if (i-k-1 >= 0 && shift != 0) - pn[i-k-1] |= (a.pn[i] << (32-shift)); - if (i-k >= 0) - pn[i-k] |= (a.pn[i] >> shift); - } - return *this; - } + base_uint& operator<<=(unsigned int shift); + base_uint& operator>>=(unsigned int shift); base_uint& operator+=(const base_uint& b) { @@ -222,57 +164,9 @@ 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*=(uint32_t b32); + base_uint& operator*=(const base_uint& b); + base_uint& operator/=(const base_uint& b); base_uint& operator++() { @@ -308,27 +202,8 @@ public: return ret; } - int CompareTo(const base_uint& b) const { - for (int i = base_uint::WIDTH-1; i >= 0; i--) { - if (pn[i] < b.pn[i]) - return -1; - if (pn[i] > b.pn[i]) - return 1; - } - return 0; - } - - bool EqualTo(uint64_t b) const { - for (int i = base_uint::WIDTH-1; i >= 2; i--) { - if (pn[i]) - return false; - } - if (pn[1] != (b >> 32)) - return false; - if (pn[0] != (b & 0xfffffffful)) - return false; - return true; - } + int CompareTo(const base_uint& b) const; + bool EqualTo(uint64_t b) const; 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; } @@ -349,53 +224,10 @@ public: friend inline bool operator==(const base_uint& a, uint64_t b) { return a.EqualTo(b); } friend inline bool operator!=(const base_uint& a, uint64_t b) { return !a.EqualTo(b); } - std::string GetHex() const - { - char psz[sizeof(pn)*2 + 1]; - for (unsigned int i = 0; i < sizeof(pn); i++) - sprintf(psz + i*2, "%02x", ((unsigned char*)pn)[sizeof(pn) - i - 1]); - return std::string(psz, psz + sizeof(pn)*2); - } - - void SetHex(const char* psz) - { - memset(pn,0,sizeof(pn)); - - // skip leading spaces - while (isspace(*psz)) - psz++; - - // skip 0x - if (psz[0] == '0' && tolower(psz[1]) == 'x') - psz += 2; - - // hex string to uint - const char* pbegin = psz; - while (::HexDigit(*psz) != -1) - psz++; - psz--; - unsigned char* p1 = (unsigned char*)pn; - unsigned char* pend = p1 + WIDTH * 4; - while (psz >= pbegin && p1 < pend) - { - *p1 = ::HexDigit(*psz--); - if (psz >= pbegin) - { - *p1 |= ((unsigned char)::HexDigit(*psz--) << 4); - p1++; - } - } - } - - void SetHex(const std::string& str) - { - SetHex(str.c_str()); - } - - std::string ToString() const - { - return (GetHex()); - } + std::string GetHex() const; + void SetHex(const char* psz); + void SetHex(const std::string& str); + std::string ToString() const; unsigned char* begin() { @@ -424,19 +256,7 @@ public: // 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; - } + unsigned int bits() const; uint64_t GetLow64() const { @@ -500,56 +320,8 @@ public: // targets, which are unsigned 256bit quantities. Thus, all the // complexities of the sign bit and using base 256 are probably an // implementation accident. - // - // This implementation directly uses shifts instead of going - // through an intermediate MPI representation. - uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL) - { - int nSize = nCompact >> 24; - uint32_t nWord = nCompact & 0x007fffff; - if (nSize <= 3) - { - nWord >>= 8*(3-nSize); - *this = nWord; - } - else - { - *this = nWord; - *this <<= 8*(nSize-3); - } - if (pfNegative) - *pfNegative = nWord != 0 && (nCompact & 0x00800000) != 0; - if (pfOverflow) - *pfOverflow = nWord != 0 && ((nSize > 34) || - (nWord > 0xff && nSize > 33) || - (nWord > 0xffff && nSize > 32)); - return *this; - } - - uint32_t GetCompact(bool fNegative = false) const - { - int nSize = (bits() + 7) / 8; - uint32_t nCompact = 0; - if (nSize <= 3) - nCompact = GetLow64() << 8*(3-nSize); - else - { - uint256 bn = *this >> 8*(nSize-3); - nCompact = bn.GetLow64(); - } - // The 0x00800000 bit denotes the sign. - // Thus, if it is already set, divide the mantissa by 256 and increase the exponent. - if (nCompact & 0x00800000) - { - nCompact >>= 8; - nSize++; - } - assert((nCompact & ~0x007fffff) == 0); - assert(nSize < 256); - nCompact |= nSize << 24; - nCompact |= (fNegative && (nCompact & 0x007fffff) ? 0x00800000 : 0); - return nCompact; - } + uint256& SetCompact(uint32_t nCompact, bool *pfNegative = NULL, bool *pfOverflow = NULL); + uint32_t GetCompact(bool fNegative = false) const; }; #endif diff --git a/src/util.cpp b/src/util.cpp index 9591372f91..5a8f85ade7 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -420,6 +420,11 @@ const signed char p_util_hexdigit[256] = -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, }; +signed char HexDigit(char c) +{ + return p_util_hexdigit[(unsigned char)c]; +} + bool IsHex(const string& str) { BOOST_FOREACH(char c, str) diff --git a/src/util.h b/src/util.h index 6057c72e66..707b8f2d76 100644 --- a/src/util.h +++ b/src/util.h @@ -156,6 +156,7 @@ bool ParseMoney(const char* pszIn, int64_t& nRet); std::string SanitizeString(const std::string& str); std::vector<unsigned char> ParseHex(const char* psz); std::vector<unsigned char> ParseHex(const std::string& str); +signed char HexDigit(char c); bool IsHex(const std::string& str); std::vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid = NULL); std::string DecodeBase64(const std::string& str); |