19

次のコードは、GCC の clz/ctz の組み込み関数を呼び出します。他のシステムでは、C バージョンがあります。明らかに、システムに組み込みの clz/ctz 命令 (x86 や ARM など) がある場合、C バージョンは少し最適ではありません。

#ifdef __GNUC__
#define clz(x) __builtin_clz(x)
#define ctz(x) __builtin_ctz(x)
#else
static uint32_t ALWAYS_INLINE popcnt( uint32_t x )
{
    x -= ((x >> 1) & 0x55555555);
    x = (((x >> 2) & 0x33333333) + (x & 0x33333333));
    x = (((x >> 4) + x) & 0x0f0f0f0f);
    x += (x >> 8);
    x += (x >> 16);
    return x & 0x0000003f;
}
static uint32_t ALWAYS_INLINE clz( uint32_t x )
{
    x |= (x >> 1);
    x |= (x >> 2);
    x |= (x >> 4);
    x |= (x >> 8);
    x |= (x >> 16);
    return 32 - popcnt(x);
}
static uint32_t ALWAYS_INLINE ctz( uint32_t x )
{
    return popcnt((x & -x) - 1);
}

#endif

ここで MSVC の適切な ifdef を追加するには、どの関数を呼び出す必要がありますか、どのヘッダーを含める必要がありますか? 私はすでにこのページを見てきましたが、#pragma の目的 (必須ですか?) と、コンパイルの MSVC バージョン要件にどのような制限を課すのか、完全にはわかりません。MSVC を実際に使用していない人として、これらの組み込み関数が他のアーキテクチャで同等の C を持っているかどうか、またはそれらを #define するときに x86/x86_64 を #ifdef する必要があるかどうかもわかりません。

4

6 に答える 6

1

MSVC にこれ用のコンパイラ組み込み関数がある場合は、次の場所にあります。

MSDN のコンパイラ組み込み関数

それ以外の場合は、__asm を使用して記述する必要があります

于 2008-12-10T17:33:21.667 に答える
1
  1. MSVCのint __builtin_ctz (unsigned int x)に相当する関数は、 32 ビット整数の unsigned int _tzcnt_u32 (unsigned int a)であり、末尾のゼロの数を返します。64 ビットの場合はunsigned __int64 _tzcnt_u64 (unsigned __int64 a) 1を使用します。

  2. MSVCのint __builtin_clz (unsigned int x)と同等の関数は、 32 ビット整数の unsigned int _lzcnt_u32 (unsigned int a)で、先行ゼロのカウントを返します。64 ビットの場合はunsigned __int64 _lzcnt_u64 (unsigned __int64 a)を使用2

C++ ヘッダー: immintrin.h

于 2021-05-03T16:35:40.763 に答える
-3

Linux および Windows (x86) でテスト済み:

#ifdef WIN32
    #include <intrin.h>
    static uint32_t __inline __builtin_clz(uint32_t x) {
        unsigned long r = 0;
        _BitScanReverse(&r, x);
        return (31-r);
    }
#endif

uint32_t clz64(const uint64_t x)
{
    uint32_t u32 = (x >> 32);
    uint32_t result = u32 ? __builtin_clz(u32) : 32;
    if (result == 32) {
        u32 = x & 0xFFFFFFFFUL;
        result += (u32 ? __builtin_clz(u32) : 32);
    }
    return result;
}
于 2014-09-13T12:17:42.713 に答える
-4

"_BitScanForward" と "_BitScanReverse" の 2 つの組み込み関数があり、MSVC と同じ目的に適しています。含む 。機能は次のとおりです。

#ifdef _MSC_VER
#include <intrin.h>

static uint32_t __inline ctz( uint32_t x )
{
   int r = 0;
   _BitScanReverse(&r, x);
   return r;
}

static uint32_t __inline clz( uint32_t x )
{
   int r = 0;
   _BitScanForward(&r, x);
   return r;
}
#endif

同等の 64 ビット版「_BitScanForward64」と「_BitScanReverse64」があります。

ここでもっと読む:

MSDN の x86 組み込み関数

于 2011-03-29T06:44:51.343 に答える