Merge branch 'develop' into c99

# Resolved Conflicts:
#	doc/html/boost_multiprecision/indexes/s01.html
#	doc/html/boost_multiprecision/indexes/s02.html
#	doc/html/boost_multiprecision/indexes/s03.html
#	doc/html/boost_multiprecision/indexes/s04.html
#	doc/html/index.html
#	include/boost/multiprecision/detail/default_ops.hpp
This commit is contained in:
jzmaddock
2016-09-23 09:01:56 +01:00
9 changed files with 177 additions and 37 deletions

View File

@@ -1392,7 +1392,7 @@ private:
}
}
//
// Exception guarentee: create the result in stack variable "result"
// Exception guarantee: create the result in stack variable "result"
// then do a swap at the end. In the event of a throw, *this will
// be left unchanged.
//

View File

@@ -541,6 +541,7 @@ template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignTy
inline typename enable_if_c<
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& is_signed_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
>::type
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{
@@ -564,8 +565,8 @@ inline typename enable_if_c<
*result = static_cast<R>(*val.limbs());
if(val.isneg())
{
check_is_negative(mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
*result = negate_integer(*result, mpl::bool_<boost::is_signed<R>::value || boost::is_floating_point<R>::value>());
check_is_negative(mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
*result = negate_integer(*result, mpl::bool_<is_signed_number<R>::value || (number_category<R>::value == number_kind_floating_point)>());
}
}
}
@@ -574,6 +575,7 @@ template <class R, unsigned MinBits1, unsigned MaxBits1, cpp_integer_type SignTy
inline typename enable_if_c<
is_trivial_cpp_int<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& is_unsigned_number<cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1> >::value
&& boost::is_convertible<typename cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>::local_limb_type, R>::value
>::type
eval_convert_to(R* result, const cpp_int_backend<MinBits1, MaxBits1, SignType1, Checked1, Allocator1>& val)
{

View File

@@ -33,7 +33,18 @@ namespace boost{ namespace multiprecision{
template <class T>
struct is_backend;
}
template <class To, class From>
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
template <class To, class From>
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_integer>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
template <class To, class From>
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_floating_point>& /*to_type*/, const mpl::int_<number_kind_floating_point>& /*from_type*/);
template <class To, class From>
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_rational>& /*from_type*/);
template <class To, class From>
void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_rational>& /*to_type*/, const mpl::int_<number_kind_integer>& /*from_type*/);
}
namespace default_ops{
@@ -368,6 +379,7 @@ inline void eval_multiply_default(T& t, const T& u, const T& v)
eval_multiply(t, v);
}
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_multiply_default(T& t, const T& u, const U& v)
{
@@ -386,6 +398,7 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value>::type e
{
eval_multiply(t, v, u);
}
#endif
template <class T, class U, class V>
inline void eval_multiply_default(T& t, const U& u, const V& v)
{
@@ -485,6 +498,7 @@ inline void eval_divide_default(T& t, const T& u, const T& v)
eval_divide(t, v);
}
}
#if !BOOST_WORKAROUND(BOOST_MSVC, < 1900)
template <class T, class U>
inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && !is_convertible<U, T>::value>::type eval_divide_default(T& t, const T& u, const U& v)
{
@@ -511,12 +525,14 @@ inline typename enable_if_c<is_convertible<U, number<T, et_on> >::value && is_co
T uu(u);
eval_divide(t, uu, v);
}
#endif
template <class T, class U, class V>
inline void eval_divide_default(T& t, const U& u, const V& v)
{
if(is_same<T, V>::value && ((void*)&t == (void*)&v))
{
T temp(u);
T temp;
temp = u;
eval_divide(temp, v);
t = temp;
}
@@ -918,6 +934,16 @@ inline void eval_convert_to(terminal<R>* result, const B& backend)
result->value = boost::lexical_cast<R>(backend.str(0, std::ios_base::fmtflags(0)));
}
template <class B1, class B2, expression_template_option et>
inline void eval_convert_to(terminal<number<B1, et> >* result, const B2& backend)
{
//
// We ran out of types to try for the conversion, try
// a generic conversion and hope for the best:
//
boost::multiprecision::detail::generic_interconvert(result->value.backend(), backend, number_category<B1>(), number_category<B2>());
}
template <class B>
inline void eval_convert_to(std::string* result, const B& backend)
{

View File

@@ -35,36 +35,37 @@ void generic_interconvert(To& to, const From& from, const mpl::int_<number_kind_
using default_ops::eval_right_shift;
using default_ops::eval_ldexp;
using default_ops::eval_add;
using default_ops::eval_is_zero;
// smallest unsigned type handled natively by "From" is likely to be it's limb_type:
typedef typename canonical<unsigned char, From>::type limb_type;
typedef typename canonical<unsigned char, From>::type l_limb_type;
// get the corresponding type that we can assign to "To":
typedef typename canonical<limb_type, To>::type to_type;
typedef typename canonical<l_limb_type, To>::type to_type;
From t(from);
bool is_neg = eval_get_sign(t) < 0;
if(is_neg)
t.negate();
// Pick off the first limb:
limb_type limb;
limb_type mask = ~static_cast<limb_type>(0);
l_limb_type limb;
l_limb_type mask = static_cast<l_limb_type>(~static_cast<l_limb_type>(0));
From fl;
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
to = static_cast<to_type>(limb);
eval_right_shift(t, std::numeric_limits<limb_type>::digits);
eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
//
// Then keep picking off more limbs until "t" is zero:
//
To l;
unsigned shift = std::numeric_limits<limb_type>::digits;
unsigned shift = std::numeric_limits<l_limb_type>::digits;
while(!eval_is_zero(t))
{
eval_bitwise_and(fl, t, mask);
eval_convert_to(&limb, fl);
l = static_cast<to_type>(limb);
eval_right_shift(t, std::numeric_limits<limb_type>::digits);
eval_right_shift(t, std::numeric_limits<l_limb_type>::digits);
eval_ldexp(l, l, shift);
eval_add(to, l);
shift += std::numeric_limits<limb_type>::digits;
shift += std::numeric_limits<l_limb_type>::digits;
}
//
// Finish off by setting the sign:

View File

@@ -761,7 +761,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
if(bl && is_self(e.left()))
if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_add(e.right(), typename right_type::tag_type());
@@ -771,11 +776,6 @@ private:
// Ignore the right node, it's *this, just add the left:
do_add(e.left(), typename left_type::tag_type());
}
else if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
@@ -799,7 +799,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
if(bl && is_self(e.left()))
if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just subtract the right:
do_subtract(e.right(), typename right_type::tag_type());
@@ -810,11 +815,6 @@ private:
do_subtract(e.left(), typename left_type::tag_type());
m_backend.negate();
}
else if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());
@@ -839,7 +839,12 @@ private:
bool bl = contains_self(e.left());
bool br = contains_self(e.right());
if(bl && is_self(e.left()))
if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(bl && is_self(e.left()))
{
// Ignore the left node, it's *this, just add the right:
do_multiplies(e.right(), typename right_type::tag_type());
@@ -849,11 +854,6 @@ private:
// Ignore the right node, it's *this, just add the left:
do_multiplies(e.left(), typename left_type::tag_type());
}
else if(bl && br)
{
self_type temp(e);
temp.m_backend.swap(this->m_backend);
}
else if(!br && (bl || (left_depth >= right_depth)))
{ // br is always false, but if bl is true we must take the this branch:
do_assign(e.left(), typename left_type::tag_type());