|
Boost-Commit : |
From: zeux_at_[hidden]
Date: 2007-05-19 19:42:05
Author: zeux
Date: 2007-05-19 19:42:04 EDT (Sat, 19 May 2007)
New Revision: 4143
URL: http://svn.boost.org/trac/boost/changeset/4143
Log:
Resolved issues with conversion to numbers (did not need make_unsigned, fixed unit test), implemented <<, >> and pow for 64-bit type properly, investigated negative number behavior, todo changed accordingly
Text files modified:
sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp | 74 +++++++++++++++++++++++++++++++++++++--
sandbox/SOC/2007/bigint/libs/bigint/test/bigint_simple_test.cpp | 12 +++++
sandbox/SOC/2007/bigint/libs/bigint/todo.txt | 14 +++++--
3 files changed, 90 insertions(+), 10 deletions(-)
Modified: sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp
==============================================================================
--- sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp (original)
+++ sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp 2007-05-19 19:42:04 EDT (Sat, 19 May 2007)
@@ -217,12 +217,46 @@
void lshift(const bigint_gmp_implementation& lhs, boost::uint64_t rhs)
{
- mpz_mul_2exp(data, lhs.data, rhs);
+ unsigned long max_arg = (std::numeric_limits<unsigned long>::max)();
+
+ if (rhs <= max_arg)
+ {
+ mpz_mul_2exp(data, lhs.data, static_cast<unsigned long>(rhs));
+ }
+ else
+ {
+ mpz_clear(data);
+ mpz_init_set(data, lhs.data);
+
+ while (rhs > 0)
+ {
+ unsigned long value = (rhs > max_arg) ? max_arg : static_cast<unsigned long>(rhs);
+ mpz_mul_2exp(data, data, value);
+ rhs -= value;
+ }
+ }
}
void rshift(const bigint_gmp_implementation& lhs, boost::uint64_t rhs)
{
- mpz_div_2exp(data, lhs.data, rhs);
+ unsigned long max_arg = (std::numeric_limits<unsigned long>::max)();
+
+ if (rhs <= max_arg)
+ {
+ mpz_div_2exp(data, lhs.data, static_cast<unsigned long>(rhs));
+ }
+ else
+ {
+ mpz_clear(data);
+ mpz_init_set(data, lhs.data);
+
+ while (rhs > 0)
+ {
+ unsigned long value = (rhs > max_arg) ? max_arg : static_cast<unsigned long>(rhs);
+ mpz_div_2exp(data, data, value);
+ rhs -= value;
+ }
+ }
}
void inc()
@@ -274,8 +308,11 @@
boost::uint64_t max_value = static_cast<boost::uint64_t>(-static_cast<boost::int64_t>((std::numeric_limits<T>::min)()));
- int count = data->_mp_size >= 0 ? data->_mp_size : -data->_mp_size; // abs() does not work on MSVC8
+ int count = -data->_mp_size; // we have a negative number
+ if (GMP_NUMB_BITS >= sizeof(boost::uint64_t) * 8) // we're going to have problems with >>= down there - but the check is simple
+ return (count == 1 && max_value >= data->_mp_d[0]);
+
for (int i = 0; i < count; ++i)
{
if (max_value < data->_mp_d[i]) return false;
@@ -293,7 +330,10 @@
case -1: return false; // Negative numbers can't fit into unsigned types
}
- T max_value = (std::numeric_limits<T>::max)();
+ boost::uint64_t max_value = (std::numeric_limits<T>::max)();
+
+ if (GMP_NUMB_BITS >= sizeof(T) * 8) // we're going to have problems with >>= wodn there - but the check is simple
+ return (data->_mp_size == 1 && max_value >= data->_mp_d[0]);
for (int i = 0; i < data->_mp_size; ++i)
{
@@ -341,7 +381,31 @@
void pow(const bigint_gmp_implementation& lhs, boost::uint64_t rhs)
{
- mpz_pow_ui(data, lhs.data, rhs);
+ unsigned long max_arg = (std::numeric_limits<unsigned long>::max)();
+
+ if (rhs <= max_arg)
+ {
+ mpz_pow_ui(data, lhs.data, static_cast<unsigned long>(rhs));
+ }
+ else
+ {
+ mpz_clear(data);
+ mpz_init_set_ui(data, 1);
+
+ mpz_t temp;
+
+ mpz_init(temp);
+
+ while (rhs > 0)
+ {
+ unsigned long value = (rhs > max_arg) ? max_arg : static_cast<unsigned long>(rhs);
+ mpz_pow_ui(temp, lhs.data, value);
+ mpz_mul(data, data, temp);
+ rhs -= value;
+ }
+
+ mpz_clear(temp);
+ }
}
void ldiv(const bigint_gmp_implementation& lhs, const bigint_gmp_implementation& rhs, bigint_gmp_implementation& remainder)
Modified: sandbox/SOC/2007/bigint/libs/bigint/test/bigint_simple_test.cpp
==============================================================================
--- sandbox/SOC/2007/bigint/libs/bigint/test/bigint_simple_test.cpp (original)
+++ sandbox/SOC/2007/bigint/libs/bigint/test/bigint_simple_test.cpp 2007-05-19 19:42:04 EDT (Sat, 19 May 2007)
@@ -36,7 +36,7 @@
b %= a;
BOOST_CHECK_EQUAL(!(a / b), false);
- BOOST_CHECK(a - b);
+ BOOST_CHECK(a);
BOOST_CHECK_EQUAL(a * b, bigint("42258228219342334666689684483132205000478474"));
BOOST_CHECK_EQUAL(!(a / b), 0);
@@ -115,6 +115,16 @@
BOOST_CHECK_EQUAL(bigint("ffffffff", 16).to_number<unsigned int>(), 0xffffffff);
BOOST_CHECK_EQUAL(bigint("7fffffff", 16).to_number<int>(), 0x7fffffff);
BOOST_CHECK_EQUAL(bigint("-80000000", 16).to_number<int>(), -0x80000000);
+
+ // 3 == 11
+ // -3 = 1....1101
+ // 0...01101
+ BOOST_CHECK_EQUAL((bigint("-3") | bigint("1101", 2)).str(2), "-11");
+ BOOST_CHECK_EQUAL((bigint("-3") & bigint("1101", 2)).str(2), "1101");
+ BOOST_CHECK_EQUAL((bigint("-3") ^ bigint("1101", 2)).str(2), "-10000");
+
+ BOOST_CHECK_EQUAL(bigint("-1") << 5, -32);
+ BOOST_CHECK_EQUAL(bigint("-33") >> 3, -5); // 33 is 100001, -33 is 1....1011111, >>3 is 1...1011, which is complement for 101
}
int test_main( int argc, char* argv[] )
Modified: sandbox/SOC/2007/bigint/libs/bigint/todo.txt
==============================================================================
--- sandbox/SOC/2007/bigint/libs/bigint/todo.txt (original)
+++ sandbox/SOC/2007/bigint/libs/bigint/todo.txt 2007-05-19 19:42:04 EDT (Sat, 19 May 2007)
@@ -71,11 +71,17 @@
+ proper 64-bit support for converting to bigint (implement one of suggestions given for the request at gmp devlist)
Status: implemented
-* proper converting to numbers (including 64-bit)
-Status: implemented, but need Jeff's assistance with make_unsigned<T>
++ proper lshift, rshift and pow functions (work in case of large exponents/bit counts)
+Status: implemented
-- check semantics of bitwise and shift operations for negative numbers
-Status: needs investigation
++ bug fix: problems with unit tests (not all of can_convert_to pass)
+Status: fixed
+
++ proper converting to numbers (including 64-bit)
+Status: implemented
+
++ check semantics of bitwise and shift operations for negative numbers
+Status: investigated, bitwise and shift operations behave as if numbers were 2-complement (as expected).
- what if there is not enough memory for the request - what happens then? Investigate.
Status: needs investigation
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk