Back to home page

EIC code displayed by LXR

 
 

    


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