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_
6 // Comparison operators for cpp_int_backend:
8 #ifndef BOOST_MP_DETAIL_BITSCAN_HPP
9 #define BOOST_MP_DETAIL_BITSCAN_HPP
11 #include <boost/detail/endian.hpp>
13 #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
17 namespace boost{ namespace multiprecision{ namespace detail{
19 template <class Unsigned>
20 inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
31 template <class Unsigned>
32 inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
43 #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
45 #pragma intrinsic(_BitScanForward,_BitScanReverse)
47 BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&)
50 _BitScanForward(&result, mask);
54 BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
57 _BitScanReverse(&result, mask);
62 #pragma intrinsic(_BitScanForward64,_BitScanReverse64)
64 BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64 mask, const mpl::int_<2>&)
67 _BitScanForward64(&result, mask);
70 template <class Unsigned>
71 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
74 _BitScanReverse64(&result, mask);
79 template <class Unsigned>
80 BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
82 typedef typename make_unsigned<Unsigned>::type ui_type;
83 typedef typename mpl::if_c<
84 sizeof(Unsigned) <= sizeof(unsigned long),
88 sizeof(Unsigned) <= sizeof(__int64),
96 return find_lsb(static_cast<ui_type>(mask), tag_type());
99 template <class Unsigned>
100 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
102 typedef typename make_unsigned<Unsigned>::type ui_type;
103 typedef typename mpl::if_c<
104 sizeof(Unsigned) <= sizeof(unsigned long),
108 sizeof(Unsigned) <= sizeof(__int64),
116 return find_msb(static_cast<ui_type>(mask), tag_type());
119 #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
121 BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
123 return __builtin_ctz(mask);
125 BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
127 return __builtin_ctzl(mask);
129 BOOST_FORCEINLINE unsigned find_lsb(boost::ulong_long_type mask, mpl::int_<3> const&)
131 return __builtin_ctzll(mask);
133 BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
135 return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask);
137 BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
139 return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
141 BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> const&)
143 return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask);
145 #ifdef BOOST_HAS_INT128
147 __extension__ typedef unsigned __int128 uint128_type;
149 BOOST_FORCEINLINE unsigned find_msb(uint128_type mask, mpl::int_<0> const&)
151 union { uint128_type v; boost::uint64_t sv[2]; } val;
153 #ifdef BOOST_LITTLE_ENDIAN
155 return find_msb(val.sv[1], mpl::int_<3>()) + 64;
156 return find_msb(val.sv[0], mpl::int_<3>());
159 return find_msb(val.sv[0], mpl::int_<3>()) + 64;
160 return find_msb(val.sv[1], mpl::int_<3>());
163 BOOST_FORCEINLINE unsigned find_lsb(uint128_type mask, mpl::int_<0> const&)
165 union { uint128_type v; boost::uint64_t sv[2]; } val;
167 #ifdef BOOST_LITTLE_ENDIAN
169 return find_lsb(val.sv[1], mpl::int_<3>()) + 64;
170 return find_lsb(val.sv[0], mpl::int_<3>());
173 return find_lsb(val.sv[0], mpl::int_<3>()) + 64;
174 return find_lsb(val.sv[1], mpl::int_<3>());
179 template <class Unsigned>
180 BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
182 typedef typename make_unsigned<Unsigned>::type ui_type;
183 typedef typename mpl::if_c<
184 sizeof(Unsigned) <= sizeof(unsigned),
187 sizeof(Unsigned) <= sizeof(unsigned long),
190 sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
196 return find_lsb(static_cast<ui_type>(mask), tag_type());
198 template <class Unsigned>
199 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
201 typedef typename make_unsigned<Unsigned>::type ui_type;
202 typedef typename mpl::if_c<
203 sizeof(Unsigned) <= sizeof(unsigned),
206 sizeof(Unsigned) <= sizeof(unsigned long),
209 sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
215 return find_msb(static_cast<ui_type>(mask), tag_type());
217 #elif defined(BOOST_INTEL)
218 BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
220 return _bit_scan_forward(mask);
222 BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
224 return _bit_scan_reverse(mask);
226 template <class Unsigned>
227 BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
229 typedef typename make_unsigned<Unsigned>::type ui_type;
230 typedef typename mpl::if_c<
231 sizeof(Unsigned) <= sizeof(unsigned),
235 return find_lsb(static_cast<ui_type>(mask), tag_type());
237 template <class Unsigned>
238 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
240 typedef typename make_unsigned<Unsigned>::type ui_type;
241 typedef typename mpl::if_c<
242 sizeof(Unsigned) <= sizeof(unsigned),
246 return find_msb(static_cast<ui_type>(mask), tag_type());
249 template <class Unsigned>
250 BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask)
252 return find_lsb(mask, mpl::int_<0>());
254 template <class Unsigned>
255 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask)
257 return find_msb(mask, mpl::int_<0>());