230 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			230 lines
		
	
	
		
			6.3 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | /////////////////////////////////////////////////////////////// | ||
|  | //  Copyright 2013 John Maddock. Distributed under the Boost | ||
|  | //  Software License, Version 1.0. (See accompanying file | ||
|  | //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_ | ||
|  | // | ||
|  | // Comparison operators for cpp_int_backend: | ||
|  | // | ||
|  | #ifndef BOOST_MP_DETAIL_BITSCAN_HPP | ||
|  | #define BOOST_MP_DETAIL_BITSCAN_HPP | ||
|  | 
 | ||
|  | #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64)) | ||
|  | #include <intrin.h> | ||
|  | #endif | ||
|  | 
 | ||
|  | namespace boost{ namespace multiprecision{ namespace detail{ | ||
|  | 
 | ||
|  | template <class Unsigned> | ||
|  | inline unsigned find_lsb(Unsigned mask, const mpl::int_<0>&) | ||
|  | { | ||
|  |    unsigned result = 0; | ||
|  |    while(!(mask & 1u)) | ||
|  |    { | ||
|  |       mask >>= 1; | ||
|  |       ++result; | ||
|  |    } | ||
|  |    return result; | ||
|  | } | ||
|  | 
 | ||
|  | template <class Unsigned> | ||
|  | inline unsigned find_msb(Unsigned mask, const mpl::int_<0>&) | ||
|  | { | ||
|  |    unsigned index = 0; | ||
|  |    while(mask) | ||
|  |    { | ||
|  |       ++index; | ||
|  |       mask >>= 1; | ||
|  |    } | ||
|  |    return --index; | ||
|  | } | ||
|  | 
 | ||
|  | #if (defined(BOOST_MSVC) || (defined(__clang__) && defined(__c2__)) || (defined(BOOST_INTEL) && defined(_MSC_VER))) && (defined(_M_IX86) || defined(_M_X64)) | ||
|  | 
 | ||
|  | #pragma intrinsic(_BitScanForward,_BitScanReverse) | ||
|  | 
 | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, const mpl::int_<1>&) | ||
|  | { | ||
|  |    unsigned long result; | ||
|  |    _BitScanForward(&result, mask); | ||
|  |    return result; | ||
|  | } | ||
|  | 
 | ||
|  | BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, const mpl::int_<1>&) | ||
|  | { | ||
|  |    unsigned long result; | ||
|  |    _BitScanReverse(&result, mask); | ||
|  |    return result; | ||
|  | } | ||
|  | #ifdef _M_X64 | ||
|  | 
 | ||
|  | #pragma intrinsic(_BitScanForward64,_BitScanReverse64) | ||
|  | 
 | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(unsigned __int64 mask, const mpl::int_<2>&) | ||
|  | { | ||
|  |    unsigned long result; | ||
|  |    _BitScanForward64(&result, mask); | ||
|  |    return result; | ||
|  | } | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_msb(Unsigned mask, const mpl::int_<2>&) | ||
|  | { | ||
|  |    unsigned long result; | ||
|  |    _BitScanReverse64(&result, mask); | ||
|  |    return result; | ||
|  | } | ||
|  | #endif | ||
|  | 
 | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned long), | ||
|  |       mpl::int_<1>, | ||
|  | #ifdef _M_X64 | ||
|  |       typename mpl::if_c< | ||
|  |          sizeof(Unsigned) <= sizeof(__int64), | ||
|  |          mpl::int_<2>, | ||
|  |          mpl::int_<0> | ||
|  |       >::type | ||
|  | #else | ||
|  |       mpl::int_<0> | ||
|  | #endif | ||
|  |    >::type tag_type; | ||
|  |    return find_lsb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_msb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned long), | ||
|  |       mpl::int_<1>, | ||
|  | #ifdef _M_X64 | ||
|  |       typename mpl::if_c< | ||
|  |          sizeof(Unsigned) <= sizeof(__int64), | ||
|  |          mpl::int_<2>, | ||
|  |          mpl::int_<0> | ||
|  |       >::type | ||
|  | #else | ||
|  |       mpl::int_<0> | ||
|  | #endif | ||
|  |    >::type tag_type; | ||
|  |    return find_msb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | 
 | ||
|  | #elif defined(BOOST_GCC) || defined(__clang__) || (defined(BOOST_INTEL) && defined(__GNUC__)) | ||
|  | 
 | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&) | ||
|  | { | ||
|  |    return __builtin_ctz(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(unsigned long mask, mpl::int_<2> const&) | ||
|  | { | ||
|  |    return __builtin_ctzl(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(boost::ulong_long_type mask, mpl::int_<3> const&) | ||
|  | { | ||
|  |    return __builtin_ctzll(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&) | ||
|  | { | ||
|  |    return sizeof(unsigned) * CHAR_BIT - 1 - __builtin_clz(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_msb(unsigned long mask, mpl::int_<2> const&) | ||
|  | { | ||
|  |    return sizeof(unsigned long) * CHAR_BIT - 1 - __builtin_clzl(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_msb(boost::ulong_long_type mask, mpl::int_<3> const&) | ||
|  | { | ||
|  |    return sizeof(boost::ulong_long_type) * CHAR_BIT - 1 - __builtin_clzll(mask); | ||
|  | } | ||
|  | 
 | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned), | ||
|  |       mpl::int_<1>, | ||
|  |       typename mpl::if_c< | ||
|  |          sizeof(Unsigned) <= sizeof(unsigned long), | ||
|  |          mpl::int_<2>, | ||
|  |          typename mpl::if_c< | ||
|  |             sizeof(Unsigned) <= sizeof(boost::ulong_long_type), | ||
|  |             mpl::int_<3>, | ||
|  |             mpl::int_<0> | ||
|  |          >::type | ||
|  |       >::type | ||
|  |    >::type tag_type; | ||
|  |    return find_lsb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_msb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned), | ||
|  |       mpl::int_<1>, | ||
|  |       typename mpl::if_c< | ||
|  |          sizeof(Unsigned) <= sizeof(unsigned long), | ||
|  |          mpl::int_<2>, | ||
|  |          typename mpl::if_c< | ||
|  |             sizeof(Unsigned) <= sizeof(boost::ulong_long_type), | ||
|  |             mpl::int_<3>, | ||
|  |             mpl::int_<0> | ||
|  |          >::type | ||
|  |       >::type | ||
|  |    >::type tag_type; | ||
|  |    return find_msb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | #elif defined(BOOST_INTEL) | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(unsigned mask, mpl::int_<1> const&) | ||
|  | { | ||
|  |    return _bit_scan_forward(mask); | ||
|  | } | ||
|  | BOOST_FORCEINLINE unsigned find_msb(unsigned mask, mpl::int_<1> const&) | ||
|  | { | ||
|  |    return _bit_scan_reverse(mask); | ||
|  | } | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned), | ||
|  |       mpl::int_<1>, | ||
|  |       mpl::int_<0> | ||
|  |    >::type tag_type; | ||
|  |    return find_lsb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_msb(Unsigned mask) | ||
|  | { | ||
|  |    typedef typename make_unsigned<Unsigned>::type ui_type; | ||
|  |    typedef typename mpl::if_c< | ||
|  |       sizeof(Unsigned) <= sizeof(unsigned), | ||
|  |       mpl::int_<1>, | ||
|  |       mpl::int_<0> | ||
|  |    >::type tag_type; | ||
|  |    return find_msb(static_cast<ui_type>(mask), tag_type()); | ||
|  | } | ||
|  | #else | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_lsb(Unsigned mask) | ||
|  | { | ||
|  |    return find_lsb(mask, mpl::int_<0>()); | ||
|  | } | ||
|  | template <class Unsigned> | ||
|  | BOOST_FORCEINLINE unsigned find_msb(Unsigned mask) | ||
|  | { | ||
|  |    return find_msb(mask, mpl::int_<0>()); | ||
|  | } | ||
|  | #endif | ||
|  | 
 | ||
|  | }}} | ||
|  | 
 | ||
|  | #endif | ||
|  | 
 |