Boost logo

Boost-Commit :

From: zeux_at_[hidden]
Date: 2007-06-07 08:14:30


Author: zeux
Date: 2007-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
New Revision: 4481
URL: http://svn.boost.org/trac/boost/changeset/4481

Log:
Added to_number and can_convert_to tests, fixed bugs found with new tests :), modified todo.txt accordingly

Added:
   sandbox/SOC/2007/bigint/libs/bigint/test/can_convert_to.cpp
   sandbox/SOC/2007/bigint/libs/bigint/test/number_conversion.cpp
      - copied, changed from r4480, /sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp
Removed:
   sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp
Text files modified:
   sandbox/SOC/2007/bigint/boost/bigint/bigint_gmp.hpp | 77 ++++++++++++++-------------------------
   sandbox/SOC/2007/bigint/libs/bigint/test/Jamfile.v2 | 3 +
   sandbox/SOC/2007/bigint/libs/bigint/test/number_conversion.cpp | 10 ++++-
   sandbox/SOC/2007/bigint/libs/bigint/todo.txt | 18 ++++++---
   4 files changed, 50 insertions(+), 58 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-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
@@ -298,74 +298,53 @@
                         return result;
                 }
                 
- template <typename T> bool _can_convert_to_signed() const
+ boost::uint64_t _to_uint64() 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; // 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]);
-
+ boost::uint64_t value = 0;
+ boost::uint64_t power = 1;
+
+ 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;
+ value += data->_mp_d[i] * power;
+ power <<= GMP_NUMB_BITS;
                         }
                         
- return true;
+ return value;
                 }
 
- template <typename T> bool _can_convert_to_unsigned() const
+ template <typename T> bool can_convert_to() const
                 {
- switch (mpz_sgn(data))
- {
- case 0: return true;
- case -1: return false; // Negative numbers can't fit into unsigned types
- }
-
- boost::uint64_t max_value = (std::numeric_limits<T>::max)();
+ // Only integer types supported
+ if (!std::numeric_limits<T>::is_integer) return false;
                         
- 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]);
+ boost::uint64_t max_value;
+ int count;
                         
- for (int i = 0; i < data->_mp_size; ++i)
+ if (mpz_sgn(data) < 0)
                         {
- if (max_value < data->_mp_d[i]) return false;
- max_value >>= GMP_NUMB_BITS;
+ count = -data->_mp_size;
+ max_value = static_cast<boost::uint64_t>(-static_cast<boost::int64_t>((std::numeric_limits<T>::min)()));
+ }
+ else
+ {
+ count = data->_mp_size;
+ max_value = (std::numeric_limits<T>::max)();
                         }
-
- return true;
- }
 
- template <typename T> bool can_convert_to() const
- {
- // 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>();
+ if (count * GMP_NUMB_BITS > sizeof(boost::uint64_t) * 8) // we can't fit in uint64 => we won't fit in anything else
+ return false;
+
+ return max_value >= _to_uint64();
                 }
                 
                 template <typename T> T to_number() const
                 {
                         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];
- }
-
+ boost::uint64_t value = _to_uint64();
+
                         return data->_mp_size >= 0 ? static_cast<T>(value) : static_cast<T>(-static_cast<boost::int64_t>(value));
                 }
 

Modified: sandbox/SOC/2007/bigint/libs/bigint/test/Jamfile.v2
==============================================================================
--- sandbox/SOC/2007/bigint/libs/bigint/test/Jamfile.v2 (original)
+++ sandbox/SOC/2007/bigint/libs/bigint/test/Jamfile.v2 2007-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
@@ -10,8 +10,9 @@
   test-suite bigint
    :
    [ run bigint_simple_test.cpp ]
- [ run number_ctors.cpp ]
+ [ run number_conversion.cpp ]
    [ run string_conversion.cpp ]
+ [ run can_convert_to.cpp ]
    ;
 }
 

Added: sandbox/SOC/2007/bigint/libs/bigint/test/can_convert_to.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2007/bigint/libs/bigint/test/can_convert_to.cpp 2007-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
@@ -0,0 +1,158 @@
+/* Boost can_convert_to.cpp test file
+ *
+ * Copyright 2007 Arseny Kapoulkine
+ *
+ * Distributed under the Boost Software License, Version 1.0.
+ * (See accompanying file LICENSE_1_0.txt or
+ * copy at http://www.boost.org/LICENSE_1_0.txt)
+ */
+
+#define BOOST_DISABLE_WIN32
+
+#include <boost/test/included/test_exec_monitor.hpp>
+
+#include <boost/bigint/bigint.hpp>
+
+#include <sstream>
+
+#include <iostream>
+
+#pragma comment(lib, "libgmp-3.lib")
+
+template <typename I> void test()
+{
+ typedef boost::bigint_base<I> number;
+
+ // char
+ BOOST_CHECK(!number("-129").can_convert_to<char>());
+ BOOST_CHECK( number("-128").can_convert_to<char>());
+ BOOST_CHECK( number("-127").can_convert_to<char>());
+
+ BOOST_CHECK( number("-1").can_convert_to<char>());
+ BOOST_CHECK( number("0").can_convert_to<char>());
+ BOOST_CHECK( number("1").can_convert_to<char>());
+
+ BOOST_CHECK( number("127").can_convert_to<char>());
+ BOOST_CHECK(!number("128").can_convert_to<char>());
+ BOOST_CHECK(!number("129").can_convert_to<char>());
+
+ // unsigned char
+ BOOST_CHECK(!number("-12930").can_convert_to<unsigned char>());
+ BOOST_CHECK(!number("-1").can_convert_to<unsigned char>());
+
+ BOOST_CHECK( number("0").can_convert_to<unsigned char>());
+ BOOST_CHECK( number("1").can_convert_to<unsigned char>());
+
+ BOOST_CHECK( number("127").can_convert_to<unsigned char>());
+ BOOST_CHECK( number("128").can_convert_to<unsigned char>());
+ BOOST_CHECK( number("129").can_convert_to<unsigned char>());
+
+ BOOST_CHECK( number("255").can_convert_to<unsigned char>());
+ BOOST_CHECK(!number("256").can_convert_to<unsigned char>());
+
+ // short
+ BOOST_CHECK(!number("-32769").can_convert_to<short>());
+ BOOST_CHECK( number("-32768").can_convert_to<short>());
+ BOOST_CHECK( number("-32767").can_convert_to<short>());
+
+ BOOST_CHECK( number("-1").can_convert_to<short>());
+ BOOST_CHECK( number("0").can_convert_to<short>());
+ BOOST_CHECK( number("1").can_convert_to<short>());
+
+ BOOST_CHECK( number("32767").can_convert_to<short>());
+ BOOST_CHECK(!number("32768").can_convert_to<short>());
+ BOOST_CHECK(!number("32769").can_convert_to<short>());
+
+ // unsigned short
+ BOOST_CHECK(!number("-12930").can_convert_to<unsigned short>());
+ BOOST_CHECK(!number("-1").can_convert_to<unsigned short>());
+
+ BOOST_CHECK( number("0").can_convert_to<unsigned short>());
+ BOOST_CHECK( number("1").can_convert_to<unsigned short>());
+
+ BOOST_CHECK( number("32767").can_convert_to<unsigned short>());
+ BOOST_CHECK( number("32768").can_convert_to<unsigned short>());
+ BOOST_CHECK( number("32769").can_convert_to<unsigned short>());
+
+ BOOST_CHECK( number("65535").can_convert_to<unsigned short>());
+ BOOST_CHECK(!number("65536").can_convert_to<unsigned short>());
+
+ // int
+ BOOST_CHECK(!number("-80000001", 16).can_convert_to<int>());
+ BOOST_CHECK( number("-80000000", 16).can_convert_to<int>());
+ BOOST_CHECK( number("-7fffffff", 16).can_convert_to<int>());
+
+ BOOST_CHECK( number("-1").can_convert_to<int>());
+ BOOST_CHECK( number("0").can_convert_to<int>());
+ BOOST_CHECK( number("1").can_convert_to<int>());
+
+ BOOST_CHECK( number("7fffffff", 16).can_convert_to<int>());
+ BOOST_CHECK(!number("80000000", 16).can_convert_to<int>());
+ BOOST_CHECK(!number("80000001", 16).can_convert_to<int>());
+
+ // unsigned int
+ BOOST_CHECK(!number("-12930").can_convert_to<unsigned int>());
+ BOOST_CHECK(!number("-1").can_convert_to<unsigned int>());
+
+ BOOST_CHECK( number("0").can_convert_to<unsigned int>());
+ BOOST_CHECK( number("1").can_convert_to<unsigned int>());
+
+ BOOST_CHECK( number("7fffffff", 16).can_convert_to<unsigned int>());
+ BOOST_CHECK( number("80000000", 16).can_convert_to<unsigned int>());
+ BOOST_CHECK( number("80000001", 16).can_convert_to<unsigned int>());
+
+ BOOST_CHECK( number("ffffffff", 16).can_convert_to<unsigned int>());
+ BOOST_CHECK(!number("100000000", 16).can_convert_to<unsigned int>());
+
+ // int64_t
+ BOOST_CHECK(!number("-8000000000000001", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("-8000000000000000", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("-7fffffffffffffff", 16).can_convert_to<boost::int64_t>());
+
+ BOOST_CHECK( number("-80000001", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("-80000000", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("-7fffffff", 16).can_convert_to<boost::int64_t>());
+
+ BOOST_CHECK( number("-1").can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("0").can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("1").can_convert_to<boost::int64_t>());
+
+ BOOST_CHECK( number("7fffffff", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK( number("80000000", 16).can_convert_to<boost::int64_t>());
+
+ BOOST_CHECK( number("7fffffffffffffff", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK(!number("8000000000000000", 16).can_convert_to<boost::int64_t>());
+ BOOST_CHECK(!number("8000000000000001", 16).can_convert_to<boost::int64_t>());
+
+ // uint64_t
+ BOOST_CHECK(!number("-12930").can_convert_to<boost::uint64_t>());
+ BOOST_CHECK(!number("-1").can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("0").can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("1").can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("7fffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("80000000", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("80000001", 16).can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("ffffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("100000000", 16).can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("7fffffffffffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("8000000000000000", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("8000000000000001", 16).can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("7fffffffffffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("8000000000000000", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK( number("8000000000000001", 16).can_convert_to<boost::uint64_t>());
+
+ BOOST_CHECK( number("ffffffffffffffff", 16).can_convert_to<boost::uint64_t>());
+ BOOST_CHECK(!number("10000000000000001", 16).can_convert_to<boost::uint64_t>());
+}
+
+int test_main(int argc, char* argv[])
+{
+ test<boost::detail::bigint_gmp_implementation>();
+
+ return 0;
+}

Copied: sandbox/SOC/2007/bigint/libs/bigint/test/number_conversion.cpp (from r4480, /sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp)
==============================================================================
--- /sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp (original)
+++ sandbox/SOC/2007/bigint/libs/bigint/test/number_conversion.cpp 2007-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
@@ -1,4 +1,4 @@
-/* Boost number_ctors.cpp test file
+/* Boost number_conversion.cpp test file
  *
  * Copyright 2007 Arseny Kapoulkine
  *
@@ -46,7 +46,13 @@
                 std::ostringstream oss;
                 oss << convert_to_number(values[i]);
 
- BOOST_CHECK_EQUAL(oss.str(), number(values[i]).str());
+ // number -> bigint
+ number v(values[i]);
+ BOOST_CHECK_EQUAL(oss.str(), v.str());
+
+ // bigint -> number
+ BOOST_CHECK(v.can_convert_to<T>()); // we should be able to convert to T
+ BOOST_CHECK_EQUAL(convert_to_number(v.to_number<T>()), convert_to_number(values[i]));
         }
 }
 

Deleted: sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp
==============================================================================
--- sandbox/SOC/2007/bigint/libs/bigint/test/number_ctors.cpp 2007-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
+++ (empty file)
@@ -1,144 +0,0 @@
-/* Boost number_ctors.cpp test file
- *
- * Copyright 2007 Arseny Kapoulkine
- *
- * Distributed under the Boost Software License, Version 1.0.
- * (See accompanying file LICENSE_1_0.txt or
- * copy at http://www.boost.org/LICENSE_1_0.txt)
- */
-
-#define BOOST_DISABLE_WIN32
-
-#include <boost/test/included/test_exec_monitor.hpp>
-
-#include <boost/bigint/bigint.hpp>
-
-#include <sstream>
-
-#include <iostream>
-
-#pragma comment(lib, "libgmp-3.lib")
-
-// This macro is not quite good, but - it's ok for our needs
-#define ARRAY_SIZE(array) sizeof(array) / sizeof(array[0])
-
-template <typename T> T convert_to_number(T value)
-{
- return value;
-}
-
-int convert_to_number(char value)
-{
- return value;
-}
-
-unsigned int convert_to_number(unsigned char value)
-{
- return value;
-}
-
-template <typename I, typename T> void test_number_ctors(T* values, size_t count)
-{
- typedef boost::bigint_base<I> number;
-
- for (size_t i = 0; i < count; ++i)
- {
- std::ostringstream oss;
- oss << convert_to_number(values[i]);
-
- BOOST_CHECK_EQUAL(oss.str(), number(values[i]).str());
- }
-}
-
-template <typename I> void test()
-{
- {
- char values[] = {-128, -127, -10, -1, 0, 1, 33, 124, 125, 126, 127};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- unsigned char values[] = {0, 1, 33, 124, 125, 126, 127, 200, 240, 254, 255};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- short values[] = {-32768, -32767, -23032, -3407, -10, -1, 0, 1, 33, 124, 125, 126, 127, 3489, 31900, 32766, 32767};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- unsigned short values[] = {0, 1, 33, 124, 125, 126, 127, 200, 240, 254, 255, 3000, 48950, 65534, 65535};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- int values[] = {-2147483647 - 1, -2147483647, -2147483646, -34294039, -3409, -1, 0, 1, 3940, 4950424, 2147483646, 2147483647};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- unsigned int values[] = {0, 1, 200, 65535, 384983, 23849384, 1203002930, 2147483648, 4294967294, 4294967295};
-
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- boost::int64_t values[] = {-2147483647 - 1, -2147483647, -2147483646, -34294039, -3409, -1, 0, 1, 3940, 4950424, 2147483646, 2147483647};
-
- // small values
- test_number_ctors<I>(values, ARRAY_SIZE(values));
-
- for (size_t i = 0; i < ARRAY_SIZE(values); ++i)
- {
- values[i] *= 2147483648; // 2^31
- values[i] *= 2; // 2^32
- }
-
- // first element is -2^31 * 2^32 == -2^63 - ok
- // last element is (2^31 - 1) * 2^32 == 2^63 - 2^32 - too small
- values[ARRAY_SIZE(values) - 1] += 4294967295;
-
- // testing unit tests
- BOOST_CHECK(values[0] < 0 && values[0] - 1 > 0); // underflow
- BOOST_CHECK(values[ARRAY_SIZE(values) - 1] > 0 && values[ARRAY_SIZE(values) - 1] + 1 < 0); // overflow
- BOOST_CHECK_EQUAL(values[0] - 1, values[ARRAY_SIZE(values) - 1]);
-
- // large values
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-
- {
- boost::uint64_t values[] = {0, 1, 200, 65535, 384983, 23849384, 1203002930, 2147483648, 4294967294, 4294967295};
-
- // small values
- test_number_ctors<I>(values, ARRAY_SIZE(values));
-
- for (size_t i = 0; i < ARRAY_SIZE(values); ++i)
- {
- values[i] *= 2147483648; // 2^31
- values[i] *= 2; // 2^32
- }
-
- // last element is (2^32 - 1) * 2^32 == 2^64 - 2^32 - too small
- values[ARRAY_SIZE(values) - 1] += 4294967295;
-
- // testing unit tests
- BOOST_CHECK_EQUAL(values[ARRAY_SIZE(values) - 1] + 1, 0); // overflow
-
- // large values
- test_number_ctors<I>(values, ARRAY_SIZE(values));
- }
-}
-
-int test_main(int argc, char* argv[])
-{
- test<boost::detail::bigint_gmp_implementation>();
-
- return 0;
-}

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-06-07 08:14:29 EDT (Thu, 07 Jun 2007)
@@ -91,6 +91,12 @@
 + fix bug in wstr() - sometimes mpz_sizeinbase returns slightly bigger size
 Status: fixed
 
++ fix bug in to_number() - fails for 64-bit integers
+Status: fixed
+
++ fix bug in can_convert_to() - fails for boundary case (-2^63-1) for boost::int64_t
+Status: fixed
+
 - remove warnings for both MSVC and GCC
 Status: needs fixing
 
@@ -105,6 +111,12 @@
 + test string conversion (various bases - 2, 9, 18, 27, 36)
 Status: implemented (merged with "test all ctors for strings")
 
++ test can_convert_to (char, short, int, int64 - both signed and unsigned, boundary cases)
+Status: implemented
+
++ test to_number (char, short, int, int64 - both signed and unsigned, boundary cases)
+Status: implemented
+
 - test copy construction and assignment
 Status: needs implementing
 
@@ -123,12 +135,6 @@
 - test bool conversion and operator!
 Status: needs implementing
 
-- test can_convert_to (char, short, int, int64 - both signed and unsigned, boundary cases)
-Status: needs implementing
-
-- test to_number (char, short, int, int64 - both signed and unsigned, boundary cases)
-Status: needs implementing
-
 - test comparison operators
 Status: needs implementing
 


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