Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:36:53

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2015-2020, Oracle and/or its affiliates.
0004 
0005 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0006 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0007 
0008 // Licensed under the Boost Software License version 1.0.
0009 // http://www.boost.org/users/license.html
0010 
0011 #ifndef BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
0012 #define BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP
0013 
0014 // For now deactivate the use of multiprecision integers
0015 // TODO: activate it later
0016 #define BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
0017 
0018 
0019 #include <climits>
0020 #include <cstddef>
0021 #include <type_traits>
0022 
0023 #if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
0024 #include <boost/multiprecision/cpp_int.hpp>
0025 #endif
0026 
0027 
0028 namespace boost { namespace geometry
0029 {
0030 
0031 #ifndef DOXYGEN_NO_DETAIL
0032 namespace detail { namespace promote_integral
0033 {
0034 
0035 // meta-function that returns the bit size of a type
0036 template
0037 <
0038     typename T,
0039     bool IsFundamental = std::is_fundamental<T>::value
0040 >
0041 struct bit_size
0042 {};
0043 
0044 
0045 // for fundamental types, just return CHAR_BIT * sizeof(T)
0046 template <typename T>
0047 struct bit_size<T, true>
0048     : std::integral_constant<std::size_t, (CHAR_BIT * sizeof(T))>
0049 {};
0050 
0051 
0052 #if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
0053 // partial specialization for cpp_int
0054 template
0055 <
0056     unsigned MinSize,
0057     unsigned MaxSize,
0058     boost::multiprecision::cpp_integer_type SignType,
0059     boost::multiprecision::cpp_int_check_type Checked,
0060     typename Allocator,
0061     boost::multiprecision::expression_template_option ExpressionTemplates
0062 >
0063 struct bit_size
0064     <
0065         boost::multiprecision::number
0066             <
0067                 boost::multiprecision::cpp_int_backend
0068                     <
0069                         MinSize, MaxSize, SignType, Checked, Allocator
0070                     >,
0071                 ExpressionTemplates
0072             >,
0073         false
0074     >
0075     : std::integral_constant<std::size_t, MaxSize>
0076 {};
0077 #endif // BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER
0078 
0079 
0080 template <typename T, std::size_t MinSize, typename ...Ts>
0081 struct promote_to_larger
0082 {
0083     // if promotion fails, keep the number T
0084     // (and cross fingers that overflow will not occur)
0085     typedef T type;
0086 };
0087 
0088 template <typename T, std::size_t MinSize, typename CurrentT, typename ...Ts>
0089 struct promote_to_larger<T, MinSize, CurrentT, Ts...>
0090 {
0091     typedef std::conditional_t
0092         <
0093             (bit_size<CurrentT>::value >= MinSize),
0094             CurrentT,
0095             typename promote_to_larger<T, MinSize, Ts...>::type
0096         > type;
0097 };
0098 
0099 template <typename ...Ts>
0100 struct integral_types {};
0101 
0102 template <typename T, std::size_t MinSize, typename ...Ts>
0103 struct promote_to_larger<T, MinSize, integral_types<Ts...>>
0104     : promote_to_larger<T, MinSize, Ts...>
0105 {};
0106 
0107 
0108 }} // namespace detail::promote_integral
0109 #endif // DOXYGEN_NO_DETAIL
0110 
0111 
0112 
0113 /*!
0114     \brief Meta-function to define an integral type with size
0115     than is (roughly) twice the bit size of T
0116     \ingroup utility
0117     \details
0118     This meta-function tries to promote the fundamental integral type T
0119     to a another integral type with size (roughly) twice the bit size of T.
0120 
0121     To do this, two times the bit size of T is tested against the bit sizes of:
0122          short, int, long, long long, boost::int128_t
0123     and the one that first matches is chosen.
0124 
0125     For unsigned types the bit size of T is tested against the bit
0126     sizes of the types above, if T is promoted to a signed type, or
0127     the bit sizes of
0128          unsigned short, unsigned int, unsigned long, std::size_t,
0129          unsigned long long, boost::uint128_t
0130     if T is promoted to an unsigned type.
0131 
0132     By default an unsigned type is promoted to a signed type.
0133     This behavior is controlled by the PromoteUnsignedToUnsigned
0134     boolean template parameter, whose default value is "false".
0135     To promote an unsigned type to an unsigned type set the value of
0136     this template parameter to "true".
0137 
0138     If the macro BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is not
0139     defined, boost's multiprecision integer cpp_int<> is used as a
0140     last resort.
0141 
0142     If BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER is defined and an
0143     appropriate type cannot be detected, the input type is returned as is.
0144 
0145     Finally, if the passed type is either a floating-point type or a
0146     user-defined type it is returned as is.
0147 
0148     \note boost::int128_type and boost::uint128_type are considered
0149     only if the macros BOOST_HAS_INT128 and BOOST_GEOMETRY_ENABLE_INT128
0150     are defined
0151 */
0152 template
0153 <
0154     typename T,
0155     bool PromoteUnsignedToUnsigned = false,
0156     bool UseCheckedInteger = false,
0157     bool IsIntegral = std::is_integral<T>::value
0158 >
0159 class promote_integral
0160 {
0161 private:
0162     static bool const is_unsigned = std::is_unsigned<T>::value;
0163 
0164     typedef detail::promote_integral::bit_size<T> bit_size_type;
0165 
0166 #if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
0167     // Define the proper check policy for the multiprecision integer
0168     typedef std::conditional_t
0169         <
0170             UseCheckedInteger,
0171             std::integral_constant
0172                 <
0173                     boost::multiprecision::cpp_int_check_type,
0174                     boost::multiprecision::checked
0175                 >,
0176             std::integral_constant
0177                 <
0178                     boost::multiprecision::cpp_int_check_type,
0179                     boost::multiprecision::unchecked
0180                 >
0181         > check_policy_type;
0182 
0183     // Meta-function to get the multiprecision integer type for the
0184     // given size and sign type (signed/unsigned)
0185     template
0186     <
0187         unsigned int Size,
0188         boost::multiprecision::cpp_integer_type SignType
0189     >
0190     struct multiprecision_integer_type
0191     {
0192         typedef boost::multiprecision::number
0193             <
0194                 boost::multiprecision::cpp_int_backend
0195                     <
0196                         Size,
0197                         Size,
0198                         SignType,
0199                         check_policy_type::value,
0200                         void
0201                     >
0202             > type;
0203     };
0204 #endif
0205 
0206     // Define the minimum size (in bits) needed for the promoted type
0207     // If T is the input type and P the promoted type, then the
0208     // minimum number of bits for P are (below b stands for the number
0209     // of bits of T):
0210     // * if T is unsigned and P is unsigned: 2 * b
0211     // * if T is signed and P is signed: 2 * b - 1
0212     // * if T is unsigned and P is signed: 2 * b + 1
0213     typedef std::conditional_t
0214         <
0215             (PromoteUnsignedToUnsigned && is_unsigned),
0216             std::integral_constant<std::size_t, (2 * bit_size_type::value)>,
0217             std::conditional_t
0218                 <
0219                     is_unsigned,
0220                     std::integral_constant<std::size_t, (2 * bit_size_type::value + 1)>,
0221                     std::integral_constant<std::size_t, (2 * bit_size_type::value - 1)>
0222                 >
0223         > min_bit_size_type;
0224 
0225     // Define the list of signed integral types we are going to use
0226     // for promotion
0227     typedef detail::promote_integral::integral_types
0228         <
0229             short,
0230             int,
0231             long,
0232             long long
0233 #if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
0234             , boost::int128_type
0235 #endif
0236 #if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
0237             , typename multiprecision_integer_type
0238                 <
0239                     min_bit_size_type::value,
0240                     boost::multiprecision::signed_magnitude
0241                 >::type
0242 #endif
0243         > signed_integral_types;
0244 
0245     // Define the list of unsigned integral types we are going to use
0246     // for promotion
0247     typedef detail::promote_integral::integral_types
0248         <
0249             unsigned short,
0250             unsigned int,
0251             unsigned long,
0252             std::size_t,
0253             unsigned long long
0254 #if defined(BOOST_HAS_INT128) && defined(BOOST_GEOMETRY_ENABLE_INT128)
0255             , boost::uint128_type
0256 #endif
0257 #if !defined(BOOST_GEOMETRY_NO_MULTIPRECISION_INTEGER)
0258             , typename multiprecision_integer_type
0259                 <
0260                     min_bit_size_type::value,
0261                     boost::multiprecision::unsigned_magnitude
0262                 >::type
0263 #endif
0264         > unsigned_integral_types;
0265 
0266     // Define the list of integral types that will be used for
0267     // promotion (depending in whether we was to promote unsigned to
0268     // unsigned or not)
0269     typedef std::conditional_t
0270         <
0271             (is_unsigned && PromoteUnsignedToUnsigned),
0272             unsigned_integral_types,
0273             signed_integral_types
0274         > integral_types;
0275 
0276 public:
0277     typedef typename detail::promote_integral::promote_to_larger
0278         <
0279             T,
0280             min_bit_size_type::value,
0281             integral_types
0282         >::type type;
0283 };
0284 
0285 
0286 template <typename T, bool PromoteUnsignedToUnsigned, bool UseCheckedInteger>
0287 class promote_integral
0288     <
0289         T, PromoteUnsignedToUnsigned, UseCheckedInteger, false
0290     >
0291 {
0292 public:
0293     typedef T type;
0294 };
0295 
0296 
0297 }} // namespace boost::geometry
0298 
0299 #endif // BOOST_GEOMETRY_UTIL_PROMOTE_INTEGRAL_HPP