forked from psanse/BITSCAN
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbbsentinel.h
More file actions
236 lines (191 loc) · 5.96 KB
/
bbsentinel.h
File metadata and controls
236 lines (191 loc) · 5.96 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
/*
* A file from the BITSCAN library, a C++ library for bit set
* optimization. BITSCAN has been used to implement BBMC, a very
* succesful bit-parallel algorithm for exact maximum clique.
* (see license file for references)
*
* Copyright (C)
* Author: Pablo San Segundo
* Intelligent Control Research Group (CSIC-UPM)
*
* Permission to use, modify and distribute this software is
* granted provided that this copyright notice appears in all
* copies, in source code or in binaries. For precise terms
* see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any
* kind, express or implied, and with no claim as to its
* suitability for any purpose.
*
*/
#ifndef __BB_SENTINEL_H__
#define __BB_SENTINEL_H__
#include "bbintrinsic.h"
#include "bbalg.h" //MIN, MAX
using namespace std;
class BBSentinel : public BBIntrin{
friend BBSentinel& AND (const BitBoardN& lhs, const BBSentinel& rhs, BBSentinel& res); //updates sentinels
public:
BBSentinel():m_BBH(EMPTY_ELEM), m_BBL(EMPTY_ELEM){init_sentinels(false);}
explicit BBSentinel(int popsize, bool bits_to_0=true): BBIntrin(popsize, bits_to_0){ init_sentinels(false);}
BBSentinel(const BBSentinel& bbN) : BBIntrin(bbN){ m_BBH=bbN.m_BBH; m_BBL=bbN.m_BBL;}
~BBSentinel(){};
////////////
// setters / getters
void set_sentinel_H(unsigned int i){ m_BBH=i;}
void set_sentinel_L(unsigned int i){ m_BBL=i;}
void set_sentinels(int low, int high);
void init_sentinels(bool update=false); //sets sentinels to maximum scope of current bit string
void clear_sentinels(); //sentinels to EMPTY
int get_sentinel_L(){ return m_BBL;}
int get_sentinel_H(){ return m_BBH;}
/////////////
// basic sentinel
int update_sentinels ();
int update_sentinels (int bbl, int bbh);
int update_sentinels_high ();
int update_sentinels_low ();
void update_sentinels_to_v (int v);
//////////////
// basic overwritten operations (could be extended)
//erase: will not update sentinels
virtual void erase_bit (); //in sentinel range
virtual void erase_bit (int nBit) {BitBoardN::erase_bit(nBit);} //required because of the cast-to-int construction of sentinels (1)
void erase_bit_and_update (int nBit); //erases and updates sentinels
BBSentinel& erase_bit (const BitBoardN&); //(1): required for SEQ coloring
virtual bool is_empty ()const;
virtual bool is_empty (int nBBL, int nBBH) const; //is empty in range
#ifdef POPCOUNT_64
int popcn64 () const;
#endif
////////////////
// operators
BBSentinel& operator= (const BBSentinel&);
BBSentinel& operator&= (const BitBoardN&);
//////////////
// I/O
void print(ostream& o=cout);
/////////////////
// bit scanning operations
virtual int init_scan(scan_types sct);
virtual inline int previous_bit_del(); //**TODO- empty bitstring
virtual inline int next_bit_del ();
virtual inline int next_bit_del (BBSentinel& bbN_del);
virtual inline int next_bit();
virtual inline int next_bit(int& nBB);
protected:
int m_BBH; //explicit storage for sentinel high index
int m_BBL; //explicit storage for sentinel low index
};
#endif
#ifdef POPCOUNT_64
inline int BBSentinel::popcn64() const{
BITBOARD pc=0;
for(int i=m_BBL; i<=m_BBH; i++){
pc+=__popcnt64(m_aBB[i]);
}
return pc;
}
#endif
//specializes the only bitscan function used
inline
int BBSentinel::previous_bit_del(){
//////////////
// BitScan reverse order and distructive
//
// COMMENTS
// 1- update sentinels at the start of loop
unsigned long posInBB;
for(int i=m_BBH; i>=m_BBL; i--){
if(_BitScanReverse64(&posInBB,m_aBB[i])){
m_BBH=i;
m_aBB[i]&=~Tables::mask[posInBB]; //erase before the return
return (posInBB+WMUL(i));
}
}
return EMPTY_ELEM;
}
inline
int BBSentinel::next_bit_del (){
//////////////
// Bitscan distructive between sentinels
//
// COMMENTS
// 1- update sentinels at the start of loop
unsigned long posInBB;
for(int i=m_BBL; i<=m_BBH; i++){
if(_BitScanForward64(&posInBB,m_aBB[i]) ){
m_BBL=i;
m_aBB[i]&=~Tables::mask[posInBB]; //erase before the return
return (posInBB+ WMUL(i));
}
}
return EMPTY_ELEM;
}
inline
int BBSentinel::next_bit_del (BBSentinel& bbN_del){
//////////////
// Bitscan distructive between sentinels
//
// COMMENTS
// 1- update sentinels at the start of loop (experimental, does not use sentinesl of bbN_del)
unsigned long posInBB;
for(int i=m_BBL; i<=m_BBH; i++){
if(_BitScanForward64(&posInBB, m_aBB[i]) ){
m_BBL=i;
m_aBB[i]&=~Tables::mask[posInBB]; //erase before the return
bbN_del.m_aBB[i]&=~Tables::mask[posInBB];
return (posInBB+ WMUL(i));
}
}
return EMPTY_ELEM;
}
inline
int BBSentinel::next_bit(){
////////////////////////////
// last update:31/12/2013
// BitScan non destructive
//
// COMMENTS
// 1- update sentinels, set m_scan.bbi to m_BBL and set m_scan.pos to MASK_LIM at the start of loop
unsigned long posInBB;
if(_BitScanForward64(&posInBB, m_aBB[m_scan.bbi] & Tables::mask_left[m_scan.pos])){
m_scan.pos =posInBB;
return (posInBB + WMUL(m_scan.bbi));
}else{
for(int i=m_scan.bbi+1; i<=m_BBH; i++){
if(_BitScanForward64(&posInBB,m_aBB[i])){
m_scan.bbi=i;
m_scan.pos=posInBB;
return (posInBB+ WMUL(i));
}
}
}
return EMPTY_ELEM;
}
inline
int BBSentinel::next_bit(int& nBB){
////////////////////////////
// last update:31/12/2013
// BitScan non destructive
//
// COMMENTS
// 1- update sentinels, set m_scan.bbi to m_BBL and set m_scan.pos to MASK_LIM at the start of loop
unsigned long posInBB;
//look uo in the last table
if(_BitScanForward64(&posInBB, m_aBB[m_scan.bbi] & Tables::mask_left[m_scan.pos])){
m_scan.pos =posInBB;
nBB=m_scan.bbi;
return (posInBB + WMUL(m_scan.bbi));
}else{ //not found in the last table. look up in the rest
for(int i=(m_scan.bbi+1); i<=m_BBH; i++){
if(_BitScanForward64(&posInBB,m_aBB[i])){
m_scan.bbi=i;
m_scan.pos=posInBB;
nBB=i;
return (posInBB+ WMUL(i));
}
}
}
return EMPTY_ELEM;
}