Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r75716 - in sandbox/big_number: boost/multiprecision libs/multiprecision/test
From: john_at_[hidden]
Date: 2011-11-28 14:24:21


Author: johnmaddock
Date: 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
New Revision: 75716
URL: http://svn.boost.org/trac/boost/changeset/75716

Log:
Fix and test integer formatted output.
Added:
   sandbox/big_number/libs/multiprecision/test/test_int_io.cpp (contents, props changed)
Text files modified:
   sandbox/big_number/boost/multiprecision/gmp.hpp | 5 ++
   sandbox/big_number/boost/multiprecision/tommath.hpp | 70 +++++++++++++++++++++------------------
   sandbox/big_number/libs/multiprecision/test/Jamfile.v2 | 15 ++++++++
   sandbox/big_number/libs/multiprecision/test/test.hpp | 2
   4 files changed, 59 insertions(+), 33 deletions(-)

Modified: sandbox/big_number/boost/multiprecision/gmp.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/gmp.hpp (original)
+++ sandbox/big_number/boost/multiprecision/gmp.hpp 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
@@ -1034,6 +1034,11 @@
          base = 8;
       else if((f & std::ios_base::hex) == std::ios_base::hex)
          base = 16;
+ //
+ // sanity check, bases 8 and 16 are only available for positive numbers:
+ //
+ if((base != 10) && (mpz_sgn(m_data) < 0))
+ BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
       void *(*alloc_func_ptr) (size_t);
       void *(*realloc_func_ptr) (void *, size_t, size_t);
       void (*free_func_ptr) (void *, size_t);

Modified: sandbox/big_number/boost/multiprecision/tommath.hpp
==============================================================================
--- sandbox/big_number/boost/multiprecision/tommath.hpp (original)
+++ sandbox/big_number/boost/multiprecision/tommath.hpp 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
@@ -42,11 +42,11 @@
    }
    tommath_int(const tommath_int& o)
    {
- detail::check_tommath_result(mp_init_copy(&m_data, const_cast<::mp_int*>(&o.m_data)));
+ detail::check_tommath_result(mp_init_copy(&m_data, const_cast< ::mp_int*>(&o.m_data)));
    }
    tommath_int& operator = (const tommath_int& o)
    {
- detail::check_tommath_result(mp_copy(const_cast<::mp_int*>(&o.m_data), &m_data));
+ detail::check_tommath_result(mp_copy(const_cast< ::mp_int*>(&o.m_data), &m_data));
       return *this;
    }
    tommath_int& operator = (boost::uintmax_t i)
@@ -162,10 +162,11 @@
          {
             radix = 8;
             n -= 1;
+ s += 1;
          }
       }
       if(n)
- detail::check_tommath_result(mp_read_radix(&m_data, s, 10));
+ detail::check_tommath_result(mp_read_radix(&m_data, s, radix));
       else
          detail::check_tommath_result(mp_set_int(&m_data, 0));
       return *this;
@@ -177,10 +178,15 @@
          base = 8;
       else if((f & std::ios_base::hex) == std::ios_base::hex)
          base = 16;
+ //
+ // sanity check, bases 8 and 16 are only available for positive numbers:
+ //
+ if((base != 10) && m_data.sign)
+ BOOST_THROW_EXCEPTION(std::runtime_error("Formatted output in bases 8 or 16 is only available for positive numbers"));
       int s;
- detail::check_tommath_result(mp_radix_size(const_cast<::mp_int*>(&m_data), 10, &s));
+ detail::check_tommath_result(mp_radix_size(const_cast< ::mp_int*>(&m_data), base, &s));
       boost::scoped_array<char> a(new char[s+1]);
- detail::check_tommath_result(mp_toradix_n(const_cast<::mp_int*>(&m_data), a.get(), base, s+1));
+ detail::check_tommath_result(mp_toradix_n(const_cast< ::mp_int*>(&m_data), a.get(), base, s+1));
       std::string result = a.get();
       if((base != 10) && (f & std::ios_base::showbase))
       {
@@ -202,7 +208,7 @@
    }
    int compare(const tommath_int& o)const
    {
- return mp_cmp(const_cast<::mp_int*>(&m_data), const_cast<::mp_int*>(&o.m_data));
+ return mp_cmp(const_cast< ::mp_int*>(&m_data), const_cast< ::mp_int*>(&o.m_data));
    }
    template <class V>
    int compare(V v)const
@@ -227,30 +233,30 @@
 
 inline void add(tommath_int& t, const tommath_int& o)
 {
- detail::check_tommath_result(mp_add(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void subtract(tommath_int& t, const tommath_int& o)
 {
- detail::check_tommath_result(mp_sub(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_sub(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void multiply(tommath_int& t, const tommath_int& o)
 {
- detail::check_tommath_result(mp_mul(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_mul(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void divide(tommath_int& t, const tommath_int& o)
 {
    tommath_int temp;
- detail::check_tommath_result(mp_div(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data(), &temp.data()));
+ detail::check_tommath_result(mp_div(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data(), &temp.data()));
 }
 inline void modulus(tommath_int& t, const tommath_int& o)
 {
    bool neg = get_sign(t) < 0;
    bool neg2 = get_sign(o) < 0;
- detail::check_tommath_result(mp_mod(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_mod(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
    if(neg != neg2)
    {
       t.negate();
- detail::check_tommath_result(mp_add(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
       t.negate();
    }
 }
@@ -268,73 +274,73 @@
 template <class UI>
 inline void left_shift(tommath_int& t, const tommath_int& v, UI i)
 {
- detail::check_tommath_result(mp_mul_2d(const_cast<::mp_int*>(&v.data()), static_cast<unsigned>(i), &t.data()));
+ detail::check_tommath_result(mp_mul_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned>(i), &t.data()));
 }
 template <class UI>
 inline void right_shift(tommath_int& t, const tommath_int& v, UI i)
 {
    tommath_int d;
- detail::check_tommath_result(mp_div_2d(const_cast<::mp_int*>(&v.data()), static_cast<unsigned long>(i), &t.data(), &d.data()));
+ detail::check_tommath_result(mp_div_2d(const_cast< ::mp_int*>(&v.data()), static_cast<unsigned long>(i), &t.data(), &d.data()));
 }
 
 inline void bitwise_and(tommath_int& result, const tommath_int& v)
 {
- detail::check_tommath_result(mp_and(&result.data(), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_and(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void bitwise_or(tommath_int& result, const tommath_int& v)
 {
- detail::check_tommath_result(mp_or(&result.data(), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_or(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void bitwise_xor(tommath_int& result, const tommath_int& v)
 {
- detail::check_tommath_result(mp_xor(&result.data(), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_xor(&result.data(), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void add(tommath_int& t, const tommath_int& p, const tommath_int& o)
 {
- detail::check_tommath_result(mp_add(const_cast<::mp_int*>(&p.data()), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_add(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void subtract(tommath_int& t, const tommath_int& p, const tommath_int& o)
 {
- detail::check_tommath_result(mp_sub(const_cast<::mp_int*>(&p.data()), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_sub(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void multiply(tommath_int& t, const tommath_int& p, const tommath_int& o)
 {
- detail::check_tommath_result(mp_mul(const_cast<::mp_int*>(&p.data()), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_mul(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data()));
 }
 inline void divide(tommath_int& t, const tommath_int& p, const tommath_int& o)
 {
    tommath_int d;
- detail::check_tommath_result(mp_div(const_cast<::mp_int*>(&p.data()), const_cast<::mp_int*>(&o.data()), &t.data(), &d.data()));
+ detail::check_tommath_result(mp_div(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data(), &d.data()));
 }
 inline void modulus(tommath_int& t, const tommath_int& p, const tommath_int& o)
 {
    bool neg = get_sign(p) < 0;
    bool neg2 = get_sign(o) < 0;
- detail::check_tommath_result(mp_mod(const_cast<::mp_int*>(&p.data()), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_mod(const_cast< ::mp_int*>(&p.data()), const_cast< ::mp_int*>(&o.data()), &t.data()));
    if(neg != neg2)
    {
       t.negate();
- detail::check_tommath_result(mp_add(&t.data(), const_cast<::mp_int*>(&o.data()), &t.data()));
+ detail::check_tommath_result(mp_add(&t.data(), const_cast< ::mp_int*>(&o.data()), &t.data()));
       t.negate();
    }
 }
 
 inline void bitwise_and(tommath_int& result, const tommath_int& u, const tommath_int& v)
 {
- detail::check_tommath_result(mp_and(const_cast<::mp_int*>(&u.data()), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_and(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void bitwise_or(tommath_int& result, const tommath_int& u, const tommath_int& v)
 {
- detail::check_tommath_result(mp_or(const_cast<::mp_int*>(&u.data()), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_or(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void bitwise_xor(tommath_int& result, const tommath_int& u, const tommath_int& v)
 {
- detail::check_tommath_result(mp_xor(const_cast<::mp_int*>(&u.data()), const_cast<::mp_int*>(&v.data()), &result.data()));
+ detail::check_tommath_result(mp_xor(const_cast< ::mp_int*>(&u.data()), const_cast< ::mp_int*>(&v.data()), &result.data()));
 }
 
 inline void complement(tommath_int& result, const tommath_int& u)
@@ -351,7 +357,7 @@
    //
    unsigned shift = result.data().used * DIGIT_BIT; // How many bits we're actually using
    // How many bits we actually need, reduced by one to account for a mythical sign bit:
- unsigned padding = result.data().used * std::numeric_limits<mp_digit>::digits - shift - 1;
+ int padding = result.data().used * std::numeric_limits<mp_digit>::digits - shift - 1;
    while(padding >= std::numeric_limits<mp_digit>::digits)
       padding -= std::numeric_limits<mp_digit>::digits;
 
@@ -373,23 +379,23 @@
 template <class A>
 inline void convert_to(A* result, const tommath_int& val)
 {
- *result = boost::lexical_cast<A>(val.str(0, false));
+ *result = boost::lexical_cast<A>(val.str(0, std::ios_base::fmtflags(0)));
 }
 inline void convert_to(char* result, const tommath_int& val)
 {
- *result = static_cast<char>(boost::lexical_cast<int>(val.str(0, false)));
+ *result = static_cast<char>(boost::lexical_cast<int>(val.str(0, std::ios_base::fmtflags(0))));
 }
 inline void convert_to(unsigned char* result, const tommath_int& val)
 {
- *result = static_cast<unsigned char>(boost::lexical_cast<unsigned>(val.str(0, false)));
+ *result = static_cast<unsigned char>(boost::lexical_cast<unsigned>(val.str(0, std::ios_base::fmtflags(0))));
 }
 inline void convert_to(signed char* result, const tommath_int& val)
 {
- *result = static_cast<signed char>(boost::lexical_cast<int>(val.str(0, false)));
+ *result = static_cast<signed char>(boost::lexical_cast<int>(val.str(0, std::ios_base::fmtflags(0))));
 }
 inline void eval_abs(tommath_int& result, const tommath_int& val)
 {
- detail::check_tommath_result(mp_abs(const_cast<::mp_int*>(&val.data()), &result.data()));
+ detail::check_tommath_result(mp_abs(const_cast< ::mp_int*>(&val.data()), &result.data()));
 }
 
 

Modified: sandbox/big_number/libs/multiprecision/test/Jamfile.v2
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/Jamfile.v2 (original)
+++ sandbox/big_number/libs/multiprecision/test/Jamfile.v2 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
@@ -607,3 +607,18 @@
          [ check-target-builds ../config//has_mpfr : : <build>no ]
         : test_float_io_mpfr ;
 
+run test_int_io.cpp $(TOMMATH)
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_TOMMATH
+ [ check-target-builds ../config//has_tommath : : <build>no ]
+ : test_int_io_tommath ;
+
+run test_int_io.cpp gmp
+ : # command line
+ : # input files
+ : # requirements
+ <define>TEST_MPZ
+ [ check-target-builds ../config//has_gmp : : <build>no ]
+ : test_int_io_mpz ;

Modified: sandbox/big_number/libs/multiprecision/test/test.hpp
==============================================================================
--- sandbox/big_number/libs/multiprecision/test/test.hpp (original)
+++ sandbox/big_number/libs/multiprecision/test/test.hpp 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
@@ -63,7 +63,7 @@
 template <class T>
 inline int digits_of(const T&)
 {
- return std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::max_digits10 + 2 : std::numeric_limits<long double>::max_digits10 + 2;
+ return std::numeric_limits<T>::is_specialized ? std::numeric_limits<T>::digits10 + 2 : std::numeric_limits<long double>::digits10 + 2;
 }
 
 inline std::ostream& report_where(const char* file, int line, const char* function)

Added: sandbox/big_number/libs/multiprecision/test/test_int_io.cpp
==============================================================================
--- (empty file)
+++ sandbox/big_number/libs/multiprecision/test/test_int_io.cpp 2011-11-28 14:24:20 EST (Mon, 28 Nov 2011)
@@ -0,0 +1,112 @@
+// Copyright John Maddock 2011.
+
+// Use, modification and distribution are subject to 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)
+
+#ifdef _MSC_VER
+# define _SCL_SECURE_NO_WARNINGS
+#endif
+
+#if !defined(TEST_MPZ) && !defined(TEST_TOMMATH)
+# define TEST_TOMMATH
+# define TEST_MPZ
+
+#ifdef _MSC_VER
+#pragma message("CAUTION!!: No backend type specified so testing everything.... this will take some time!!")
+#endif
+#ifdef __GNUC__
+#pragma warning "CAUTION!!: No backend type specified so testing everything.... this will take some time!!"
+#endif
+
+#endif
+
+#if defined(TEST_MPZ)
+#include <boost/multiprecision/gmp.hpp>
+#endif
+#if defined(TEST_TOMMATH)
+#include <boost/multiprecision/tommath.hpp>
+#endif
+
+#include <boost/algorithm/string/case_conv.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/random/uniform_int.hpp>
+#include "test.hpp"
+#include <iostream>
+#include <iomanip>
+
+template <class T>
+T generate_random()
+{
+ static boost::random::uniform_int_distribution<unsigned> ui(0, 20);
+ static boost::random::mt19937 gen;
+ T val = gen();
+ unsigned lim = ui(gen);
+ for(unsigned i = 0; i < lim; ++i)
+ {
+ val *= (gen.max)();
+ val += gen();
+ }
+ return val;
+}
+
+template <class T>
+void do_round_trip(const T& val, std::ios_base::fmtflags f)
+{
+ std::stringstream ss;
+ ss << std::setprecision(std::numeric_limits<T>::max_digits10);
+ ss.flags(f);
+ ss << val;
+ T new_val = ss.str();
+ BOOST_CHECK_EQUAL(new_val, val);
+ new_val = val.str(0, f);
+ BOOST_CHECK_EQUAL(new_val, val);
+}
+
+template <class T>
+void do_round_trip(const T& val)
+{
+ do_round_trip(val, std::ios_base::fmtflags(0));
+ if(val >= 0)
+ {
+ do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::hex));
+ do_round_trip(val, std::ios_base::fmtflags(std::ios_base::showbase|std::ios_base::oct));
+ }
+}
+
+template <class T>
+void test_round_trip()
+{
+ for(unsigned i = 0; i < 1000; ++i)
+ {
+ T val = generate_random<T>();
+ do_round_trip(val);
+ do_round_trip(T(-val));
+ }
+
+ BOOST_CHECK_EQUAL(T(1002).str(), "1002");
+ BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::showpos), "+1002");
+ BOOST_CHECK_EQUAL(T(-1002).str(), "-1002");
+ BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct), "1752");
+ BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::oct|std::ios_base::showbase), "01752");
+ BOOST_CHECK_EQUAL(boost::to_lower_copy(T(1002).str(0, std::ios_base::hex)), "3ea");
+ BOOST_CHECK_EQUAL(boost::to_lower_copy(T(1002).str(0, std::ios_base::hex|std::ios_base::showbase)), "0x3ea");
+ BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec), "1002");
+ BOOST_CHECK_EQUAL(T(1002).str(0, std::ios_base::dec|std::ios_base::showbase), "1002");
+
+ BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::oct), std::runtime_error);
+ BOOST_CHECK_THROW(T(-2).str(0, std::ios_base::hex), std::runtime_error);
+}
+
+int main()
+{
+#ifdef TEST_MPZ
+ test_round_trip<boost::multiprecision::mpz_int>();
+#endif
+#ifdef TEST_TOMMATH
+ test_round_trip<boost::multiprecision::mp_int>();
+#endif
+ return boost::report_errors();
+}
+


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