summaryrefslogtreecommitdiff
path: root/boost/multiprecision/number.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/multiprecision/number.hpp')
-rw-r--r--boost/multiprecision/number.hpp204
1 files changed, 159 insertions, 45 deletions
diff --git a/boost/multiprecision/number.hpp b/boost/multiprecision/number.hpp
index 76b7931ac3..4dd1fb0283 100644
--- a/boost/multiprecision/number.hpp
+++ b/boost/multiprecision/number.hpp
@@ -3,25 +3,32 @@
// 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_MATH_EXTENDED_REAL_HPP
-#define BOOST_MATH_EXTENDED_REAL_HPP
+#ifndef BOOST_MP_NUMBER_HPP
+#define BOOST_MP_NUMBER_HPP
-#include <boost/config.hpp>
#include <cstdint>
+#include <boost/multiprecision/detail/standalone_config.hpp>
#include <boost/multiprecision/detail/precision.hpp>
#include <boost/multiprecision/detail/generic_interconvert.hpp>
#include <boost/multiprecision/detail/number_compare.hpp>
#include <boost/multiprecision/traits/is_restricted_conversion.hpp>
#include <boost/multiprecision/traits/is_complex.hpp>
+#include <boost/multiprecision/traits/is_convertible_arithmetic.hpp>
#include <boost/multiprecision/detail/hash.hpp>
+#include <boost/multiprecision/detail/number_base.hpp>
#include <istream> // stream operators
#include <cstdio> // EOF
#include <cctype> // isspace
#include <functional> // std::hash
+#include <type_traits>
#ifndef BOOST_NO_CXX17_HDR_STRING_VIEW
#include <string_view>
#endif
+#ifndef BOOST_MP_STANDALONE
+#include <boost/core/nvp.hpp>
+#endif
+
namespace boost {
namespace multiprecision {
@@ -46,30 +53,38 @@ class number
BOOST_MP_FORCEINLINE constexpr number() noexcept(noexcept(Backend())) {}
BOOST_MP_FORCEINLINE constexpr number(const number& e) noexcept(noexcept(Backend(std::declval<Backend const&>()))) : m_backend(e.m_backend) {}
template <class V>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
- (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
-#ifdef BOOST_HAS_FLOAT128
- && !std::is_same<V, __float128>::value
-#endif
- >::type* = 0)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v,
+ typename std::enable_if<
+ (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
+ || std::is_same<std::string, V>::value
+ || std::is_convertible<V, const char*>::value)
+ && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value
+ && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
{
m_backend = canonical_value(v);
}
template <class V>
BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
- std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
+ std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
#ifndef BOOST_INTEL
noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
#endif
: m_backend(canonical_value(v))
{}
- template <class V>
- BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational && std::is_same<self_type, value_type>::value)
-#ifdef BOOST_HAS_FLOAT128
- && !std::is_same<V, __float128>::value
-#endif
- >::type* = 0)
- : m_backend(canonical_value(v), digits10)
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE constexpr number(const V& v, U digits10,
+ typename std::enable_if<
+ (boost::multiprecision::detail::is_convertible_arithmetic<V, Backend>::value
+ || std::is_same<std::string, V>::value
+ || std::is_convertible<V, const char*>::value)
+ && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value
+ && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex)
+ && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)
+ && std::is_same<self_type, value_type>::value
+ && std::is_integral<U>::value
+ && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)
+ && std::is_constructible<Backend, typename detail::canonical<V, Backend>::type const&, unsigned>::value>::type* = nullptr)
+ : m_backend(canonical_value(v), static_cast<unsigned>(digits10))
{}
//
// Conversions from unscoped enum's are implicit:
@@ -80,7 +95,7 @@ class number
constexpr
#endif
number(const V& v, typename std::enable_if<
- std::is_enum<V>::value && std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
+ std::is_enum<V>::value && std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
: number(static_cast<typename std::underlying_type<V>::type>(v))
{}
//
@@ -92,27 +107,28 @@ class number
constexpr
#endif
number(const V& v, typename std::enable_if<
- std::is_enum<V>::value && !std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
+ std::is_enum<V>::value && !std::is_convertible<V, int>::value && !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && !detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
: number(static_cast<typename std::underlying_type<V>::type>(v))
{}
- BOOST_MP_FORCEINLINE constexpr number(const number& e, unsigned digits10)
+ template <class U>
+ BOOST_MP_FORCEINLINE constexpr number(const number& e, U digits10, typename std::enable_if<std::is_constructible<Backend, const Backend&, unsigned>::value && std::is_integral<U>::value && (std::numeric_limits<U>::digits <= std::numeric_limits<unsigned>::digits)>::type* = nullptr)
noexcept(noexcept(Backend(std::declval<Backend const&>(), std::declval<unsigned>())))
- : m_backend(e.m_backend, digits10) {}
+ : m_backend(e.m_backend, static_cast<unsigned>(digits10)) {}
template <class V>
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v, typename std::enable_if<
- (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = 0)
+ (boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && !detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value>::type* = nullptr)
noexcept(noexcept(std::declval<Backend&>() = std::declval<typename detail::canonical<V, Backend>::type const&>()))
{
m_backend = canonical_value(v);
}
template <class V>
explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, typename std::enable_if<
- detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = 0)
+ detail::is_explicitly_convertible<typename detail::canonical<V, Backend>::type, Backend>::value && (detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value || !std::is_convertible<typename detail::canonical<V, Backend>::type, Backend>::value)>::type* = nullptr)
noexcept(noexcept(Backend(std::declval<typename detail::canonical<V, Backend>::type const&>())))
: m_backend(canonical_value(v)) {}
template <class V>
- explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = 0)
+ explicit BOOST_MP_FORCEINLINE constexpr number(const V& v, unsigned digits10, typename std::enable_if<(boost::multiprecision::detail::is_arithmetic<V>::value || std::is_same<std::string, V>::value || std::is_convertible<V, const char*>::value) && detail::is_restricted_conversion<typename detail::canonical<V, Backend>::type, Backend>::value && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_complex) && (boost::multiprecision::number_category<Backend>::value != boost::multiprecision::number_kind_rational)>::type* = nullptr)
: m_backend(canonical_value(v), digits10) {}
template <expression_template_option ET>
@@ -121,13 +137,13 @@ class number
template <class Other, expression_template_option ET>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val,
- typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
+ typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
noexcept(noexcept(Backend(std::declval<Other const&>())))
: m_backend(val.backend()) {}
template <class Other, expression_template_option ET>
explicit BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
- (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = 0)
+ (!detail::is_explicitly_convertible<Other, Backend>::value)>::type* = nullptr)
{
//
// Attempt a generic interconvertion:
@@ -149,12 +165,61 @@ class number
}
template <class Other, expression_template_option ET>
explicit BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& val, typename std::enable_if<
- (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = 0) noexcept(noexcept(Backend(std::declval<Other const&>())))
+ (detail::is_explicitly_convertible<Other, Backend>::value && (detail::is_restricted_conversion<Other, Backend>::value || !std::is_convertible<Other, Backend>::value))>::type* = nullptr) noexcept(noexcept(Backend(std::declval<Other const&>())))
: m_backend(val.backend()) {}
template <class V, class U>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
- typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = 0)
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(v2)))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, U&& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(V&& v1, U&& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ && !boost::multiprecision::detail::is_variable_precision<Backend>::value)>::type* = nullptr)
+ : m_backend(canonical_value(detail::evaluate_if_expression(static_cast<V&&>(v1))), canonical_value(detail::evaluate_if_expression(static_cast<U&&>(v2))))
+ {
+ }
+ template <class V, class U>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
+ typename std::enable_if<
+ (std::is_convertible<V, value_type>::value
+ && std::is_convertible<U, value_type>::value
+ && !std::is_same<value_type, self_type>::value
+ && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const V&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const U&>()))>::type>::type, Backend>::type const&>::value
+ || boost::multiprecision::detail::is_variable_precision<Backend>::value))>::type* = nullptr)
{
using default_ops::assign_components;
// Copy precision options from this type to component_type:
@@ -167,7 +232,7 @@ class number
template <class V, class U>
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2,
typename std::enable_if<
- (std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = 0)
+ (std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value && !std::is_same<V, self_type>::value && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
{
using default_ops::assign_components;
// Copy precision options from this type to component_type:
@@ -207,16 +272,21 @@ class number
template <class V, class U>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
- typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = 0)
+ typename std::enable_if<(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value && !std::is_same<value_type, self_type>::value)>::type* = nullptr)
: m_backend(canonical_value(detail::evaluate_if_expression(v1)), canonical_value(detail::evaluate_if_expression(v2)), digits10)
{}
template <class V, class U>
BOOST_MP_FORCEINLINE explicit BOOST_MP_CXX14_CONSTEXPR number(const V& v1, const U& v2, unsigned digits10,
- typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value) && !(is_convertible<V, value_type>::value && is_convertible<U, value_type>::value)>::type* = 0)
+ typename std::enable_if<((std::is_constructible<value_type, V>::value || std::is_convertible<V, std::string>::value) && (std::is_constructible<value_type, U>::value || std::is_convertible<U, std::string>::value) && !std::is_same<value_type, self_type>::value) && !(std::is_convertible<V, value_type>::value && std::is_convertible<U, value_type>::value)>::type* = nullptr)
: m_backend(detail::evaluate_if_expression(v1), detail::evaluate_if_expression(v2), digits10) {}
template <class Other, expression_template_option ET>
- BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(const number<Other, ET>& v1, const number<Other, ET>& v2, typename std::enable_if<std::is_convertible<Other, Backend>::value>::type* = 0)
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(
+ const number<Other, ET>& v1,
+ const number<Other, ET>& v2,
+ typename std::enable_if<
+ std::is_convertible<Other, Backend>::value
+ && (!std::is_constructible<Backend, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&, typename detail::canonical<typename std::remove_cv<typename std::remove_reference<decltype(detail::evaluate_if_expression(std::declval<const number<Other, ET>&>()))>::type>::type, Backend>::type const&>::value || boost::multiprecision::detail::is_variable_precision<Backend>::value) >::type* = nullptr)
{
using default_ops::assign_components;
detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(v1, v2);
@@ -253,7 +323,7 @@ class number
BOOST_MP_CXX14_CONSTEXPR number& assign(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e)
{
using tag_type = std::integral_constant<bool, is_equivalent_number_type<number, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value>;
- detail::scoped_default_precision<number<Backend, ExpressionTemplates> > precision_guard(e);
+
//
// If the current precision of *this differs from that of expression e, then we
// create a temporary (which will have the correct precision thanks to precision_guard)
@@ -266,12 +336,16 @@ class number
BOOST_IF_CONSTEXPR(std::is_same<self_type, typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type>::value)
{
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
- if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
+ {
+ const detail::scoped_default_precision<number<Backend, ExpressionTemplates>> precision_guard(e);
+
+ if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
{
number t;
t.assign(e);
return *this = std::move(t);
}
+ }
}
do_assign(e, tag_type());
return *this;
@@ -325,6 +399,7 @@ class number
{
number t(v, digits10_or_component);
boost::multiprecision::detail::scoped_source_precision<self_type> scope;
+ static_cast<void>(scope);
return *this = t;
}
template <class Other, expression_template_option ET>
@@ -357,7 +432,7 @@ class number
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
- BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
+ BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e, typename std::enable_if<std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
{
//
// No preicsion guard here, we already have one in operator=
@@ -366,7 +441,7 @@ class number
}
template <class tag, class Arg1, class Arg2, class Arg3, class Arg4>
explicit BOOST_MP_CXX14_CONSTEXPR number(const detail::expression<tag, Arg1, Arg2, Arg3, Arg4>& e,
- typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = 0)
+ typename std::enable_if<!std::is_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value && boost::multiprecision::detail::is_explicitly_convertible<typename detail::expression<tag, Arg1, Arg2, Arg3, Arg4>::result_type, self_type>::value>::type* = nullptr)
{
//
// No precision guard as assign has one already:
@@ -386,7 +461,7 @@ class number
}
template <class Other, expression_template_option ET>
BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR number(number<Other, ET>&& val,
- typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = 0)
+ typename std::enable_if<(std::is_convertible<Other, Backend>::value && !detail::is_restricted_conversion<Other, Backend>::value)>::type* = nullptr)
noexcept(noexcept(Backend(std::declval<Other const&>())))
: m_backend(static_cast<number<Other, ET>&&>(val).backend()) {}
template <class Other, expression_template_option ET>
@@ -646,7 +721,7 @@ class number
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
{
- number t(*this + v);
+ number t(*this * v);
return *this = std::move(t);
}
@@ -816,7 +891,7 @@ class number
BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(number)
if (precision_guard.precision() != boost::multiprecision::detail::current_precision_of<self_type>(*this))
{
- number t(*this + v);
+ number t(*this / v);
return *this = std::move(t);
}
@@ -954,11 +1029,14 @@ class number
{
return m_backend.str(digits, f);
}
+
+ #ifndef BOOST_MP_STANDALONE
template <class Archive>
void serialize(Archive& ar, const unsigned int /*version*/)
{
ar& boost::make_nvp("backend", m_backend);
}
+ #endif
private:
template <class T>
@@ -991,7 +1069,7 @@ class number
#if BOOST_WORKAROUND(BOOST_MSVC, < 1900) || (defined(__apple_build_version__) && BOOST_WORKAROUND(__clang_major__, < 9))
template <class T>
#else
- template <class T, class = typename std::enable_if<std::is_enum<T>::value || !(std::is_constructible<T, self_type const&>::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
+ template <class T, class = typename std::enable_if<std::is_enum<T>::value || !(std::is_constructible<T, detail::convertible_to<self_type const&> >::value || !std::is_default_constructible<T>::value || (!boost::multiprecision::detail::is_arithmetic<T>::value && !boost::multiprecision::detail::is_complex<T>::value)), T>::type>
#endif
explicit BOOST_MP_CXX14_CONSTEXPR operator T() const
{
@@ -1043,6 +1121,7 @@ class number
static BOOST_MP_CXX14_CONSTEXPR void default_variable_precision_options(variable_precision_options opts)
{
Backend::default_variable_precision_options(opts);
+ Backend::thread_default_variable_precision_options(opts);
}
static BOOST_MP_CXX14_CONSTEXPR void thread_default_variable_precision_options(variable_precision_options opts)
{
@@ -2096,6 +2175,15 @@ class number
using child2_type = typename Exp::right_type ;
return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.middle(), typename child1_type::arity()) || contains_self(e.right(), typename child2_type::arity());
}
+ template <class Exp>
+ BOOST_MP_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR bool contains_self(const Exp& e, std::integral_constant<int, 4> const&) const noexcept
+ {
+ using child0_type = typename Exp::left_type;
+ using child1_type = typename Exp::left_middle_type;
+ using child2_type = typename Exp::right_middle_type;
+ using child3_type = typename Exp::right_type;
+ return contains_self(e.left(), typename child0_type::arity()) || contains_self(e.left_middle(), typename child1_type::arity()) || contains_self(e.right_middle(), typename child2_type::arity()) || contains_self(e.right(), typename child3_type::arity());
+ }
// Test if the expression is a reference to *this:
template <class Exp>
@@ -2158,9 +2246,9 @@ inline std::ostream& operator<<(std::ostream& os, const number<Backend, Expressi
{
char fill = os.fill();
if ((os.flags() & std::ios_base::left) == std::ios_base::left)
- s.append(static_cast<std::string::size_type>(ss - s.size()), fill);
+ s.append(static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
else
- s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - s.size()), fill);
+ s.insert(static_cast<std::string::size_type>(0), static_cast<std::string::size_type>(ss - static_cast<std::streamsize>(s.size())), fill);
}
return os << s;
}
@@ -2241,8 +2329,23 @@ inline std::istream& operator>>(std::istream& is, number<Backend, ExpressionTemp
else
s = detail::read_string_while(is, "+-0123456789");
break;
+ case boost::multiprecision::number_kind_rational:
+ if (oct_format)
+ s = detail::read_string_while(is, "+-01234567/");
+ else if (hex_format)
+ s = detail::read_string_while(is, "+-xXabcdefABCDEF0123456789/");
+ else
+ s = detail::read_string_while(is, "+-0123456789/");
+ break;
case boost::multiprecision::number_kind_floating_point:
- s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
+ BOOST_IF_CONSTEXPR(std::is_same<number<Backend, ExpressionTemplates>, typename number<Backend, ExpressionTemplates>::value_type>::value)
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY");
+ else
+ // Interval:
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY{,}");
+ break;
+ case boost::multiprecision::number_kind_complex:
+ s = detail::read_string_while(is, "+-eE.0123456789infINFnanNANinfinityINFINITY,()");
break;
default:
is >> s;
@@ -2275,6 +2378,17 @@ inline BOOST_MP_CXX14_CONSTEXPR std::size_t hash_value(const number<Backend, Exp
return hash_value(val.backend());
}
+namespace detail {
+
+BOOST_MP_FORCEINLINE bool istream_peek(std::istream& is, char& c, bool have_hex)
+{
+ int i = is.peek();
+ c = static_cast<char>(i);
+ return (EOF != i) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F')));
+}
+
+} // namespace detail
+
} // namespace multiprecision
template <class T>
@@ -2290,7 +2404,7 @@ inline std::istream& operator>>(std::istream& is, rational<multiprecision::numbe
bool hex_format = (is.flags() & std::ios_base::hex) == std::ios_base::hex;
bool oct_format = (is.flags() & std::ios_base::oct) == std::ios_base::oct;
- while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while (multiprecision::detail::istream_peek(is, c, have_hex))
{
if (c == 'x' || c == 'X')
have_hex = true;
@@ -2306,7 +2420,7 @@ inline std::istream& operator>>(std::istream& is, rational<multiprecision::numbe
if (c == '/')
{
is.get();
- while ((EOF != (c = static_cast<char>(is.peek()))) && (c == 'x' || c == 'X' || c == '-' || c == '+' || (c >= '0' && c <= '9') || (have_hex && (c >= 'a' && c <= 'f')) || (have_hex && (c >= 'A' && c <= 'F'))))
+ while (multiprecision::detail::istream_peek(is, c, have_hex))
{
if (c == 'x' || c == 'X')
have_hex = true;