Boost logo

Boost-Commit :

From: zeux_at_[hidden]
Date: 2007-05-17 16:18:17


Author: zeux
Date: 2007-05-17 16:18:16 EDT (Thu, 17 May 2007)
New Revision: 4102
URL: http://svn.boost.org/trac/boost/changeset/4102

Log:
Fixed warnings, near-proper can_convert_to and to_number + unit tests (not complete), fixed todo

Text files modified:
   sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp | 67 +++++++++++++++++++++++++++++++++++++--
   sandbox/SOC/2007/bigint/libs/bigint/test/bigint_simple_test.cpp | 40 +++++++++++++++++++++++
   sandbox/SOC/2007/bigint/libs/bigint/todo.txt | 4 +-
   3 files changed, 104 insertions(+), 7 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-17 16:18:16 EDT (Thu, 17 May 2007)
@@ -10,6 +10,8 @@
 #ifndef BOOST_BIGINT_BIGINT_GMP_HPP
 #define BOOST_BIGINT_BIGINT_GMP_HPP
 
+#include <limits>
+
 #include <boost/scoped_array.hpp>
 
 #include <boost/bigint/bigint_util.hpp>
@@ -71,7 +73,7 @@
                 {
                         mp_size_t size;
                         
- data->_mp_d[0] = number & GMP_NUMB_MAX;
+ data->_mp_d[0] = static_cast<mp_limb_t>(number & GMP_NUMB_MAX);
                         size = number != 0;
                         
                         if (number > GMP_NUMB_MAX)
@@ -82,7 +84,7 @@
                                 
                                 while (number > 0)
                                 {
- data->_mp_d[size++] = number & GMP_NUMB_MAX;
+ data->_mp_d[size++] = static_cast<mp_limb_t>(number & GMP_NUMB_MAX);
                                         number >>= GMP_NUMB_BITS;
                                 }
                         }
@@ -149,7 +151,7 @@
                         
                         size_t d_bits = detail::bigint::get_bit_count(d_size, base);
                         
- mpz_init2(data, d_bits);
+ mpz_init2(data, static_cast<unsigned long>(d_bits));
                         data->_mp_size = sign * mpn_set_str(data->_mp_d, d.get(), d_size, base);
                 }
 
@@ -261,15 +263,70 @@
                         std::wstring result(s.get(), s.get() + s_size);
                         return result;
                 }
+
+ template <typename T> bool _can_convert_to_signed() const
+ {
+ switch (mpz_sgn(data))
+ {
+ case 1: return _can_convert_to_unsigned<T>(); // Reuse
+ case 0: return true;
+ }
+
+ 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
+
+ for (int i = 0; i < count; ++i)
+ {
+ if (max_value < data->_mp_d[i]) return false;
+ max_value >>= GMP_NUMB_BITS;
+ }
+
+ return true;
+ }
+
+ template <typename T> bool _can_convert_to_unsigned() const
+ {
+ switch (mpz_sgn(data))
+ {
+ case 0: return true;
+ case -1: return false; // Negative numbers can't fit into unsigned types
+ }
+
+ T max_value = (std::numeric_limits<T>::max)();
+
+ for (int i = 0; i < data->_mp_size; ++i)
+ {
+ if (max_value < data->_mp_d[i]) return false;
+ max_value >>= GMP_NUMB_BITS;
+ }
+
+ return true;
+ }
 
                 template <typename T> bool can_convert_to() const
                 {
- return mpz_fits_sint_p(data) != 0;
+ // Only integer types supported
+ if (!std::numeric_limits<T>::is_integer) return false;
+
+ return std::numeric_limits<T>::is_signed ? _can_convert_to_signed<T>() : _can_convert_to_unsigned<T>();
                 }
                 
                 template <typename T> T to_number() const
                 {
- return mpz_get_si(data);
+ if (!std::numeric_limits<T>::is_integer) return T();
+
+ boost::uint64_t value = 0;
+
+ int count = data->_mp_size >= 0 ? data->_mp_size : -data->_mp_size; // abs() does not work on MSVC8
+
+ for (int i = 0; i < count; ++i)
+ {
+ value <<= GMP_NUMB_BITS;
+ value += data->_mp_d[i];
+ }
+
+ return data->_mp_size >= 0 ? static_cast<T>(value) : static_cast<T>(-static_cast<boost::int64_t>(value));
                 }
 
                 bool is_zero() const

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-17 16:18:16 EDT (Thu, 17 May 2007)
@@ -75,6 +75,46 @@
         oss << std::dec << bigint(10) << std::hex << bigint(10) << std::oct << bigint(10);
 
         BOOST_CHECK_EQUAL(oss.str(), "10a12");
+
+ // can_convert_to
+ BOOST_CHECK( bigint("127").can_convert_to<char>());
+ BOOST_CHECK(!bigint("128").can_convert_to<char>());
+ BOOST_CHECK(!bigint("129").can_convert_to<char>());
+
+ BOOST_CHECK( bigint("-127").can_convert_to<char>());
+ BOOST_CHECK( bigint("-128").can_convert_to<char>());
+ BOOST_CHECK(!bigint("-129").can_convert_to<char>());
+
+ BOOST_CHECK( bigint("127").can_convert_to<unsigned char>());
+ BOOST_CHECK( bigint("128").can_convert_to<unsigned char>());
+ BOOST_CHECK( bigint("129").can_convert_to<unsigned char>());
+
+ BOOST_CHECK( bigint("255").can_convert_to<unsigned char>());
+ BOOST_CHECK(!bigint("256").can_convert_to<unsigned char>());
+
+ BOOST_CHECK( bigint("ffffffff", 16).can_convert_to<unsigned int>());
+ BOOST_CHECK(!bigint("100000000", 16).can_convert_to<unsigned int>());
+
+ BOOST_CHECK( bigint("7fffffff", 16).can_convert_to<int>());
+ BOOST_CHECK(!bigint("80000000", 16).can_convert_to<int>());
+
+ BOOST_CHECK( bigint("-7fffffff", 16).can_convert_to<int>());
+ BOOST_CHECK( bigint("-80000000", 16).can_convert_to<int>());
+ BOOST_CHECK(!bigint("-80000001", 16).can_convert_to<int>());
+
+ BOOST_CHECK( bigint("ffffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( bigint("100000000", 16).can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( bigint("7fffffff", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( bigint("80000000", 16).can_convert_to<boost::int64_t>());
+
+ BOOST_CHECK( bigint("-7fffffff", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( bigint("-80000000", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( bigint("-80000001", 16).can_convert_to<boost::int64_t>());
+
+ 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);
 }
 
 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-17 16:18:16 EDT (Thu, 17 May 2007)
@@ -71,8 +71,8 @@
 + 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: needs implementing
+* proper converting to numbers (including 64-bit)
+Status: implemented, but need Jeff's assistance with make_unsigned<T>
 
 - check semantics of bitwise and shift operations for negative numbers
 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