Blame view

3rdparty/boost_1_81_0/boost/integer/integer_log2.hpp 3.2 KB
63e88f80   Hu Chunming   提交三方库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
  // -----------------------------------------------------------
  // integer_log2.hpp
  //
  //   Gives the integer part of the logarithm, in base 2, of a
  // given number. Behavior is undefined if the argument is <= 0.
  //
  //        Copyright (c) 2003-2004, 2008 Gennaro Prota
  //            Copyright (c) 2022 Andrey Semashev
  //
  // Distributed under the Boost Software License, Version 1.0.
  //    (See accompanying file LICENSE_1_0.txt or copy at
  //          https://www.boost.org/LICENSE_1_0.txt)
  //
  // -----------------------------------------------------------
  
  #ifndef BOOST_INTEGER_INTEGER_LOG2_HPP
  #define BOOST_INTEGER_INTEGER_LOG2_HPP
  
  #include <climits>
  #include <limits>
  #include <boost/config.hpp>
  #include <boost/assert.hpp>
  #include <boost/cstdint.hpp>
  #include <boost/core/bit.hpp>
  #include <boost/core/enable_if.hpp>
  #include <boost/type_traits/is_integral.hpp>
  #include <boost/type_traits/make_unsigned.hpp>
  
  namespace boost {
  namespace detail {
  
  // helper to find the maximum power of two
  // less than p
  template< unsigned int p, unsigned int n, bool = ((2u * n) < p) >
  struct max_pow2_less :
      public max_pow2_less< p, 2u * n >
  {
  };
  
  template< unsigned int p, unsigned int n >
  struct max_pow2_less< p, n, false >
  {
      BOOST_STATIC_CONSTANT(unsigned int, value = n);
  };
  
  template< typename T >
  inline typename boost::disable_if< boost::is_integral< T >, int >::type integer_log2_impl(T x)
  {
      unsigned int n = detail::max_pow2_less<
          std::numeric_limits< T >::digits,
          CHAR_BIT / 2u
      >::value;
  
      int result = 0;
      while (x != 1)
      {
          T t(x >> n);
          if (t)
          {
              result += static_cast< int >(n);
  #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
              x = static_cast< T&& >(t);
  #else
              x = t;
  #endif
          }
          n >>= 1u;
      }
  
      return result;
  }
  
  template< typename T >
  inline typename boost::enable_if< boost::is_integral< T >, int >::type integer_log2_impl(T x)
  {
      // We could simply rely on numeric_limits but sometimes
      // Borland tries to use numeric_limits<const T>, because
      // of its usual const-related problems in argument deduction
      // - gps
      return static_cast< int >((sizeof(T) * CHAR_BIT - 1u) -
          boost::core::countl_zero(static_cast< typename boost::make_unsigned< T >::type >(x)));
  }
  
  #if defined(BOOST_HAS_INT128)
  // We need to provide explicit overloads for __int128 because (a) boost/core/bit.hpp currently does not support it and
  // (b) std::numeric_limits are not specialized for __int128 in some standard libraries.
  inline int integer_log2_impl(boost::uint128_type x)
  {
      const boost::uint64_t x_hi = static_cast< boost::uint64_t >(x >> 64u);
      if (x_hi != 0u)
          return 127 - boost::core::countl_zero(x_hi);
      else
          return 63 - boost::core::countl_zero(static_cast< boost::uint64_t >(x));
  }
  
  inline int integer_log2_impl(boost::int128_type x)
  {
      return detail::integer_log2_impl(static_cast< boost::uint128_type >(x));
  }
  #endif // defined(BOOST_HAS_INT128)
  
  } // namespace detail
  
  
  // ------------
  // integer_log2
  // ------------
  template< typename T >
  inline int integer_log2(T x)
  {
      BOOST_ASSERT(x > 0);
      return detail::integer_log2_impl(x);
  }
  
  } // namespace boost
  
  #endif // BOOST_INTEGER_INTEGER_LOG2_HPP