boost/multiprecision/detail/precision.hpp
/////////////////////////////////////////////////////////////////////////////// // 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 <boost/multiprecision/traits/is_variable_precision.hpp> #include <boost/multiprecision/detail/number_base.hpp> namespace boost{ namespace multiprecision{ namespace detail{ template <class B, boost::multiprecision::expression_template_option ET> inline unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>& n, const mpl::true_&) { return n.precision(); } template <class B, boost::multiprecision::expression_template_option ET> inline BOOST_CONSTEXPR unsigned current_precision_of_imp(const boost::multiprecision::number<B, ET>&, const mpl::false_&) { return std::numeric_limits<boost::multiprecision::number<B, ET> >::digits10; } template <class Terminal> inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal&) { return std::numeric_limits<Terminal>::digits10; } template <class Terminal, std::size_t N> inline BOOST_CONSTEXPR unsigned current_precision_of(const Terminal(&)[N]) { // For string literals: return 0; } template <class B, boost::multiprecision::expression_template_option ET> inline BOOST_CONSTEXPR unsigned current_precision_of(const boost::multiprecision::number<B, ET>& n) { return current_precision_of_imp(n, boost::multiprecision::detail::is_variable_precision<boost::multiprecision::number<B, ET> >()); } template<class tag, class Arg1> inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, void, void, void>& expr) { return current_precision_of(expr.left_ref()); } template<class Arg1> inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<terminal, Arg1, void, void, void>& expr) { return current_precision_of(expr.value()); } template <class tag, class Arg1, class Arg2> inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, Arg2, void, void>& expr) { return (std::max)(current_precision_of(expr.left_ref()), current_precision_of(expr.right_ref())); } template <class tag, class Arg1, class Arg2, class Arg3> inline BOOST_CONSTEXPR unsigned current_precision_of(const expression<tag, Arg1, Arg2, Arg3, void>& 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 <class R, bool = boost::multiprecision::detail::is_variable_precision<R>::value> struct scoped_default_precision { template <class T> scoped_default_precision(const T&) {} template <class T, class U> scoped_default_precision(const T&, const U&) {} template <class T, class U, class V> scoped_default_precision(const T&, const U&, const V&) {} }; template <class R> struct scoped_default_precision<R, true> { template <class T> scoped_default_precision(const T& a) { init(current_precision_of(a)); } template <class T, class U> scoped_default_precision(const T& a, const U& b) { init((std::max)(current_precision_of(a), current_precision_of(b))); } template <class T, class U, class V> 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 <class T> inline void maybe_promote_precision(T*, const mpl::false_&){} template <class T> inline void maybe_promote_precision(T* obj, const mpl::true_&) { if (obj->precision() != T::default_precision()) { obj->precision(T::default_precision()); } } template <class T> inline void maybe_promote_precision(T* obj) { maybe_promote_precision(obj, boost::multiprecision::detail::is_variable_precision<T>()); } #ifndef BOOST_NO_CXX17_IF_CONSTEXPR # define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) if constexpr (boost::multiprecision::detail::is_variable_precision<T>::value) #else # define BOOST_MP_CONSTEXPR_IF_VARIABLE_PRECISION(T) if(boost::multiprecision::detail::is_variable_precision<T>::value) #endif } } } #endif // BOOST_MP_IS_BACKEND_HPP