mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-19 22:22:00 +00:00
46 lines
1.4 KiB
C++
46 lines
1.4 KiB
C++
|
#include <emmintrin.h>
|
|||
|
|
|||
|
#include <DB/Columns/IColumn.h>
|
|||
|
|
|||
|
|
|||
|
namespace DB
|
|||
|
{
|
|||
|
|
|||
|
size_t countBytesInFilter(const IColumn::Filter & filt)
|
|||
|
{
|
|||
|
size_t count = 0;
|
|||
|
|
|||
|
/** NOTE: По идее, filt должен содержать только нолики и единички.
|
|||
|
* Но, на всякий случай, здесь используется условие > 0 (на знаковые байты).
|
|||
|
* Лучше было бы использовать != 0, то это не позволяет SSE2.
|
|||
|
*/
|
|||
|
|
|||
|
const __m128i zero16 = _mm_set1_epi8(0);
|
|||
|
|
|||
|
const Int8 * pos = reinterpret_cast<const Int8 *>(&filt[0]);
|
|||
|
const Int8 * end = pos + filt.size();
|
|||
|
const Int8 * end64 = pos + filt.size() / 64 * 64;
|
|||
|
|
|||
|
for (; pos < end64; pos += 64)
|
|||
|
count += __builtin_popcount(
|
|||
|
static_cast<UInt64>(_mm_movemask_epi8(_mm_cmpgt_epi8(
|
|||
|
_mm_loadu_si128(reinterpret_cast<const __m128i *>(pos)),
|
|||
|
zero16)))
|
|||
|
| (static_cast<UInt64>(_mm_movemask_epi8(_mm_cmpgt_epi8(
|
|||
|
_mm_loadu_si128(reinterpret_cast<const __m128i *>(pos + 16)),
|
|||
|
zero16))) << 16)
|
|||
|
| (static_cast<UInt64>(_mm_movemask_epi8(_mm_cmpgt_epi8(
|
|||
|
_mm_loadu_si128(reinterpret_cast<const __m128i *>(pos + 32)),
|
|||
|
zero16))) << 32)
|
|||
|
| (static_cast<UInt64>(_mm_movemask_epi8(_mm_cmpgt_epi8(
|
|||
|
_mm_loadu_si128(reinterpret_cast<const __m128i *>(pos + 48)),
|
|||
|
zero16))) << 48));
|
|||
|
|
|||
|
for (; pos < end; ++pos)
|
|||
|
count += *pos > 0;
|
|||
|
|
|||
|
return count;
|
|||
|
}
|
|||
|
|
|||
|
}
|