Skip to content

Commit 999f811

Browse files
committed
fix bit functions to fit cpp20
1 parent 929ab27 commit 999f811

File tree

5 files changed

+73
-54
lines changed

5 files changed

+73
-54
lines changed

atcoder/convolution.hpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ template <class mint,
1818
int g = internal::primitive_root<mint::mod()>,
1919
internal::is_static_modint_t<mint>* = nullptr>
2020
struct fft_info {
21-
static constexpr int rank2 = bsf_constexpr(mint::mod() - 1);
21+
static constexpr int rank2 = countr_zero_constexpr(mint::mod() - 1);
2222
std::array<mint, rank2 + 1> root; // root[i]^(2^i) == 1
2323
std::array<mint, rank2 + 1> iroot; // root[i] * iroot[i] == 1
2424

@@ -60,7 +60,7 @@ struct fft_info {
6060
template <class mint, internal::is_static_modint_t<mint>* = nullptr>
6161
void butterfly(std::vector<mint>& a) {
6262
int n = int(a.size());
63-
int h = internal::ceil_pow2(n);
63+
int h = internal::countr_zero((unsigned int)n);
6464

6565
static const fft_info<mint> info;
6666

@@ -78,7 +78,7 @@ void butterfly(std::vector<mint>& a) {
7878
a[i + offset + p] = l - r;
7979
}
8080
if (s + 1 != (1 << len))
81-
rot *= info.rate2[bsf(~(unsigned int)(s))];
81+
rot *= info.rate2[countr_zero(~(unsigned int)(s))];
8282
}
8383
len++;
8484
} else {
@@ -104,7 +104,7 @@ void butterfly(std::vector<mint>& a) {
104104
a[i + offset + 3 * p] = a0 + na2 + (mod2 - a1na3imag);
105105
}
106106
if (s + 1 != (1 << len))
107-
rot *= info.rate3[bsf(~(unsigned int)(s))];
107+
rot *= info.rate3[countr_zero(~(unsigned int)(s))];
108108
}
109109
len += 2;
110110
}
@@ -114,7 +114,7 @@ void butterfly(std::vector<mint>& a) {
114114
template <class mint, internal::is_static_modint_t<mint>* = nullptr>
115115
void butterfly_inv(std::vector<mint>& a) {
116116
int n = int(a.size());
117-
int h = internal::ceil_pow2(n);
117+
int h = internal::countr_zero((unsigned int)n);
118118

119119
static const fft_info<mint> info;
120120

@@ -135,7 +135,7 @@ void butterfly_inv(std::vector<mint>& a) {
135135
;
136136
}
137137
if (s + 1 != (1 << (len - 1)))
138-
irot *= info.irate2[bsf(~(unsigned int)(s))];
138+
irot *= info.irate2[countr_zero(~(unsigned int)(s))];
139139
}
140140
len--;
141141
} else {
@@ -167,7 +167,7 @@ void butterfly_inv(std::vector<mint>& a) {
167167
irot3.val();
168168
}
169169
if (s + 1 != (1 << (len - 2)))
170-
irot *= info.irate3[bsf(~(unsigned int)(s))];
170+
irot *= info.irate3[countr_zero(~(unsigned int)(s))];
171171
}
172172
len -= 2;
173173
}
@@ -198,7 +198,7 @@ std::vector<mint> convolution_naive(const std::vector<mint>& a,
198198
template <class mint, internal::is_static_modint_t<mint>* = nullptr>
199199
std::vector<mint> convolution_fft(std::vector<mint> a, std::vector<mint> b) {
200200
int n = int(a.size()), m = int(b.size());
201-
int z = 1 << internal::ceil_pow2(n + m - 1);
201+
int z = (int)internal::bit_ceil((unsigned int)(n + m - 1));
202202
assert(mint::mod() % z == 1);
203203
a.resize(z);
204204
internal::butterfly(a);

atcoder/internal_bit.hpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,23 @@
55
#include <intrin.h>
66
#endif
77

8+
#if __cplusplus >= 202002L
9+
#include <bit>
10+
#endif
11+
812
namespace atcoder {
913

1014
namespace internal {
1115

12-
// @param n `0 <= n`
13-
// @return minimum non-negative `x` s.t. `n <= 2**x`
14-
int ceil_pow2(int n) {
15-
int x = 0;
16-
while ((1U << x) < (unsigned int)(n)) x++;
16+
unsigned int bit_ceil(unsigned int n) {
17+
unsigned int x = 1;
18+
while (x < (unsigned int)(n)) x *= 2;
1719
return x;
1820
}
1921

2022
// @param n `1 <= n`
2123
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
22-
constexpr int bsf_constexpr(unsigned int n) {
23-
int x = 0;
24-
while (!(n & (1 << x))) x++;
25-
return x;
26-
}
27-
28-
// @param n `1 <= n`
29-
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
30-
int bsf(unsigned int n) {
24+
int countr_zero(unsigned int n) {
3125
#ifdef _MSC_VER
3226
unsigned long index;
3327
_BitScanForward(&index, n);
@@ -37,6 +31,14 @@ int bsf(unsigned int n) {
3731
#endif
3832
}
3933

34+
// @param n `1 <= n`
35+
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
36+
constexpr int countr_zero_constexpr(unsigned int n) {
37+
int x = 0;
38+
while (!(n & (1 << x))) x++;
39+
return x;
40+
}
41+
4042
} // namespace internal
4143

4244
} // namespace atcoder

atcoder/lazysegtree.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ struct lazy_segtree {
2222
lazy_segtree() : lazy_segtree(0) {}
2323
explicit lazy_segtree(int n) : lazy_segtree(std::vector<S>(n, e())) {}
2424
explicit lazy_segtree(const std::vector<S>& v) : _n(int(v.size())) {
25-
log = internal::ceil_pow2(_n);
26-
size = 1 << log;
25+
size = (int)internal::bit_ceil((unsigned int)(_n));
26+
log = internal::countr_zero((unsigned int)size);
2727
d = std::vector<S>(2 * size, e());
2828
lz = std::vector<F>(size, id());
2929
for (int i = 0; i < _n; i++) d[size + i] = v[i];

atcoder/segtree.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ template <class S, S (*op)(S, S), S (*e)()> struct segtree {
1414
segtree() : segtree(0) {}
1515
explicit segtree(int n) : segtree(std::vector<S>(n, e())) {}
1616
explicit segtree(const std::vector<S>& v) : _n(int(v.size())) {
17-
log = internal::ceil_pow2(_n);
18-
size = 1 << log;
17+
size = (int)internal::bit_ceil((unsigned int)(_n));
18+
log = internal::countr_zero((unsigned int)size);
1919
d = std::vector<S>(2 * size, e());
2020
for (int i = 0; i < _n; i++) d[size + i] = v[i];
2121
for (int i = size - 1; i >= 1; i--) {

test/unittest/bit_test.cpp

Lines changed: 45 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,51 @@ using namespace atcoder;
88
using ll = long long;
99
using ull = unsigned long long;
1010

11-
TEST(BitTest, CeilPow2) {
12-
ASSERT_EQ(0, internal::ceil_pow2(0));
13-
ASSERT_EQ(0, internal::ceil_pow2(1));
14-
ASSERT_EQ(1, internal::ceil_pow2(2));
15-
ASSERT_EQ(2, internal::ceil_pow2(3));
16-
ASSERT_EQ(2, internal::ceil_pow2(4));
17-
ASSERT_EQ(3, internal::ceil_pow2(5));
18-
ASSERT_EQ(3, internal::ceil_pow2(6));
19-
ASSERT_EQ(3, internal::ceil_pow2(7));
20-
ASSERT_EQ(3, internal::ceil_pow2(8));
21-
ASSERT_EQ(4, internal::ceil_pow2(9));
22-
ASSERT_EQ(30, internal::ceil_pow2(1 << 30));
23-
ASSERT_EQ(31, internal::ceil_pow2((1 << 30) + 1));
24-
ASSERT_EQ(31, internal::ceil_pow2(std::numeric_limits<int>::max()));
11+
TEST(BitTest, BitCeil) {
12+
ASSERT_EQ(1, internal::bit_ceil(0U));
13+
ASSERT_EQ(1, internal::bit_ceil(1U));
14+
ASSERT_EQ(2, internal::bit_ceil(2U));
15+
ASSERT_EQ(4, internal::bit_ceil(3U));
16+
ASSERT_EQ(4, internal::bit_ceil(4U));
17+
ASSERT_EQ(8, internal::bit_ceil(5U));
18+
ASSERT_EQ(8, internal::bit_ceil(6U));
19+
ASSERT_EQ(8, internal::bit_ceil(7U));
20+
ASSERT_EQ(8, internal::bit_ceil(8U));
21+
ASSERT_EQ(16, internal::bit_ceil(9U));
22+
ASSERT_EQ(1U<<30, internal::bit_ceil(1U << 30));
23+
ASSERT_EQ(1U<<31, internal::bit_ceil((1U << 30) + 1));
24+
ASSERT_EQ(1U<<31, internal::bit_ceil((1U << 31) - 1));
2525
}
2626

27-
TEST(BitTest, BSF) {
28-
ASSERT_EQ(0, internal::bsf(1));
29-
ASSERT_EQ(1, internal::bsf(2));
30-
ASSERT_EQ(0, internal::bsf(3));
31-
ASSERT_EQ(2, internal::bsf(4));
32-
ASSERT_EQ(0, internal::bsf(5));
33-
ASSERT_EQ(1, internal::bsf(6));
34-
ASSERT_EQ(0, internal::bsf(7));
35-
ASSERT_EQ(3, internal::bsf(8));
36-
ASSERT_EQ(0, internal::bsf(9));
37-
ASSERT_EQ(30, internal::bsf(1U << 30));
38-
ASSERT_EQ(0, internal::bsf((1U << 31) - 1));
39-
ASSERT_EQ(31, internal::bsf(1U << 31));
40-
ASSERT_EQ(0, internal::bsf(std::numeric_limits<unsigned int>::max()));
27+
TEST(BitTest, CountrZero) {
28+
ASSERT_EQ(0, internal::countr_zero(1U));
29+
ASSERT_EQ(1, internal::countr_zero(2U));
30+
ASSERT_EQ(0, internal::countr_zero(3U));
31+
ASSERT_EQ(2, internal::countr_zero(4U));
32+
ASSERT_EQ(0, internal::countr_zero(5U));
33+
ASSERT_EQ(1, internal::countr_zero(6U));
34+
ASSERT_EQ(0, internal::countr_zero(7U));
35+
ASSERT_EQ(3, internal::countr_zero(8U));
36+
ASSERT_EQ(0, internal::countr_zero(9U));
37+
ASSERT_EQ(30, internal::countr_zero(1U << 30));
38+
ASSERT_EQ(0, internal::countr_zero((1U << 31) - 1));
39+
ASSERT_EQ(31, internal::countr_zero(1U << 31));
40+
ASSERT_EQ(0, internal::countr_zero(std::numeric_limits<unsigned int>::max()));
41+
}
42+
43+
TEST(BitTest, CountrZeroConstexpr) {
44+
ASSERT_EQ(0, internal::countr_zero_constexpr(1U));
45+
ASSERT_EQ(1, internal::countr_zero_constexpr(2U));
46+
ASSERT_EQ(0, internal::countr_zero_constexpr(3U));
47+
ASSERT_EQ(2, internal::countr_zero_constexpr(4U));
48+
ASSERT_EQ(0, internal::countr_zero_constexpr(5U));
49+
ASSERT_EQ(1, internal::countr_zero_constexpr(6U));
50+
ASSERT_EQ(0, internal::countr_zero_constexpr(7U));
51+
ASSERT_EQ(3, internal::countr_zero_constexpr(8U));
52+
ASSERT_EQ(0, internal::countr_zero_constexpr(9U));
53+
ASSERT_EQ(30, internal::countr_zero_constexpr(1U << 30));
54+
ASSERT_EQ(0, internal::countr_zero_constexpr((1U << 31) - 1));
55+
ASSERT_EQ(31, internal::countr_zero_constexpr(1U << 31));
56+
ASSERT_EQ(0,
57+
internal::countr_zero_constexpr(std::numeric_limits<unsigned int>::max()));
4158
}

0 commit comments

Comments
 (0)