annotate DEPENDENCIES/generic/include/boost/math/tools/promotion.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 // boost\math\tools\promotion.hpp
Chris@16 2
Chris@16 3 // Copyright John Maddock 2006.
Chris@16 4 // Copyright Paul A. Bristow 2006.
Chris@16 5
Chris@16 6 // Use, modification and distribution are subject to the
Chris@16 7 // Boost Software License, Version 1.0.
Chris@16 8 // (See accompanying file LICENSE_1_0.txt
Chris@16 9 // or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 10
Chris@16 11 // Promote arguments functions to allow math functions to have arguments
Chris@16 12 // provided as integer OR real (floating-point, built-in or UDT)
Chris@16 13 // (called ArithmeticType in functions that use promotion)
Chris@16 14 // that help to reduce the risk of creating multiple instantiations.
Chris@16 15 // Allows creation of an inline wrapper that forwards to a foo(RT, RT) function,
Chris@16 16 // so you never get to instantiate any mixed foo(RT, IT) functions.
Chris@16 17
Chris@16 18 #ifndef BOOST_MATH_PROMOTION_HPP
Chris@16 19 #define BOOST_MATH_PROMOTION_HPP
Chris@16 20
Chris@16 21 #ifdef _MSC_VER
Chris@16 22 #pragma once
Chris@16 23 #endif
Chris@16 24
Chris@16 25 // Boost type traits:
Chris@16 26 #include <boost/math/tools/config.hpp>
Chris@16 27 #include <boost/type_traits/is_floating_point.hpp> // for boost::is_floating_point;
Chris@16 28 #include <boost/type_traits/is_integral.hpp> // for boost::is_integral
Chris@16 29 #include <boost/type_traits/is_convertible.hpp> // for boost::is_convertible
Chris@16 30 #include <boost/type_traits/is_same.hpp>// for boost::is_same
Chris@16 31 #include <boost/type_traits/remove_cv.hpp>// for boost::remove_cv
Chris@16 32 // Boost Template meta programming:
Chris@16 33 #include <boost/mpl/if.hpp> // for boost::mpl::if_c.
Chris@16 34 #include <boost/mpl/and.hpp> // for boost::mpl::if_c.
Chris@16 35 #include <boost/mpl/or.hpp> // for boost::mpl::if_c.
Chris@16 36 #include <boost/mpl/not.hpp> // for boost::mpl::if_c.
Chris@16 37
Chris@16 38 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Chris@16 39 #include <boost/static_assert.hpp>
Chris@16 40 #endif
Chris@16 41
Chris@16 42 namespace boost
Chris@16 43 {
Chris@16 44 namespace math
Chris@16 45 {
Chris@16 46 namespace tools
Chris@16 47 {
Chris@16 48 // If either T1 or T2 is an integer type,
Chris@16 49 // pretend it was a double (for the purposes of further analysis).
Chris@16 50 // Then pick the wider of the two floating-point types
Chris@16 51 // as the actual signature to forward to.
Chris@16 52 // For example:
Chris@16 53 // foo(int, short) -> double foo(double, double);
Chris@16 54 // foo(int, float) -> double foo(double, double);
Chris@16 55 // Note: NOT float foo(float, float)
Chris@16 56 // foo(int, double) -> foo(double, double);
Chris@16 57 // foo(double, float) -> double foo(double, double);
Chris@16 58 // foo(double, float) -> double foo(double, double);
Chris@16 59 // foo(any-int-or-float-type, long double) -> foo(long double, long double);
Chris@16 60 // but ONLY float foo(float, float) is unchanged.
Chris@16 61 // So the only way to get an entirely float version is to call foo(1.F, 2.F),
Chris@16 62 // But since most (all?) the math functions convert to double internally,
Chris@16 63 // probably there would not be the hoped-for gain by using float here.
Chris@16 64
Chris@16 65 // This follows the C-compatible conversion rules of pow, etc
Chris@16 66 // where pow(int, float) is converted to pow(double, double).
Chris@16 67
Chris@16 68 template <class T>
Chris@16 69 struct promote_arg
Chris@16 70 { // If T is integral type, then promote to double.
Chris@16 71 typedef typename mpl::if_<is_integral<T>, double, T>::type type;
Chris@16 72 };
Chris@16 73 // These full specialisations reduce mpl::if_ usage and speed up
Chris@16 74 // compilation:
Chris@16 75 template <> struct promote_arg<float> { typedef float type; };
Chris@16 76 template <> struct promote_arg<double>{ typedef double type; };
Chris@16 77 template <> struct promote_arg<long double> { typedef long double type; };
Chris@16 78 template <> struct promote_arg<int> { typedef double type; };
Chris@16 79
Chris@16 80 template <class T1, class T2>
Chris@16 81 struct promote_args_2
Chris@16 82 { // Promote, if necessary, & pick the wider of the two floating-point types.
Chris@16 83 // for both parameter types, if integral promote to double.
Chris@16 84 typedef typename promote_arg<T1>::type T1P; // T1 perhaps promoted.
Chris@16 85 typedef typename promote_arg<T2>::type T2P; // T2 perhaps promoted.
Chris@16 86
Chris@16 87 typedef typename mpl::if_<
Chris@16 88 typename mpl::and_<is_floating_point<T1P>, is_floating_point<T2P> >::type, // both T1P and T2P are floating-point?
Chris@16 89 typename mpl::if_< typename mpl::or_<is_same<long double, T1P>, is_same<long double, T2P> >::type, // either long double?
Chris@16 90 long double, // then result type is long double.
Chris@16 91 typename mpl::if_< typename mpl::or_<is_same<double, T1P>, is_same<double, T2P> >::type, // either double?
Chris@16 92 double, // result type is double.
Chris@16 93 float // else result type is float.
Chris@16 94 >::type
Chris@16 95 >::type,
Chris@16 96 // else one or the other is a user-defined type:
Chris@16 97 typename mpl::if_< typename mpl::and_<mpl::not_<is_floating_point<T2P> >, ::boost::is_convertible<T1P, T2P> >, T2P, T1P>::type>::type type;
Chris@16 98 }; // promote_arg2
Chris@16 99 // These full specialisations reduce mpl::if_ usage and speed up
Chris@16 100 // compilation:
Chris@16 101 template <> struct promote_args_2<float, float> { typedef float type; };
Chris@16 102 template <> struct promote_args_2<double, double>{ typedef double type; };
Chris@16 103 template <> struct promote_args_2<long double, long double> { typedef long double type; };
Chris@16 104 template <> struct promote_args_2<int, int> { typedef double type; };
Chris@16 105 template <> struct promote_args_2<int, float> { typedef double type; };
Chris@16 106 template <> struct promote_args_2<float, int> { typedef double type; };
Chris@16 107 template <> struct promote_args_2<int, double> { typedef double type; };
Chris@16 108 template <> struct promote_args_2<double, int> { typedef double type; };
Chris@16 109 template <> struct promote_args_2<int, long double> { typedef long double type; };
Chris@16 110 template <> struct promote_args_2<long double, int> { typedef long double type; };
Chris@16 111 template <> struct promote_args_2<float, double> { typedef double type; };
Chris@16 112 template <> struct promote_args_2<double, float> { typedef double type; };
Chris@16 113 template <> struct promote_args_2<float, long double> { typedef long double type; };
Chris@16 114 template <> struct promote_args_2<long double, float> { typedef long double type; };
Chris@16 115 template <> struct promote_args_2<double, long double> { typedef long double type; };
Chris@16 116 template <> struct promote_args_2<long double, double> { typedef long double type; };
Chris@16 117
Chris@16 118 template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
Chris@16 119 struct promote_args
Chris@16 120 {
Chris@16 121 typedef typename promote_args_2<
Chris@16 122 typename remove_cv<T1>::type,
Chris@16 123 typename promote_args_2<
Chris@16 124 typename remove_cv<T2>::type,
Chris@16 125 typename promote_args_2<
Chris@16 126 typename remove_cv<T3>::type,
Chris@16 127 typename promote_args_2<
Chris@16 128 typename remove_cv<T4>::type,
Chris@16 129 typename promote_args_2<
Chris@16 130 typename remove_cv<T5>::type, typename remove_cv<T6>::type
Chris@16 131 >::type
Chris@16 132 >::type
Chris@16 133 >::type
Chris@16 134 >::type
Chris@16 135 >::type type;
Chris@16 136
Chris@16 137 #ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
Chris@16 138 //
Chris@16 139 // Guard against use of long double if it's not supported:
Chris@16 140 //
Chris@16 141 BOOST_STATIC_ASSERT_MSG((0 == ::boost::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.");
Chris@16 142 #endif
Chris@16 143 };
Chris@16 144
Chris@16 145 //
Chris@16 146 // This struct is the same as above, but has no static assert on long double usage,
Chris@16 147 // it should be used only on functions that can be implemented for long double
Chris@16 148 // even when std lib support is missing or broken for that type.
Chris@16 149 //
Chris@16 150 template <class T1, class T2=float, class T3=float, class T4=float, class T5=float, class T6=float>
Chris@16 151 struct promote_args_permissive
Chris@16 152 {
Chris@16 153 typedef typename promote_args_2<
Chris@16 154 typename remove_cv<T1>::type,
Chris@16 155 typename promote_args_2<
Chris@16 156 typename remove_cv<T2>::type,
Chris@16 157 typename promote_args_2<
Chris@16 158 typename remove_cv<T3>::type,
Chris@16 159 typename promote_args_2<
Chris@16 160 typename remove_cv<T4>::type,
Chris@16 161 typename promote_args_2<
Chris@16 162 typename remove_cv<T5>::type, typename remove_cv<T6>::type
Chris@16 163 >::type
Chris@16 164 >::type
Chris@16 165 >::type
Chris@16 166 >::type
Chris@16 167 >::type type;
Chris@16 168 };
Chris@16 169
Chris@16 170 } // namespace tools
Chris@16 171 } // namespace math
Chris@16 172 } // namespace boost
Chris@16 173
Chris@16 174 #endif // BOOST_MATH_PROMOTION_HPP
Chris@16 175