![]() |
|
|||
File indexing completed on 2025-09-16 08:39:08
0001 // boost\math\tools\promotion.hpp 0002 0003 // Copyright John Maddock 2006. 0004 // Copyright Paul A. Bristow 2006. 0005 // Copyright Matt Borland 2023. 0006 // Copyright Ryan Elandt 2023. 0007 0008 // Use, modification and distribution are subject to the 0009 // Boost Software License, Version 1.0. 0010 // (See accompanying file LICENSE_1_0.txt 0011 // or copy at http://www.boost.org/LICENSE_1_0.txt) 0012 0013 // Promote arguments functions to allow math functions to have arguments 0014 // provided as integer OR real (floating-point, built-in or UDT) 0015 // (called ArithmeticType in functions that use promotion) 0016 // that help to reduce the risk of creating multiple instantiations. 0017 // Allows creation of an inline wrapper that forwards to a foo(RT, RT) function, 0018 // so you never get to instantiate any mixed foo(RT, IT) functions. 0019 0020 #ifndef BOOST_MATH_PROMOTION_HPP 0021 #define BOOST_MATH_PROMOTION_HPP 0022 0023 #ifdef _MSC_VER 0024 #pragma once 0025 #endif 0026 0027 #include <boost/math/tools/config.hpp> 0028 #include <boost/math/tools/type_traits.hpp> 0029 0030 namespace boost 0031 { 0032 namespace math 0033 { 0034 namespace tools 0035 { 0036 ///// This promotion system works as follows: 0037 // 0038 // Rule<T1> (one argument promotion rule): 0039 // - Promotes `T` to `double` if `T` is an integer type as identified by 0040 // `std::is_integral`, otherwise is `T` 0041 // 0042 // Rule<T1, T2_to_TN...> (two or more argument promotion rule): 0043 // - 1. Calculates type using applying Rule<T1>. 0044 // - 2. Calculates type using applying Rule<T2_to_TN...> 0045 // - If the type calculated in 1 and 2 are both floating point types, as 0046 // identified by `std::is_floating_point`, then return the type 0047 // determined by `std::common_type`. Otherwise return the type using 0048 // an asymmetric convertibility rule. 0049 // 0050 ///// Discussion: 0051 // 0052 // If either T1 or T2 is an integer type, 0053 // pretend it was a double (for the purposes of further analysis). 0054 // Then pick the wider of the two floating-point types 0055 // as the actual signature to forward to. 0056 // For example: 0057 // foo(int, short) -> double foo(double, double); // ***NOT*** float foo(float, float) 0058 // foo(int, float) -> double foo(double, double); // ***NOT*** float foo(float, float) 0059 // foo(int, double) -> foo(double, double); 0060 // foo(double, float) -> double foo(double, double); 0061 // foo(double, float) -> double foo(double, double); 0062 // foo(any-int-or-float-type, long double) -> foo(long double, long double); 0063 // ONLY float foo(float, float) is unchanged, so the only way to get an 0064 // entirely float version is to call foo(1.F, 2.F). But since most (all?) the 0065 // math functions convert to double internally, probably there would not be the 0066 // hoped-for gain by using float here. 0067 // 0068 // This follows the C-compatible conversion rules of pow, etc 0069 // where pow(int, float) is converted to pow(double, double). 0070 0071 0072 // Promotes a single argument to double if it is an integer type 0073 template <class T> 0074 struct promote_arg { 0075 using type = typename boost::math::conditional<boost::math::is_integral<T>::value, double, T>::type; 0076 }; 0077 0078 0079 // Promotes two arguments, neither of which is an integer type using an asymmetric 0080 // convertibility rule. 0081 template <class T1, class T2, bool = (boost::math::is_floating_point<T1>::value && boost::math::is_floating_point<T2>::value)> 0082 struct pa2_integral_already_removed { 0083 using type = typename boost::math::conditional< 0084 !boost::math::is_floating_point<T2>::value && boost::math::is_convertible<T1, T2>::value, 0085 T2, T1>::type; 0086 }; 0087 // For two floating point types, promotes using `std::common_type` functionality 0088 template <class T1, class T2> 0089 struct pa2_integral_already_removed<T1, T2, true> { 0090 using type = boost::math::common_type_t<T1, T2, float>; 0091 }; 0092 0093 0094 // Template definition for promote_args_permissive 0095 template <typename... Args> 0096 struct promote_args_permissive; 0097 // Specialization for one argument 0098 template <typename T> 0099 struct promote_args_permissive<T> { 0100 using type = typename promote_arg<typename boost::math::remove_cv<T>::type>::type; 0101 }; 0102 // Specialization for two or more arguments 0103 template <typename T1, typename... T2_to_TN> 0104 struct promote_args_permissive<T1, T2_to_TN...> { 0105 using type = typename pa2_integral_already_removed< 0106 typename promote_args_permissive<T1>::type, 0107 typename promote_args_permissive<T2_to_TN...>::type 0108 >::type; 0109 }; 0110 0111 template <class... Args> 0112 using promote_args_permissive_t = typename promote_args_permissive<Args...>::type; 0113 0114 0115 // Same as `promote_args_permissive` but with a static assertion that the promoted type 0116 // is not `long double` if `BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS` is defined 0117 template <class... Args> 0118 struct promote_args { 0119 using type = typename promote_args_permissive<Args...>::type; 0120 #if defined(BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS) 0121 // 0122 // Guard against use of long double if it's not supported: 0123 // 0124 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."); 0125 #endif 0126 }; 0127 0128 template <class... Args> 0129 using promote_args_t = typename promote_args<Args...>::type; 0130 0131 } // namespace tools 0132 } // namespace math 0133 } // namespace boost 0134 0135 #endif // BOOST_MATH_PROMOTION_HPP
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |