1*ccdc9c3eSSadaf Ebrahimi // Copyright 2016 The RE2 Authors. All Rights Reserved.
2*ccdc9c3eSSadaf Ebrahimi // Use of this source code is governed by a BSD-style
3*ccdc9c3eSSadaf Ebrahimi // license that can be found in the LICENSE file.
4*ccdc9c3eSSadaf Ebrahimi
5*ccdc9c3eSSadaf Ebrahimi #ifndef RE2_BITMAP256_H_
6*ccdc9c3eSSadaf Ebrahimi #define RE2_BITMAP256_H_
7*ccdc9c3eSSadaf Ebrahimi
8*ccdc9c3eSSadaf Ebrahimi #ifdef _MSC_VER
9*ccdc9c3eSSadaf Ebrahimi #include <intrin.h>
10*ccdc9c3eSSadaf Ebrahimi #endif
11*ccdc9c3eSSadaf Ebrahimi #include <stdint.h>
12*ccdc9c3eSSadaf Ebrahimi #include <string.h>
13*ccdc9c3eSSadaf Ebrahimi
14*ccdc9c3eSSadaf Ebrahimi #include "util/util.h"
15*ccdc9c3eSSadaf Ebrahimi #include "util/logging.h"
16*ccdc9c3eSSadaf Ebrahimi
17*ccdc9c3eSSadaf Ebrahimi namespace re2 {
18*ccdc9c3eSSadaf Ebrahimi
19*ccdc9c3eSSadaf Ebrahimi class Bitmap256 {
20*ccdc9c3eSSadaf Ebrahimi public:
Bitmap256()21*ccdc9c3eSSadaf Ebrahimi Bitmap256() {
22*ccdc9c3eSSadaf Ebrahimi memset(words_, 0, sizeof words_);
23*ccdc9c3eSSadaf Ebrahimi }
24*ccdc9c3eSSadaf Ebrahimi
25*ccdc9c3eSSadaf Ebrahimi // Tests the bit with index c.
Test(int c)26*ccdc9c3eSSadaf Ebrahimi bool Test(int c) const {
27*ccdc9c3eSSadaf Ebrahimi DCHECK_GE(c, 0);
28*ccdc9c3eSSadaf Ebrahimi DCHECK_LE(c, 255);
29*ccdc9c3eSSadaf Ebrahimi
30*ccdc9c3eSSadaf Ebrahimi return (words_[c / 64] & (1ULL << (c % 64))) != 0;
31*ccdc9c3eSSadaf Ebrahimi }
32*ccdc9c3eSSadaf Ebrahimi
33*ccdc9c3eSSadaf Ebrahimi // Sets the bit with index c.
Set(int c)34*ccdc9c3eSSadaf Ebrahimi void Set(int c) {
35*ccdc9c3eSSadaf Ebrahimi DCHECK_GE(c, 0);
36*ccdc9c3eSSadaf Ebrahimi DCHECK_LE(c, 255);
37*ccdc9c3eSSadaf Ebrahimi
38*ccdc9c3eSSadaf Ebrahimi words_[c / 64] |= (1ULL << (c % 64));
39*ccdc9c3eSSadaf Ebrahimi }
40*ccdc9c3eSSadaf Ebrahimi
41*ccdc9c3eSSadaf Ebrahimi // Finds the next non-zero bit with index >= c.
42*ccdc9c3eSSadaf Ebrahimi // Returns -1 if no such bit exists.
43*ccdc9c3eSSadaf Ebrahimi int FindNextSetBit(int c) const;
44*ccdc9c3eSSadaf Ebrahimi
45*ccdc9c3eSSadaf Ebrahimi private:
46*ccdc9c3eSSadaf Ebrahimi // Finds the least significant non-zero bit in n.
FindLSBSet(uint64_t n)47*ccdc9c3eSSadaf Ebrahimi static int FindLSBSet(uint64_t n) {
48*ccdc9c3eSSadaf Ebrahimi DCHECK_NE(n, 0);
49*ccdc9c3eSSadaf Ebrahimi
50*ccdc9c3eSSadaf Ebrahimi #if defined(__GNUC__)
51*ccdc9c3eSSadaf Ebrahimi return __builtin_ctzll(n);
52*ccdc9c3eSSadaf Ebrahimi #elif defined(_MSC_VER) && defined(_M_X64)
53*ccdc9c3eSSadaf Ebrahimi unsigned long c;
54*ccdc9c3eSSadaf Ebrahimi _BitScanForward64(&c, n);
55*ccdc9c3eSSadaf Ebrahimi return static_cast<int>(c);
56*ccdc9c3eSSadaf Ebrahimi #elif defined(_MSC_VER) && defined(_M_IX86)
57*ccdc9c3eSSadaf Ebrahimi unsigned long c;
58*ccdc9c3eSSadaf Ebrahimi if (static_cast<uint32_t>(n) != 0) {
59*ccdc9c3eSSadaf Ebrahimi _BitScanForward(&c, static_cast<uint32_t>(n));
60*ccdc9c3eSSadaf Ebrahimi return static_cast<int>(c);
61*ccdc9c3eSSadaf Ebrahimi } else {
62*ccdc9c3eSSadaf Ebrahimi _BitScanForward(&c, static_cast<uint32_t>(n >> 32));
63*ccdc9c3eSSadaf Ebrahimi return static_cast<int>(c) + 32;
64*ccdc9c3eSSadaf Ebrahimi }
65*ccdc9c3eSSadaf Ebrahimi #else
66*ccdc9c3eSSadaf Ebrahimi int c = 63;
67*ccdc9c3eSSadaf Ebrahimi for (int shift = 1 << 5; shift != 0; shift >>= 1) {
68*ccdc9c3eSSadaf Ebrahimi uint64_t word = n << shift;
69*ccdc9c3eSSadaf Ebrahimi if (word != 0) {
70*ccdc9c3eSSadaf Ebrahimi n = word;
71*ccdc9c3eSSadaf Ebrahimi c -= shift;
72*ccdc9c3eSSadaf Ebrahimi }
73*ccdc9c3eSSadaf Ebrahimi }
74*ccdc9c3eSSadaf Ebrahimi return c;
75*ccdc9c3eSSadaf Ebrahimi #endif
76*ccdc9c3eSSadaf Ebrahimi }
77*ccdc9c3eSSadaf Ebrahimi
78*ccdc9c3eSSadaf Ebrahimi uint64_t words_[4];
79*ccdc9c3eSSadaf Ebrahimi };
80*ccdc9c3eSSadaf Ebrahimi
FindNextSetBit(int c)81*ccdc9c3eSSadaf Ebrahimi int Bitmap256::FindNextSetBit(int c) const {
82*ccdc9c3eSSadaf Ebrahimi DCHECK_GE(c, 0);
83*ccdc9c3eSSadaf Ebrahimi DCHECK_LE(c, 255);
84*ccdc9c3eSSadaf Ebrahimi
85*ccdc9c3eSSadaf Ebrahimi // Check the word that contains the bit. Mask out any lower bits.
86*ccdc9c3eSSadaf Ebrahimi int i = c / 64;
87*ccdc9c3eSSadaf Ebrahimi uint64_t word = words_[i] & (~0ULL << (c % 64));
88*ccdc9c3eSSadaf Ebrahimi if (word != 0)
89*ccdc9c3eSSadaf Ebrahimi return (i * 64) + FindLSBSet(word);
90*ccdc9c3eSSadaf Ebrahimi
91*ccdc9c3eSSadaf Ebrahimi // Check any following words.
92*ccdc9c3eSSadaf Ebrahimi i++;
93*ccdc9c3eSSadaf Ebrahimi switch (i) {
94*ccdc9c3eSSadaf Ebrahimi case 1:
95*ccdc9c3eSSadaf Ebrahimi if (words_[1] != 0)
96*ccdc9c3eSSadaf Ebrahimi return (1 * 64) + FindLSBSet(words_[1]);
97*ccdc9c3eSSadaf Ebrahimi FALLTHROUGH_INTENDED;
98*ccdc9c3eSSadaf Ebrahimi case 2:
99*ccdc9c3eSSadaf Ebrahimi if (words_[2] != 0)
100*ccdc9c3eSSadaf Ebrahimi return (2 * 64) + FindLSBSet(words_[2]);
101*ccdc9c3eSSadaf Ebrahimi FALLTHROUGH_INTENDED;
102*ccdc9c3eSSadaf Ebrahimi case 3:
103*ccdc9c3eSSadaf Ebrahimi if (words_[3] != 0)
104*ccdc9c3eSSadaf Ebrahimi return (3 * 64) + FindLSBSet(words_[3]);
105*ccdc9c3eSSadaf Ebrahimi FALLTHROUGH_INTENDED;
106*ccdc9c3eSSadaf Ebrahimi default:
107*ccdc9c3eSSadaf Ebrahimi return -1;
108*ccdc9c3eSSadaf Ebrahimi }
109*ccdc9c3eSSadaf Ebrahimi }
110*ccdc9c3eSSadaf Ebrahimi
111*ccdc9c3eSSadaf Ebrahimi } // namespace re2
112*ccdc9c3eSSadaf Ebrahimi
113*ccdc9c3eSSadaf Ebrahimi #endif // RE2_BITMAP256_H_
114