@@ -185,6 +185,98 @@ uint64_t bitwise_and_dot_product<SIMDLevel::AVX512_SPR>(
185185 return sum;
186186}
187187
188+ template <>
189+ BitwiseAndDotProductResult bitwise_and_dot_product_with_popcount<
190+ SIMDLevel::AVX512_SPR >(
191+ const uint8_t * query,
192+ const uint8_t * data,
193+ size_t size,
194+ size_t qb) {
195+ uint64_t dot_product = 0 ;
196+ uint64_t popcount_sum = 0 ;
197+ size_t offset = 0 ;
198+
199+ if (size_t step = 512 / 8 ; offset + step <= size) {
200+ __m512i dot_512 = _mm512_setzero_si512 ();
201+ __m512i pop_512 = _mm512_setzero_si512 ();
202+ for (; offset + step <= size; offset += step) {
203+ __m512i v_x = _mm512_loadu_si512 (
204+ reinterpret_cast <const __m512i*>(data + offset));
205+ pop_512 = _mm512_add_epi64 (pop_512, popcount_512_vpopcntdq (v_x));
206+ for (size_t j = 0 ; j < qb; j++) {
207+ __m512i v_q = _mm512_loadu_si512 (
208+ reinterpret_cast <const __m512i*>(
209+ query + j * size + offset));
210+ __m512i v_and = _mm512_and_si512 (v_q, v_x);
211+ __m512i v_popcnt = popcount_512_vpopcntdq (v_and);
212+ __m512i v_shifted = _mm512_slli_epi64 (v_popcnt, j);
213+ dot_512 = _mm512_add_epi64 (dot_512, v_shifted);
214+ }
215+ }
216+ dot_product += _mm512_reduce_add_epi64 (dot_512);
217+ popcount_sum += _mm512_reduce_add_epi64 (pop_512);
218+ }
219+
220+ if (size_t step = 256 / 8 ; offset + step <= size) {
221+ __m256i dot_256 = _mm256_setzero_si256 ();
222+ __m256i pop_256 = _mm256_setzero_si256 ();
223+ for (; offset + step <= size; offset += step) {
224+ __m256i v_x = _mm256_loadu_si256 (
225+ reinterpret_cast <const __m256i*>(data + offset));
226+ pop_256 = _mm256_add_epi64 (pop_256, popcount_256_vpopcntdq (v_x));
227+ for (size_t j = 0 ; j < qb; j++) {
228+ __m256i v_q = _mm256_loadu_si256 (
229+ reinterpret_cast <const __m256i*>(
230+ query + j * size + offset));
231+ __m256i v_and = _mm256_and_si256 (v_q, v_x);
232+ __m256i v_popcnt = popcount_256_vpopcntdq (v_and);
233+ __m256i v_shifted = _mm256_slli_epi64 (v_popcnt, j);
234+ dot_256 = _mm256_add_epi64 (dot_256, v_shifted);
235+ }
236+ }
237+ dot_product += reduce_add_256 (dot_256);
238+ popcount_sum += reduce_add_256 (pop_256);
239+ }
240+
241+ __m128i dot_128 = _mm_setzero_si128 ();
242+ __m128i pop_128 = _mm_setzero_si128 ();
243+ for (size_t step = 128 / 8 ; offset + step <= size; offset += step) {
244+ __m128i v_x = _mm_loadu_si128 (
245+ reinterpret_cast <const __m128i*>(data + offset));
246+ pop_128 = _mm_add_epi64 (pop_128, popcount_128_vpopcntdq (v_x));
247+ for (size_t j = 0 ; j < qb; j++) {
248+ __m128i v_q = _mm_loadu_si128 (
249+ reinterpret_cast <const __m128i*>(
250+ query + j * size + offset));
251+ __m128i v_and = _mm_and_si128 (v_q, v_x);
252+ __m128i v_popcnt = popcount_128_vpopcntdq (v_and);
253+ __m128i v_shifted = _mm_slli_epi64 (v_popcnt, j);
254+ dot_128 = _mm_add_epi64 (dot_128, v_shifted);
255+ }
256+ }
257+ dot_product += reduce_add_128 (dot_128);
258+ popcount_sum += reduce_add_128 (pop_128);
259+
260+ for (size_t step = 64 / 8 ; offset + step <= size; offset += step) {
261+ const auto yv = *reinterpret_cast <const uint64_t *>(data + offset);
262+ popcount_sum += popcount64 (yv);
263+ for (size_t j = 0 ; j < qb; j++) {
264+ const auto qv = *reinterpret_cast <const uint64_t *>(
265+ query + j * size + offset);
266+ dot_product += static_cast <uint64_t >(popcount64 (qv & yv)) << j;
267+ }
268+ }
269+ for (; offset < size; ++offset) {
270+ const auto yv = *(data + offset);
271+ popcount_sum += popcount32 (yv);
272+ for (size_t j = 0 ; j < qb; j++) {
273+ const auto qv = *(query + j * size + offset);
274+ dot_product += static_cast <uint64_t >(popcount32 (qv & yv)) << j;
275+ }
276+ }
277+ return {dot_product, popcount_sum};
278+ }
279+
188280template <>
189281uint64_t bitwise_xor_dot_product<SIMDLevel::AVX512_SPR >(
190282 const uint8_t * query,
0 commit comments