Add multiplication and division to uint160/uint256
This commit is contained in:
parent
4d480c8a3f
commit
a7031507e6
@ -482,6 +482,77 @@ BOOST_AUTO_TEST_CASE( plusMinus )
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( multiply )
|
||||
{
|
||||
BOOST_CHECK((R1L * R1L).ToString() == "62a38c0486f01e45879d7910a7761bf30d5237e9873f9bff3642a732c4d84f10");
|
||||
BOOST_CHECK((R1L * R2L).ToString() == "de37805e9986996cfba76ff6ba51c008df851987d9dd323f0e5de07760529c40");
|
||||
BOOST_CHECK((R1L * ZeroL) == ZeroL);
|
||||
BOOST_CHECK((R1L * OneL) == R1L);
|
||||
BOOST_CHECK((R1L * MaxL) == -R1L);
|
||||
BOOST_CHECK((R2L * R1L) == (R1L * R2L));
|
||||
BOOST_CHECK((R2L * R2L).ToString() == "ac8c010096767d3cae5005dec28bb2b45a1d85ab7996ccd3e102a650f74ff100");
|
||||
BOOST_CHECK((R2L * ZeroL) == ZeroL);
|
||||
BOOST_CHECK((R2L * OneL) == R2L);
|
||||
BOOST_CHECK((R2L * MaxL) == -R2L);
|
||||
|
||||
BOOST_CHECK((R1S * R1S).ToString() == "a7761bf30d5237e9873f9bff3642a732c4d84f10");
|
||||
BOOST_CHECK((R1S * R2S).ToString() == "ba51c008df851987d9dd323f0e5de07760529c40");
|
||||
BOOST_CHECK((R1S * ZeroS) == ZeroS);
|
||||
BOOST_CHECK((R1S * OneS) == R1S);
|
||||
BOOST_CHECK((R1S * MaxS) == -R1S);
|
||||
BOOST_CHECK((R2S * R1S) == (R1S * R2S));
|
||||
BOOST_CHECK((R2S * R2S).ToString() == "c28bb2b45a1d85ab7996ccd3e102a650f74ff100");
|
||||
BOOST_CHECK((R2S * ZeroS) == ZeroS);
|
||||
BOOST_CHECK((R2S * OneS) == R2S);
|
||||
BOOST_CHECK((R2S * MaxS) == -R2S);
|
||||
|
||||
BOOST_CHECK(MaxL * MaxL == OneL);
|
||||
BOOST_CHECK(MaxS * MaxS == OneS);
|
||||
|
||||
BOOST_CHECK((R1L * 0) == 0);
|
||||
BOOST_CHECK((R1L * 1) == R1L);
|
||||
BOOST_CHECK((R1L * 3).ToString() == "7759b1c0ed14047f961ad09b20ff83687876a0181a367b813634046f91def7d4");
|
||||
BOOST_CHECK((R2L * 0x87654321UL).ToString() == "23f7816e30c4ae2017257b7a0fa64d60402f5234d46e746b61c960d09a26d070");
|
||||
BOOST_CHECK((R1S * 0) == 0);
|
||||
BOOST_CHECK((R1S * 1) == R1S);
|
||||
BOOST_CHECK((R1S * 7).ToString() == "f7a987f3c3bf758d927f202d7e795faeff084244");
|
||||
BOOST_CHECK((R2S * 0xFFFFFFFFUL).ToString() == "1c6f6c930353e17f7d6127213bb18d2883e2cd90");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE( divide )
|
||||
{
|
||||
uint256 D1L("AD7133AC1977FA2B7");
|
||||
uint256 D2L("ECD751716");
|
||||
BOOST_CHECK((R1L / D1L).ToString() == "00000000000000000b8ac01106981635d9ed112290f8895545a7654dde28fb3a");
|
||||
BOOST_CHECK((R1L / D2L).ToString() == "000000000873ce8efec5b67150bad3aa8c5fcb70e947586153bf2cec7c37c57a");
|
||||
BOOST_CHECK(R1L / OneL == R1L);
|
||||
BOOST_CHECK(R1L / MaxL == ZeroL);
|
||||
BOOST_CHECK(MaxL / R1L == 2);
|
||||
BOOST_CHECK_THROW(R1L / ZeroL, uint_error);
|
||||
BOOST_CHECK((R2L / D1L).ToString() == "000000000000000013e1665895a1cc981de6d93670105a6b3ec3b73141b3a3c5");
|
||||
BOOST_CHECK((R2L / D2L).ToString() == "000000000e8f0abe753bb0afe2e9437ee85d280be60882cf0bd1aaf7fa3cc2c4");
|
||||
BOOST_CHECK(R2L / OneL == R2L);
|
||||
BOOST_CHECK(R2L / MaxL == ZeroL);
|
||||
BOOST_CHECK(MaxL / R2L == 1);
|
||||
BOOST_CHECK_THROW(R2L / ZeroL, uint_error);
|
||||
|
||||
uint160 D1S("D3C5EDCDEA54EB92679F0A4B4");
|
||||
uint160 D2S("13037");
|
||||
BOOST_CHECK((R1S / D1S).ToString() == "0000000000000000000000000db9af3beade6c02");
|
||||
BOOST_CHECK((R1S / D2S).ToString() == "000098dfb6cc40ca592bf74366794f298ada205c");
|
||||
BOOST_CHECK(R1S / OneS == R1S);
|
||||
BOOST_CHECK(R1S / MaxS == ZeroS);
|
||||
BOOST_CHECK(MaxS / R1S == 1);
|
||||
BOOST_CHECK_THROW(R1S / ZeroS, uint_error);
|
||||
BOOST_CHECK((R2S / D1S).ToString() == "0000000000000000000000000c5608e781182047");
|
||||
BOOST_CHECK((R2S / D2S).ToString() == "00008966751b7187c3c67c1fda5cea7db2c1c069");
|
||||
BOOST_CHECK(R2S / OneS == R2S);
|
||||
BOOST_CHECK(R2S / MaxS == ZeroS);
|
||||
BOOST_CHECK(MaxS / R2S == 1);
|
||||
BOOST_CHECK_THROW(R2S / ZeroS, uint_error);
|
||||
}
|
||||
|
||||
|
||||
bool almostEqual(double d1, double d2)
|
||||
{
|
||||
return fabs(d1-d2) <= 4*fabs(d1)*std::numeric_limits<double>::epsilon();
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user