MSVC эквивалентен __builtin_popcount?

Что эквивалентно __builtin_popcount, как указано в GCC и Clang, для MSVC-10?

Ответ 1

Используя предоставленные комментарии:

Ответ 2

С помощью этого фрагмента кода вы получаете встроенный GCC при создании с помощью MSVC:

#ifdef _MSC_VER
#  include <intrin.h>
#  define __builtin_popcount __popcnt
#endif

(Работает с Visual Studio 2008).

Ответ 3

Внутренний уровень __popcount, упомянутый выше, не работает на ARM или даже на всех процессорах x86 (для этого требуется ABM). Вы не должны использовать его напрямую; вместо этого, если вы используете x86/amd64, вы должны использовать встроенный __cpuid для определения во время выполнения, если процессор поддерживает popcnt.

Имейте в виду, что вы, вероятно, не хотите выпускать cpuid для каждого вызова popcnt; вы захотите сохранить результат где-нибудь. Если ваш код всегда будет однопоточным, это тривиально, но если вам нужно быть потокобезопасным, вам придется использовать что-то вроде One Инициализация времени. Тем не менее, это будет работать только с Windows ≥ Vista; если вам нужно работать со старыми версиями, вам нужно будет свернуть свое (или использовать что-то со стороннего).

Для машин без ABM (или если обнаружение времени выполнения не стоит), есть несколько переносимых версий на Бит Twiddling Hacks (смотрите для "Набор счетных бит" ). Моя любимая версия работает для любого типа T до 128 бит:

v = v - ((v >> 1) & (T)~(T)0/3);                           // temp
v = (v & (T)~(T)0/15*3) + ((v >> 2) & (T)~(T)0/15*3);      // temp
v = (v + (v >> 4)) & (T)~(T)0/255*15;                      // temp
c = (T)(v * ((T)~(T)0/255)) >> (sizeof(T) - 1) * CHAR_BIT; // count

Если вы хотите использовать вставную версию, вы можете использовать встроенный модуль в портативных фрагментах (полное раскрытие: переносные фрагменты - это один моих проектов), которые должны работать практически везде.