MSVC эквивалентно __builtin_popcount?
Что эквивалентно __builtin_popcount
как найти в GCC и Clang, для MSVC-10?
3 ответа
Используя предоставленные комментарии:
__popcnt
доступны через<intrin.h>
_mm_popcnt_u64
с SSE4 и<nmmintrin.h>
С помощью этого фрагмента кода вы получаете встроенный GCC при сборке с MSVC:
#ifdef _MSC_VER
# include <intrin.h>
# define __builtin_popcount __popcnt
#endif
(Работает с Visual Studio 2008).
__popcount
Упомянутый выше intrinsic не работает на ARM или даже на всех процессорах x86 (для этого требуется набор команд ABM). Вы не должны использовать это непосредственно; вместо этого, если вы используете x86/amd64, вы должны использовать __cpuid
встроенный, чтобы определить во время выполнения, поддерживает ли процессор popcnt
,
Имейте в виду, что вы, вероятно, не хотите выдавать cpuid
для каждого popcnt
вызов; Вы хотите сохранить результат где-нибудь. Если ваш код всегда будет однопоточным, это тривиально, но если вам нужно быть поточно-ориентированным, вам придется использовать что-то вроде одноразовой инициализации. Это будет работать только с Windows ≥ Vista; если вам нужно работать со старыми версиями, вам нужно будет свернуть свою собственную (или использовать что-то от стороннего производителя).
Для машин без ABM (или если обнаружение во время выполнения не стоит), есть несколько портативных версий в Bit 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
Если вам нужна встроенная версия, вы можете использовать встроенный модуль в portable-snippets (полное описание: portable-snippets - один из моих проектов), который должен работать практически везде.