Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r54953 - in sandbox/mp_math/boost/mp_math/integer: . detail detail/base
From: baraclese_at_[hidden]
Date: 2009-07-14 15:45:22


Author: baraclese
Date: 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
New Revision: 54953
URL: http://svn.boost.org/trac/boost/changeset/54953

Log:
* add gmp_integer_fwd.hpp
* add libtom_integer_fwd.hpp
* add detail/digit_converter.hpp
* add detail/stream_io.hpp
* add detail/base/print_digits.hpp
* add experimental ctors to allow conversion from one integer type to another

Added:
   sandbox/mp_math/boost/mp_math/integer/detail/base/print_digits.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/digit_converter.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/detail/stream_io.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/gmp_integer_fwd.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/libtom_integer_fwd.hpp (contents, props changed)
   sandbox/mp_math/boost/mp_math/integer/multiprecision_integer_tag.hpp (contents, props changed)
Text files modified:
   sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp | 42 +++++++++++++++++++++++++++++++++++++++
   sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp | 4 ++
   2 files changed, 44 insertions(+), 2 deletions(-)

Added: sandbox/mp_math/boost/mp_math/integer/detail/base/print_digits.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/base/print_digits.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,62 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_BASE_PRINT_DIGITS_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_BASE_PRINT_DIGITS_HPP
+
+#include <iostream>
+#include <boost/cstdint.hpp>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+namespace base {
+
+// Prints raw digit values in hex format to std::cout.
+// If argument all is true then it also prints the digits that were allocated
+// but are currently not in use.
+//
+// Sample output size = 4, capacity = 16:
+// 4{0,0,0,1}12{0,0,0,0,0,0,0,0,0,0,0,0}
+
+template<class ApInt>
+void print_digits(const ApInt& x, bool all)
+{
+ typedef typename ApInt::size_type size_type;
+
+ const std::ios::fmtflags flags = std::cout.flags();
+
+ std::cout << x.size() << "{" << std::hex;
+ for (size_type i = 0; i < x.size(); ++i)
+ {
+ std::cout << static_cast<uintmax_t>(x[i]);
+ if (i < x.size() - 1)
+ std::cout << ",";
+ }
+ std::cout << "}";
+
+ if (all)
+ {
+ std::cout << std::dec << x.capacity() - x.size() << "{" << std::hex;
+ for (size_type i = x.size(); i < x.capacity(); ++i)
+ {
+ std::cout << static_cast<uintmax_t>(x[i]);
+ if (i < x.capacity() - 1)
+ std::cout << ",";
+ }
+ std::cout << "}";
+ }
+ std::cout << "\n";
+ std::cout.flags(flags);
+}
+
+
+} // namespace base
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/digit_converter.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/digit_converter.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,115 @@
+// Copyright Kevin Sopp 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_DIGIT_CONVERTER_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_DIGIT_CONVERTER_HPP
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <typeinfo>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+struct eq_tag{}; // equal digit type and equal radix
+struct ne_tag{}; // not equal
+
+
+// This class converts only the magnitude, sign needs to be handled by caller
+template<class DstType, class SrcType>
+struct digit_converter
+{
+ typedef DstType dst_type;
+ typedef SrcType src_type;
+ typedef typename dst_type::traits_type dst_traits;
+ typedef typename src_type::traits_type src_traits;
+
+ static void convert(dst_type& dst, const src_type& src);
+ static void convert(dst_type& dst, const src_type& src, eq_tag);
+ static void convert(dst_type& dst, const src_type& src, ne_tag);
+};
+
+
+template<class DstType, class SrcType>
+void
+digit_converter<DstType,SrcType>::
+convert(dst_type& dst, const src_type& src)
+{
+ typedef typename mpl::if_c<
+ sizeof(typename dst_type::digit_type) == sizeof(typename src_type::digit_type) &&
+ dst_traits::radix_bits == src_traits::radix_bits,
+ eq_tag,
+ ne_tag
+ >::type tag_type;
+
+ convert(dst, src, tag_type());
+}
+
+template<class DstType, class SrcType>
+void
+digit_converter<DstType,SrcType>::
+convert(dst_type& dst, const src_type& src, eq_tag)
+{
+ dst.reserve(src.size());
+ std::memcpy(dst.digits(),
+ src.digits(),
+ sizeof(typename dst_type::digit_type) * src.size());
+ dst.set_size(src.size());
+}
+
+template<class DstType, class SrcType>
+void
+digit_converter<DstType,SrcType>::
+convert(dst_type& dst, const src_type& src, ne_tag)
+{
+ dst.reserve(src.size()
+ * (src_traits::radix_bits + (dst_traits::radix_bits - 1))
+ / dst_traits::radix_bits);
+
+ typedef typename src_type::digit_type src_digit_type;
+ typedef typename dst_type::digit_type dst_digit_type;
+
+ unsigned dst_offset = 0;
+
+ dst_digit_type d = 0;
+ for (typename src_type::const_iterator s = src.begin(); s != src.end(); ++s)
+ {
+ unsigned bits_read = 0;
+ while (bits_read < dst_traits::radix_bits)
+ {
+ unsigned bits = std::min(dst_traits::radix_bits - dst_offset,
+ src_traits::radix_bits - bits_read);
+
+ d |= static_cast<dst_digit_type>(*s >> (src_traits::radix_bits - bits))
+ << dst_offset;
+
+ dst_offset += bits;
+ bits_read += bits;
+
+ if (bits_read >= src_traits::radix_bits)
+ break;
+
+ if (dst_offset >= dst_traits::radix_bits)
+ {
+ dst.push(d);
+ d = 0;
+ }
+ }
+ }
+
+ if (d)
+ dst.push(d);
+}
+
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/detail/stream_io.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/detail/stream_io.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,116 @@
+// Copyright Kevin Sopp 2008 - 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_DETAIL_STREAM_IO_HPP
+#define BOOST_MP_MATH_INTEGER_DETAIL_STREAM_IO_HPP
+
+#include <iosfwd>
+
+namespace boost {
+namespace mp_math {
+namespace detail {
+
+
+template<class ApInt>
+struct stream_io
+{
+ template<typename charT, class traits>
+ static void read(ApInt& z, std::basic_istream<charT, traits>& is);
+};
+
+
+template<class ApInt>
+template<typename charT, class traits>
+void stream_io<ApInt>::read(ApInt& z, std::basic_istream<charT, traits>& is)
+{
+ typename std::basic_istream<charT, traits>::sentry sentry(is);
+ if (!sentry)
+ return;
+
+ // TODO we read into a string first which costs memory and std::string
+ // allocator is not under user control. We should convert incoming digits
+ // directly. Actually we should check what is the fastest way.
+ std::string s;
+
+ const std::istreambuf_iterator<charT, traits> end;
+ std::istreambuf_iterator<charT, traits> c(is);
+
+ // TODO stop at minus sign if unsigned ApInt
+ if (*c == '+' || *c == '-')
+ {
+ s.push_back(*c);
+ ++c;
+ }
+
+ int base;
+ if (*c == '0')
+ {
+ base = 8;
+ s.push_back(*c);
+ ++c;
+ if (*c == 'x' || *c == 'X')
+ {
+ base = 16;
+ s.push_back(*c);
+ ++c;
+ }
+ }
+ else if (*c >= '0' && *c <= '9')
+ base = 10;
+ else
+ {
+ is.setstate(std::ios_base::failbit);
+ return;
+ }
+
+ switch (base)
+ {
+ case 8:
+ while (c != end)
+ {
+ if (*c >= '0' && *c <= '7')
+ s.push_back(*c);
+ else
+ break;
+ ++c;
+ }
+ break;
+ case 10:
+ while (c != end)
+ {
+ if (*c >= '0' && *c <= '9')
+ s.push_back(*c);
+ else
+ break;
+ ++c;
+ }
+ break;
+ case 16:
+ while (c != end)
+ {
+ if ((*c >= '0' && *c <= '9') ||
+ (*c >= 'A' && *c <= 'F') ||
+ (*c >= 'a' && *c <= 'f'))
+ s.push_back(*c);
+ else
+ break;
+ ++c;
+ }
+ break;
+ }
+
+ // TODO we do another round of radix detection in the string ctor...
+ const ApInt tmp(s.begin(), s.end());
+ z = tmp; // TODO move tmp into z
+}
+
+
+
+} // namespace detail
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Modified: sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/gmp_integer.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -600,6 +600,16 @@
   gmp_integer(const char* s, std::ios_base::fmtflags);
   gmp_integer(const std::string& s, std::ios_base::fmtflags);
 
+
+ template<class ApInt>
+ gmp_integer(const ApInt& x,
+ typename enable_if<
+ mpl::and_<
+ mpl::not_<is_same<traits_type, typename ApInt::traits_type> >,
+ is_same<typename ApInt::tag, multiprecision_integer_tag>
+ >
+ >::type* dummy = 0);
+
   gmp_integer(const gmp_integer& copy)
   {
     mpz_init_set(val_, copy.val_);
@@ -733,11 +743,17 @@
   int sign() const { return is_positive() ? 1 : -1; }
   bool sign_bit() const { return is_positive() ? 0 : 1; }
 
+ void set_sign_bit(bool s)
+ {
+ if (sign_bit() != s)
+ mpz_neg(val_, val_);
+ }
+
   // These two functions use the same signature as GMP's mpz_class
   mpz_ptr get_mpz_t() { return val_; }
   mpz_srcptr get_mpz_t() const { return val_; }
 
- size_type size () const { return mpz_size(val_); }
+ size_type size() const { return mpz_size(val_); }
 
   void set_size(size_type s) { val_->_mp_size = static_cast<int>(s); }
 
@@ -745,6 +761,15 @@
 
   void reserve(size_type n) { mpz_realloc(val_, n); }
 
+ void push(digit_type d)
+ {
+ val_->_mp_d[__GMP_ABS(val_->_mp_size)] = d;
+ if (val_->_mp_size > 0)
+ ++(val_->_mp_size);
+ else
+ --(val_->_mp_size);
+ }
+
   digit_type* digits() { return val_->_mp_d; }
   const digit_type* digits() const { return val_->_mp_d; }
 
@@ -986,6 +1011,21 @@
 }
 
 template<class B>
+template<class ApInt>
+gmp_integer<B>::gmp_integer(
+ const ApInt& x,
+ typename enable_if<
+ mpl::and_<
+ mpl::not_<is_same<traits_type, typename ApInt::traits_type> >,
+ is_same<typename ApInt::tag, multiprecision_integer_tag>
+ >
+ >::type*)
+{
+ detail::digit_converter<gmp_integer<B>, ApInt>::convert(*this, x);
+ set_sign_bit(x.sign_bit()); // FIXME works for signed types only
+}
+
+template<class B>
 inline void swap(gmp_integer<B>& lhs, gmp_integer<B>& rhs)
 {
   lhs.swap(rhs);

Added: sandbox/mp_math/boost/mp_math/integer/gmp_integer_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/gmp_integer_fwd.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,22 @@
+// Copyright Kevin Sopp 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_GMP_INTEGER_FWD_HPP
+#define BOOST_MP_MATH_INTEGER_GMP_INTEGER_FWD_HPP
+
+namespace boost {
+namespace mp_math {
+
+struct gmp_behavior;
+
+template<class Behavior = gmp_behavior>
+class gmp_integer;
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/libtom_integer_fwd.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/libtom_integer_fwd.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,22 @@
+// Copyright Kevin Sopp 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_LIBTOM_INTEGER_FWD_HPP
+#define BOOST_MP_MATH_INTEGER_LIBTOM_INTEGER_FWD_HPP
+
+namespace boost {
+namespace mp_math {
+
+struct libtom_behavior;
+
+template<class Behavior = libtom_behavior>
+class libtom_integer;
+
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Added: sandbox/mp_math/boost/mp_math/integer/multiprecision_integer_tag.hpp
==============================================================================
--- (empty file)
+++ sandbox/mp_math/boost/mp_math/integer/multiprecision_integer_tag.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -0,0 +1,22 @@
+// Copyright Kevin Sopp 2009.
+// 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)
+
+#ifndef BOOST_MP_MATH_INTEGER_MULTIPRECISION_INTEGER_TAG_HPP
+#define BOOST_MP_MATH_INTEGER_MULTIPRECISION_INTEGER_TAG_HPP
+
+namespace boost {
+namespace mp_math {
+
+// This exists so that we can remove the
+// template<class ApInt> integer_type(const ApInt&)
+// constructor from the overload set.
+
+struct multiprecision_integer_tag;
+
+} // namespace mp_math
+} // namespace boost
+
+#endif
+

Modified: sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp
==============================================================================
--- sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp (original)
+++ sandbox/mp_math/boost/mp_math/integer/unbounded_int.hpp 2009-07-14 15:45:21 EDT (Tue, 14 Jul 2009)
@@ -25,6 +25,8 @@
 #include <boost/mp_math/integer/detail/string_conversion.hpp>
 #include <boost/mp_math/integer/detail/unbounded_int_integral.hpp>
 #include <boost/mp_math/integer/detail/base/unbounded_int.hpp>
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/not.hpp>
 
 namespace boost {
 namespace mp_math {
@@ -365,7 +367,7 @@
   base_type(0, 0, 0)
 {
   detail::digit_converter<unbounded_int<A,T>, ApInt>::convert(*this, x);
- //set_sign_bit(x.sign_bit());
+ set_sign_bit(x.sign_bit()); // FIXME works for signed types only
 }
 
 


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