diff options
Diffstat (limited to 'boost/multiprecision/number.hpp')
-rw-r--r-- | boost/multiprecision/number.hpp | 204 |
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; |