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 https://www.boost.org/LICENSE_1_0.txt
6 // Comparison operators for cpp_int_backend:
8 #ifndef BOOST_MP_DETAIL_BITSCAN_HPP
9 #define BOOST_MP_DETAIL_BITSCAN_HPP
11 #include <boost/predef/other/endian.h>
12 #include <boost/cstdint.hpp>
14 #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
18 namespace boost { namespace multiprecision { namespace detail {
20 template <class Unsigned>
21 inline BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb_default(Unsigned mask)
32 template <class Unsigned>
33 inline BOOST_MP_CXX14_CONSTEXPR unsigned find_msb_default(Unsigned mask)
44 template <class Unsigned>
45 inline BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb(Unsigned mask, const mpl::int_<0>&)
47 return find_lsb_default(mask);
50 template <class Unsigned>
51 inline BOOST_MP_CXX14_CONSTEXPR unsigned find_msb(Unsigned mask, const mpl::int_<0>&)
53 return find_msb_default(mask);
56 #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64))
58 #pragma intrinsic(_BitScanForward, _BitScanReverse)
60 BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&)
63 _BitScanForward(&result, mask);
67 BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&)
70 _BitScanReverse(&result, mask);
75 #pragma intrinsic(_BitScanForward64, _BitScanReverse64)
77 BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64 mask, const mpl::int_<2>&)
80 _BitScanForward64(&result, mask);
83 template <class Unsigned>
84 BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&)
87 _BitScanReverse64(&result, mask);
92 template <class Unsigned>
93 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb(Unsigned mask)
95 typedef typename make_unsigned<Unsigned>::type ui_type;
96 typedef typename mpl::if_c<
97 sizeof(Unsigned) <= sizeof(unsigned long),
101 sizeof(Unsigned) <= sizeof(__int64),
108 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
109 if (BOOST_MP_IS_CONST_EVALUATED(mask))
111 return find_lsb_default(mask);
115 return find_lsb(static_cast<ui_type>(mask), tag_type());
118 template <class Unsigned>
119 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_msb(Unsigned mask)
121 typedef typename make_unsigned<Unsigned>::type ui_type;
122 typedef typename mpl::if_c<
123 sizeof(Unsigned) <= sizeof(unsigned long),
127 sizeof(Unsigned) <= sizeof(__int64),
134 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
135 if (BOOST_MP_IS_CONST_EVALUATED(mask))
137 return find_msb_default(mask);
141 return find_msb(static_cast<ui_type>(mask), tag_type());
144 #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__))
146 BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
148 return __builtin_ctz(mask);
150 BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&)
152 return __builtin_ctzl(mask);
154 BOOST_FORCEINLINE unsigned find_lsb(boost::ulong_long_type mask, mpl::int_<3> const&)
156 return __builtin_ctzll(mask);
158 BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
160 return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask);
162 BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&)
164 return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask);
166 BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> const&)
168 return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask);
170 #ifdef BOOST_HAS_INT128
172 __extension__ typedef unsigned __int128 uint128_type;
174 BOOST_FORCEINLINE unsigned find_msb(uint128_type mask, mpl::int_<0> const&)
179 boost::uint64_t sv[2];
182 #if BOOST_ENDIAN_LITTLE_BYTE
184 return find_msb(val.sv[1], mpl::int_<3>()) + 64;
185 return find_msb(val.sv[0], mpl::int_<3>());
188 return find_msb(val.sv[0], mpl::int_<3>()) + 64;
189 return find_msb(val.sv[1], mpl::int_<3>());
192 BOOST_FORCEINLINE unsigned find_lsb(uint128_type mask, mpl::int_<0> const&)
197 boost::uint64_t sv[2];
200 #if BOOST_ENDIAN_LITTLE_BYTE
202 return find_lsb(val.sv[1], mpl::int_<3>()) + 64;
203 return find_lsb(val.sv[0], mpl::int_<3>());
206 return find_lsb(val.sv[0], mpl::int_<3>()) + 64;
207 return find_lsb(val.sv[1], mpl::int_<3>());
212 template <class Unsigned>
213 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb(Unsigned mask)
215 typedef typename make_unsigned<Unsigned>::type ui_type;
216 typedef typename mpl::if_c<
217 sizeof(Unsigned) <= sizeof(unsigned),
220 sizeof(Unsigned) <= sizeof(unsigned long),
223 sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
225 mpl::int_<0> >::type>::type>::type tag_type;
226 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
227 if (BOOST_MP_IS_CONST_EVALUATED(mask))
229 return find_lsb_default(mask);
233 return find_lsb(static_cast<ui_type>(mask), tag_type());
235 template <class Unsigned>
236 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_msb(Unsigned mask)
238 typedef typename make_unsigned<Unsigned>::type ui_type;
239 typedef typename mpl::if_c<
240 sizeof(Unsigned) <= sizeof(unsigned),
243 sizeof(Unsigned) <= sizeof(unsigned long),
246 sizeof(Unsigned) <= sizeof(boost::ulong_long_type),
248 mpl::int_<0> >::type>::type>::type tag_type;
249 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
250 if (BOOST_MP_IS_CONST_EVALUATED(mask))
252 return find_msb_default(mask);
256 return find_msb(static_cast<ui_type>(mask), tag_type());
258 #elif defined(BOOST_INTEL)
259 BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&)
261 return _bit_scan_forward(mask);
263 BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&)
265 return _bit_scan_reverse(mask);
267 template <class Unsigned>
268 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb(Unsigned mask)
270 typedef typename make_unsigned<Unsigned>::type ui_type;
271 typedef typename mpl::if_c<
272 sizeof(Unsigned) <= sizeof(unsigned),
274 mpl::int_<0> >::type tag_type;
275 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
276 if (BOOST_MP_IS_CONST_EVALUATED(mask))
278 return find_lsb_default(mask);
282 return find_lsb(static_cast<ui_type>(mask), tag_type());
284 template <class Unsigned>
285 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_msb(Unsigned mask)
287 typedef typename make_unsigned<Unsigned>::type ui_type;
288 typedef typename mpl::if_c<
289 sizeof(Unsigned) <= sizeof(unsigned),
291 mpl::int_<0> >::type tag_type;
292 #ifndef BOOST_MP_NO_CONSTEXPR_DETECTION
293 if (BOOST_MP_IS_CONST_EVALUATED(mask))
295 return find_msb_default(mask);
299 return find_msb(static_cast<ui_type>(mask), tag_type());
302 template <class Unsigned>
303 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_lsb(Unsigned mask)
305 return find_lsb(mask, mpl::int_<0>());
307 template <class Unsigned>
308 BOOST_FORCEINLINE BOOST_MP_CXX14_CONSTEXPR unsigned find_msb(Unsigned mask)
310 return find_msb(mask, mpl::int_<0>());
314 }}} // namespace boost::multiprecision::detail