5#include "cplib/port/bit.hpp"
7#pragma GCC push_options
8#ifndef _CPLIB_NO_FORCE_BMI2_
9#pragma GCC target("abm,bmi,bmi2")
12namespace cplib::impl {
16inline uint64_t low_bits(uint64_t x,
int n) {
17#if __GNUC__ < 10 && (defined(__BMI2__) || !defined(_CPLIB_NO_FORCE_BMI2_))
18 return _bzhi_u64(x, n);
20 return n >= 64 ? x : x & ((1ull << n) - 1);
25inline int popcount_low(uint64_t x,
int n) {
return port::popcount(low_bits(x, n)); }
28inline int prev_set_bit(uint64_t x,
int n) {
return port::bit_width(low_bits(x, n)) - 1; }
31inline int next_set_bit(uint64_t x,
int n) {
return n >= 64 ? 64 : port::countr_zero(x >> n << n); }
34inline uint64_t xor_permute(uint64_t x,
int xor_val) {
35 static constexpr uint64_t checkerboard[6]{0x5555555555555555ull, 0x3333333333333333ull, 0x0f0f0f0f0f0f0f0full,
36 0x00ff00ff00ff00ffull, 0x0000ffff0000ffffull, 0x00000000ffffffffull};
38 for (
int i = 0; i < 6 && xor_val != 0; i++) {
40 uint64_t lo = ret & checkerboard[i];
41 uint64_t hi = ret & ~checkerboard[i];
53#pragma GCC pop_options