integer_log2.hpp 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. // -----------------------------------------------------------
  2. // integer_log2.hpp
  3. //
  4. // Gives the integer part of the logarithm, in base 2, of a
  5. // given number. Behavior is undefined if the argument is <= 0.
  6. //
  7. // Copyright (c) 2003-2004, 2008 Gennaro Prota
  8. //
  9. // Distributed under the Boost Software License, Version 1.0.
  10. // (See accompanying file LICENSE_1_0.txt or copy at
  11. // https://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // -----------------------------------------------------------
  14. #ifndef BOOST_INTEGER_INTEGER_LOG2_HPP
  15. #define BOOST_INTEGER_INTEGER_LOG2_HPP
  16. #include <boost/limits.hpp>
  17. #include <boost/config.hpp>
  18. #include <boost/assert.hpp>
  19. #if defined(BOOST_BORLANDC)
  20. #include <climits>
  21. #endif
  22. namespace boost {
  23. namespace detail {
  24. template <typename T>
  25. int integer_log2_impl(T x, int n) {
  26. int result = 0;
  27. while (x != 1) {
  28. const T t = static_cast<T>(x >> n);
  29. if (t) {
  30. result += n;
  31. x = t;
  32. }
  33. n /= 2;
  34. }
  35. return result;
  36. }
  37. // helper to find the maximum power of two
  38. // less than p (more involved than necessary,
  39. // to avoid PTS)
  40. //
  41. template <int p, int n>
  42. struct max_pow2_less {
  43. enum { c = 2*n < p };
  44. BOOST_STATIC_CONSTANT(int, value =
  45. c ? (max_pow2_less< c*p, 2*c*n>::value) : n);
  46. };
  47. template <>
  48. struct max_pow2_less<0, 0> {
  49. BOOST_STATIC_CONSTANT(int, value = 0);
  50. };
  51. // this template is here just for Borland :(
  52. // we could simply rely on numeric_limits but sometimes
  53. // Borland tries to use numeric_limits<const T>, because
  54. // of its usual const-related problems in argument deduction
  55. // - gps
  56. template <typename T>
  57. struct width {
  58. #ifdef BOOST_BORLANDC
  59. BOOST_STATIC_CONSTANT(int, value = sizeof(T) * CHAR_BIT);
  60. #else
  61. BOOST_STATIC_CONSTANT(int, value = (std::numeric_limits<T>::digits));
  62. #endif
  63. };
  64. } // detail
  65. // ---------
  66. // integer_log2
  67. // ---------------
  68. //
  69. template <typename T>
  70. int integer_log2(T x) {
  71. BOOST_ASSERT(x > 0);
  72. const int n = detail::max_pow2_less<
  73. detail::width<T> :: value, 4
  74. > :: value;
  75. return detail::integer_log2_impl(x, n);
  76. }
  77. }
  78. #endif // include guard