// Copyright 2023 Matt Borland // Distributed under the Boost Software License, Version 1.0. // https://www.boost.org/LICENSE_1_0.txt #ifndef BOOST_DECIMAL_DETAIL_PROMOTION_HPP #define BOOST_DECIMAL_DETAIL_PROMOTION_HPP #include #include #include #ifndef BOOST_DECIMAL_BUILD_MODULE #include #include #endif namespace boost { namespace decimal { namespace detail { namespace impl { // Assign explicit decimal values because the decimal_fast32_t size could be greater than that // of decimal64_t even though the precision is worse template struct decimal_val { static constexpr int value = 0; }; template <> struct decimal_val { static constexpr int value = 32; }; template <> struct decimal_val { static constexpr int value = 32; }; // Assign a higher value to the fast type for consistency of promotion // Side effect is the same calculation will be faster with the same precision template <> struct decimal_val { static constexpr int value = 33; }; template <> struct decimal_val { static constexpr int value = 64; }; template <> struct decimal_val { static constexpr int value = 64; }; template <> struct decimal_val { static constexpr int value = 65; }; template <> struct decimal_val { static constexpr int value = 128; }; template <> struct decimal_val { static constexpr int value = 128; }; template <> struct decimal_val { static constexpr int value = 129; }; } // namespace impl template constexpr int decimal_val_v = impl::decimal_val::value; namespace impl { // Promotes a single argument to double if it is an integer type template struct promote_arg { using type = std::conditional_t, double, T>; }; template using promote_arg_t = typename promote_arg::type; // Promote two arguments picking in order: // 1) the highest precision decimal type // 2) any decimal type // 3) or the highest precision type in that order template struct promote_2_args { using type = std::conditional_t<(is_decimal_floating_point_v && is_decimal_floating_point_v), std::conditional_t<(decimal_val_v > decimal_val_v), T1, T2>, std::conditional_t, T1, std::conditional_t, T2, std::conditional_t<(sizeof(promote_arg_t) > sizeof(promote_arg_t)), promote_arg_t, promote_arg_t>>>>; }; template using promote_2_args_t = typename promote_2_args::type; // Promote N args using the rules of promote_2_args template struct promote_args; template struct promote_args { using type = promote_arg_t; }; template struct promote_args { using type = promote_2_args_t, typename promote_args::type>; }; } //namespace impl template using promote_args_t = typename impl::promote_args::type; #if BOOST_DECIMAL_DEC_EVAL_METHOD == 0 template using evaluation_type_t = T; #elif BOOST_DECIMAL_DEC_EVAL_METHOD == 1 template using evaluation_type_t = detail::promote_args_t; #else template using evaluation_type_t = detail::promote_args_t; #endif } //namespace detail } //namespace decimal } //namespace boost #endif //BOOST_DECIMAL_DETAIL_PROMOTION_HPP