bitscan.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. ///////////////////////////////////////////////////////////////
  2. // Copyright 2013 John Maddock. Distributed under the Boost
  3. // Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_
  5. //
  6. // Comparison operators for cpp_int_backend:
  7. //
  8. #ifndef BOOST_MP_DETAIL_BITSCAN_HPP
  9. #define BOOST_MP_DETAIL_BITSCAN_HPP
  10. namespace boost{ namespace multiprecision{ namespace detail{
  11. template <class Unsigned>
  12. inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
  13. {
  14. unsigned result = 0;
  15. while(!(mask & 1u))
  16. {
  17. mask >>= 1;
  18. ++result;
  19. }
  20. return result;
  21. }
  22. template <class Unsigned>
  23. inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
  24. {
  25. unsigned index = 0;
  26. while(mask)
  27. {
  28. ++index;
  29. mask >>= 1;
  30. }
  31. return --index;
  32. }
  33. #if defined(BOOST_MSVC) && (defined(_M_IX86) || defined(_M_X64))
  34. BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&)
  35. {
  36. unsigned long result;
  37. _BitScanForward(&result, mask);
  38. return result;
  39. }
  40. BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
  41. {
  42. unsigned long result;
  43. _BitScanReverse(&result, mask);
  44. return result;
  45. }
  46. #ifdef _M_X64
  47. BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64 mask, const mpl::int_<2>&)
  48. {
  49. unsigned long result;
  50. _BitScanForward64(&result, mask);
  51. return result;
  52. }
  53. template <class Unsigned>
  54. BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
  55. {
  56. unsigned long result;
  57. _BitScanReverse64(&result, mask);
  58. return result;
  59. }
  60. #endif
  61. template <class Unsigned>
  62. BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
  63. {
  64. typedef typename make_unsigned<Unsigned>::type ui_type;
  65. typedef typename mpl::if_c<
  66. sizeof(Unsigned) <= sizeof(unsigned long),
  67. mpl::int_<1>,
  68. #ifdef _M_X64
  69. typename mpl::if_c<
  70. sizeof(Unsigned) <= sizeof(__int64),
  71. mpl::int_<2>,
  72. mpl::int_<0>
  73. >::type
  74. #else
  75. mpl::int_<0>
  76. #endif
  77. >::type tag_type;
  78. return find_lsb(static_cast<ui_type>(mask), tag_type());
  79. }
  80. template <class Unsigned>
  81. BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
  82. {
  83. typedef typename make_unsigned<Unsigned>::type ui_type;
  84. typedef typename mpl::if_c<
  85. sizeof(Unsigned) <= sizeof(unsigned long),
  86. mpl::int_<1>,
  87. #ifdef _M_X64
  88. typename mpl::if_c<
  89. sizeof(Unsigned) <= sizeof(__int64),
  90. mpl::int_<2>,
  91. mpl::int_<0>
  92. >::type
  93. #else
  94. mpl::int_<0>
  95. #endif
  96. >::type tag_type;
  97. return find_msb(static_cast<ui_type>(mask), tag_type());
  98. }
  99. #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
  100. BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
  101. {
  102. return __builtin_ctz(mask);
  103. }
  104. BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
  105. {
  106. return __builtin_ctzl(mask);
  107. }
  108. BOOST_FORCEINLINE unsigned find_lsb(unsigned long long mask, mpl::int_<3> const&)
  109. {
  110. return __builtin_ctzll(mask);
  111. }
  112. BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
  113. {
  114. return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask);
  115. }
  116. BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
  117. {
  118. return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
  119. }
  120. BOOST_FORCEINLINE unsigned find_msb(unsigned long long mask, mpl::int_<3> const&)
  121. {
  122. return sizeof(unsigned long long) * CHAR_BIT - 1 - __builtin_clzll(mask);
  123. }
  124. template <class Unsigned>
  125. BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
  126. {
  127. typedef typename make_unsigned<Unsigned>::type ui_type;
  128. typedef typename mpl::if_c<
  129. sizeof(Unsigned) <= sizeof(unsigned),
  130. mpl::int_<1>,
  131. typename mpl::if_c<
  132. sizeof(Unsigned) <= sizeof(unsigned long),
  133. mpl::int_<2>,
  134. typename mpl::if_c<
  135. sizeof(Unsigned) <= sizeof(unsigned long long),
  136. mpl::int_<3>,
  137. mpl::int_<0>
  138. >::type
  139. >::type
  140. >::type tag_type;
  141. return find_lsb(static_cast<ui_type>(mask), tag_type());
  142. }
  143. template <class Unsigned>
  144. BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
  145. {
  146. typedef typename make_unsigned<Unsigned>::type ui_type;
  147. typedef typename mpl::if_c<
  148. sizeof(Unsigned) <= sizeof(unsigned),
  149. mpl::int_<1>,
  150. typename mpl::if_c<
  151. sizeof(Unsigned) <= sizeof(unsigned long),
  152. mpl::int_<2>,
  153. typename mpl::if_c<
  154. sizeof(Unsigned) <= sizeof(unsigned long long),
  155. mpl::int_<3>,
  156. mpl::int_<0>
  157. >::type
  158. >::type
  159. >::type tag_type;
  160. return find_msb(static_cast<ui_type>(mask), tag_type());
  161. }
  162. #elif defined(BOOST_INTEL)
  163. BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
  164. {
  165. return _bit_scan_forward(mask);
  166. }
  167. BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
  168. {
  169. return _bit_scan_reverse(mask);
  170. }
  171. template <class Unsigned>
  172. BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
  173. {
  174. typedef typename make_unsigned<Unsigned>::type ui_type;
  175. typedef typename mpl::if_c<
  176. sizeof(Unsigned) <= sizeof(unsigned),
  177. mpl::int_<1>,
  178. mpl::int_<0>
  179. >::type tag_type;
  180. return find_lsb(static_cast<ui_type>(mask), tag_type());
  181. }
  182. template <class Unsigned>
  183. BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
  184. {
  185. typedef typename make_unsigned<Unsigned>::type ui_type;
  186. typedef typename mpl::if_c<
  187. sizeof(Unsigned) <= sizeof(unsigned),
  188. mpl::int_<1>,
  189. mpl::int_<0>
  190. >::type tag_type;
  191. return find_msb(static_cast<ui_type>(mask), tag_type());
  192. }
  193. #else
  194. template <class Unsigned>
  195. BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
  196. {
  197. return find_lsb(mask, mpl::int_<0>());
  198. }
  199. template <class Unsigned>
  200. BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
  201. {
  202. return find_msb(mask, mpl::int_<0>());
  203. }
  204. #endif
  205. }}}
  206. #endif