math_functions.hpp 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Stephen Cleary 2000.
  4. // (C) Copyright Ion Gaztanaga 2007-2013.
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. //
  10. // See http://www.boost.org/libs/container for documentation.
  11. //
  12. // This file is a slightly modified file from Boost.Pool
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. #ifndef BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
  16. #define BOOST_CONTAINER_DETAIL_MATH_FUNCTIONS_HPP
  17. #ifndef BOOST_CONFIG_HPP
  18. # include <boost/config.hpp>
  19. #endif
  20. #if defined(BOOST_HAS_PRAGMA_ONCE)
  21. # pragma once
  22. #endif
  23. #include <boost/container/detail/config_begin.hpp>
  24. #include <boost/container/detail/workaround.hpp>
  25. #include <climits>
  26. #include <boost/static_assert.hpp>
  27. namespace boost {
  28. namespace container {
  29. namespace dtl {
  30. // Greatest common divisor and least common multiple
  31. //
  32. // gcd is an algorithm that calculates the greatest common divisor of two
  33. // integers, using Euclid's algorithm.
  34. //
  35. // Pre: A > 0 && B > 0
  36. // Recommended: A > B
  37. template <typename Integer>
  38. inline Integer gcd(Integer A, Integer B)
  39. {
  40. do
  41. {
  42. const Integer tmp(B);
  43. B = A % B;
  44. A = tmp;
  45. } while (B != 0);
  46. return A;
  47. }
  48. //
  49. // lcm is an algorithm that calculates the least common multiple of two
  50. // integers.
  51. //
  52. // Pre: A > 0 && B > 0
  53. // Recommended: A > B
  54. template <typename Integer>
  55. inline Integer lcm(const Integer & A, const Integer & B)
  56. {
  57. Integer ret = A;
  58. ret /= gcd(A, B);
  59. ret *= B;
  60. return ret;
  61. }
  62. template <typename Integer>
  63. inline Integer log2_ceil(const Integer & A)
  64. {
  65. Integer i = 0;
  66. Integer power_of_2 = 1;
  67. while(power_of_2 < A){
  68. power_of_2 <<= 1;
  69. ++i;
  70. }
  71. return i;
  72. }
  73. template <typename Integer>
  74. inline Integer upper_power_of_2(const Integer & A)
  75. {
  76. Integer power_of_2 = 1;
  77. while(power_of_2 < A){
  78. power_of_2 <<= 1;
  79. }
  80. return power_of_2;
  81. }
  82. template <typename Integer, bool Loop = true>
  83. struct upper_power_of_2_loop_ct
  84. {
  85. template <Integer I, Integer P>
  86. struct apply
  87. {
  88. static const Integer value =
  89. upper_power_of_2_loop_ct<Integer, (I > P*2)>::template apply<I, P*2>::value;
  90. };
  91. };
  92. template <typename Integer>
  93. struct upper_power_of_2_loop_ct<Integer, false>
  94. {
  95. template <Integer I, Integer P>
  96. struct apply
  97. {
  98. static const Integer value = P;
  99. };
  100. };
  101. template <typename Integer, Integer I>
  102. struct upper_power_of_2_ct
  103. {
  104. static const Integer value = upper_power_of_2_loop_ct<Integer, (I > 1)>::template apply<I, 2>::value;
  105. };
  106. //This function uses binary search to discover the
  107. //highest set bit of the integer
  108. inline std::size_t floor_log2 (std::size_t x)
  109. {
  110. const std::size_t Bits = sizeof(std::size_t)*CHAR_BIT;
  111. const bool Size_t_Bits_Power_2= !(Bits & (Bits-1));
  112. BOOST_STATIC_ASSERT(((Size_t_Bits_Power_2)== true));
  113. std::size_t n = x;
  114. std::size_t log2 = 0;
  115. for(std::size_t shift = Bits >> 1; shift; shift >>= 1){
  116. std::size_t tmp = n >> shift;
  117. if (tmp)
  118. log2 += shift, n = tmp;
  119. }
  120. return log2;
  121. }
  122. template<std::size_t I1, std::size_t I2>
  123. struct gcd_ct
  124. {
  125. static const std::size_t Max = I1 > I2 ? I1 : I2;
  126. static const std::size_t Min = I1 < I2 ? I1 : I2;
  127. static const std::size_t value = gcd_ct<Min, Max % Min>::value;
  128. };
  129. template<std::size_t I1>
  130. struct gcd_ct<I1, 0>
  131. {
  132. static const std::size_t value = I1;
  133. };
  134. template<std::size_t I1>
  135. struct gcd_ct<0, I1>
  136. {
  137. static const std::size_t value = I1;
  138. };
  139. template<std::size_t I1, std::size_t I2>
  140. struct lcm_ct
  141. {
  142. static const std::size_t value = I1 * I2 / gcd_ct<I1, I2>::value;
  143. };
  144. } // namespace dtl
  145. } // namespace container
  146. } // namespace boost
  147. #include <boost/container/detail/config_end.hpp>
  148. #endif