Skip to content

Commit 47b2ec4

Browse files
authored
Merge pull request #157 from yosupo06/issue/153
rename internal_bit functions to follow the cpp20 manner
2 parents e1c0e55 + 67a9897 commit 47b2ec4

File tree

5 files changed

+83
-54
lines changed

5 files changed

+83
-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: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,32 @@
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++;
17-
return x;
18-
}
16+
#if __cplusplus >= 202002L
1917

20-
// @param n `1 <= n`
21-
// @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++;
18+
using std::bit_ceil;
19+
20+
#else
21+
22+
// @return same with std::bit::bit_ceil
23+
unsigned int bit_ceil(unsigned int n) {
24+
unsigned int x = 1;
25+
while (x < (unsigned int)(n)) x *= 2;
2526
return x;
2627
}
2728

29+
#endif
30+
2831
// @param n `1 <= n`
29-
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
30-
int bsf(unsigned int n) {
32+
// @return same with std::bit::countr_zero
33+
int countr_zero(unsigned int n) {
3134
#ifdef _MSC_VER
3235
unsigned long index;
3336
_BitScanForward(&index, n);
@@ -37,6 +40,14 @@ int bsf(unsigned int n) {
3740
#endif
3841
}
3942

43+
// @param n `1 <= n`
44+
// @return same with std::bit::countr_zero
45+
constexpr int countr_zero_constexpr(unsigned int n) {
46+
int x = 0;
47+
while (!(n & (1 << x))) x++;
48+
return x;
49+
}
50+
4051
} // namespace internal
4152

4253
} // 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: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,34 +8,52 @@ 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));
25+
ASSERT_EQ(1U << 31, internal::bit_ceil(1U << 31));
2526
}
2627

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

0 commit comments

Comments
 (0)