brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.5 KiB · a65f370 Raw
136 lines · plain
1// boost\math\tools\promotion.hpp2 3// Copyright John Maddock 2006.4// Copyright Paul A. Bristow 2006.5// Copyright Matt Borland 2023.6// Copyright Ryan Elandt 2023.7 8// Use, modification and distribution are subject to the9// Boost Software License, Version 1.0.10// (See accompanying file LICENSE_1_0.txt11// or copy at http://www.boost.org/LICENSE_1_0.txt)12 13// Promote arguments functions to allow math functions to have arguments14// provided as integer OR real (floating-point, built-in or UDT)15// (called ArithmeticType in functions that use promotion)16// that help to reduce the risk of creating multiple instantiations.17// Allows creation of an inline wrapper that forwards to a foo(RT, RT) function,18// so you never get to instantiate any mixed foo(RT, IT) functions.19 20#ifndef BOOST_MATH_PROMOTION_HPP21#define BOOST_MATH_PROMOTION_HPP22 23#ifdef _MSC_VER24#pragma once25#endif26 27#include <boost/math/tools/config.hpp>28#include <boost/math/tools/type_traits.hpp>29 30namespace boost31{32  namespace math33  {34    namespace tools35    {36      ///// This promotion system works as follows:37      // 38      // Rule<T1> (one argument promotion rule):39      //   - Promotes `T` to `double` if `T` is an integer type as identified by40      //     `std::is_integral`, otherwise is `T`41      //42      // Rule<T1, T2_to_TN...> (two or more argument promotion rule):43      //   - 1. Calculates type using applying Rule<T1>.44      //   - 2. Calculates type using applying Rule<T2_to_TN...> 45      //   - If the type calculated in 1 and 2 are both floating point types, as46      //     identified by `std::is_floating_point`, then return the type47      //     determined by `std::common_type`. Otherwise return the type using48      //     an asymmetric convertibility rule.49      //50      ///// Discussion:51      //52      // If either T1 or T2 is an integer type,53      // pretend it was a double (for the purposes of further analysis).54      // Then pick the wider of the two floating-point types55      // as the actual signature to forward to.56      // For example:57      //    foo(int, short) -> double foo(double, double);  // ***NOT*** float foo(float, float)58      //    foo(int, float) -> double foo(double, double);  // ***NOT*** float foo(float, float)59      //    foo(int, double) -> foo(double, double);60      //    foo(double, float) -> double foo(double, double);61      //    foo(double, float) -> double foo(double, double);62      //    foo(any-int-or-float-type, long double) -> foo(long double, long double);63      // ONLY float foo(float, float) is unchanged, so the only way to get an64      // entirely float version is to call foo(1.F, 2.F). But since most (all?) the65      // math functions convert to double internally, probably there would not be the66      // hoped-for gain by using float here.67      //68      // This follows the C-compatible conversion rules of pow, etc69      // where pow(int, float) is converted to pow(double, double).70 71 72      // Promotes a single argument to double if it is an integer type73      template <class T>74      struct promote_arg {75         using type = typename boost::math::conditional<boost::math::is_integral<T>::value, double, T>::type;76      };77 78 79      // Promotes two arguments, neither of which is an integer type using an asymmetric80      // convertibility rule.81      template <class T1, class T2, bool = (boost::math::is_floating_point<T1>::value && boost::math::is_floating_point<T2>::value)>82      struct pa2_integral_already_removed {83         using type = typename boost::math::conditional<84            !boost::math::is_floating_point<T2>::value && boost::math::is_convertible<T1, T2>::value, 85            T2, T1>::type;86      };87      // For two floating point types, promotes using `std::common_type` functionality 88      template <class T1, class T2>89      struct pa2_integral_already_removed<T1, T2, true> {90         using type = boost::math::common_type_t<T1, T2, float>;91      };92 93 94      // Template definition for promote_args_permissive95      template <typename... Args>96      struct promote_args_permissive;97      // Specialization for one argument98      template <typename T>99      struct promote_args_permissive<T> {100         using type = typename promote_arg<typename boost::math::remove_cv<T>::type>::type;101      };102      // Specialization for two or more arguments103      template <typename T1, typename... T2_to_TN>104      struct promote_args_permissive<T1, T2_to_TN...> {105         using type = typename pa2_integral_already_removed<106                  typename promote_args_permissive<T1>::type,107                  typename promote_args_permissive<T2_to_TN...>::type108               >::type;109      };110 111      template <class... Args>112      using promote_args_permissive_t = typename promote_args_permissive<Args...>::type;113 114 115      // Same as `promote_args_permissive` but with a static assertion that the promoted type116      // is not `long double` if `BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS` is defined117      template <class... Args>118      struct promote_args {119         using type = typename promote_args_permissive<Args...>::type;120#if defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS)121         //122         // Guard against use of long double if it's not supported:123         //124         static_assert((0 == boost::math::is_same<type, long double>::value), "Sorry, but this platform does not have sufficient long double support for the special functions to be reliably implemented.");125#endif126      };127 128      template <class... Args>129      using promote_args_t = typename promote_args<Args...>::type;130 131    } // namespace tools132  } // namespace math133} // namespace boost134 135#endif // BOOST_MATH_PROMOTION_HPP136