/////////////////////////////////////////////////////////////////////////////// // Copyright 2018 John Maddock. 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_PRECISION_HPP #define BOOST_MP_PRECISION_HPP #include #include namespace boost{ namespace multiprecision{ namespace detail{ template inline unsigned current_precision_of_imp(const boost::multiprecision::number& n, const mpl::true_&) { return n.precision(); } template inline BOOST_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number&, const mpl::false_&) { return std::numeric_limits >::digits10; } template inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal&) { return std::numeric_limits::digits10; } template inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal(&)[N]) { // For string literals: return 0; } template inline BOOST_CONSTEXPR unsigned current_precision_of(const boost::multiprecision::number& n) { return current_precision_of_imp(n, boost::multiprecision::detail::is_variable_precision >()); } template inline BOOST_CONSTEXPR unsigned current_precision_of(const expression& expr) { return current_precision_of(expr.left_ref()); } template inline BOOST_CONSTEXPR unsigned current_precision_of(const expression& expr) { return current_precision_of(expr.value()); } template inline BOOST_CONSTEXPR unsigned current_precision_of(const expression& expr) { return (std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_ref())); } template inline BOOST_CONSTEXPR unsigned current_precision_of(const expression& expr) { return (std::max)((std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_ref())), current_precision_of(expr.middle_ref())); } template ::value> struct scoped_default_precision { template scoped_default_precision(const T&) {} template scoped_default_precision(const T&, const U&) {} template scoped_default_precision(const T&, const U&, const V&) {} }; template struct scoped_default_precision { template scoped_default_precision(const T& a) { init(current_precision_of(a)); } template scoped_default_precision(const T& a, const U& b) { init((std::max)(current_precision_of(a), current_precision_of(b))); } template scoped_default_precision(const T& a, const U& b, const V& c) { init((std::max)((std::max)(current_precision_of(a), current_precision_of(b)), current_precision_of(c))); } ~scoped_default_precision() { R::default_precision(m_prec); } private: void init(unsigned p) { m_prec = R::default_precision(); if (p) R::default_precision(p); } unsigned m_prec; }; template inline void maybe_promote_precision(T*, const mpl::false_&){} template inline void maybe_promote_precision(T* obj, const mpl::true_&) { if (obj->precision() != T::default_precision()) { obj->precision(T::default_precision()); } } template inline void maybe_promote_precision(T* obj) { maybe_promote_precision(obj, boost::multiprecision::detail::is_variable_precision()); } #ifndef BOOST_NO_CXX17_IF_CONSTEXPR # define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) if constexpr (boost::multiprecision::detail::is_variable_precision::value) #else # define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) if(boost::multiprecision::detail::is_variable_precision::value) #endif } } } #endif // BOOST_MP_IS_BACKEND_HPP