Mercurial > repos > lsong10 > psiclass
comparison PsiCLASS-1.0.2/BitTable.hpp @ 0:903fc43d6227 draft default tip
Uploaded
author | lsong10 |
---|---|
date | Fri, 26 Mar 2021 16:52:45 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:903fc43d6227 |
---|---|
1 /** | |
2 Use an 64bit integer to represent bit table. | |
3 | |
4 Li Song | |
5 July 24, 2012 | |
6 | |
7 - Modified again from May 27, 2017. | |
8 */ | |
9 | |
10 | |
11 #ifndef _BIT_TABLE_HEADER | |
12 #define _BIT_TABLE_HEADER | |
13 | |
14 #include <stdio.h> | |
15 | |
16 typedef unsigned long long int UINT64 ; | |
17 #define UNIT_SIZE (sizeof( UINT64 ) * 8 ) | |
18 #define UNIT_MASK ((UINT64)63) | |
19 | |
20 class BitTable | |
21 { | |
22 private: | |
23 UINT64 *tab ; // The bits | |
24 int size ; // The size of the table | |
25 int asize ; // The size of the array (size/64). | |
26 public: | |
27 BitTable() // Intialize a bit table. | |
28 { | |
29 //tab = new UINT64[1] ; | |
30 //size = UNIT_SIZE ; | |
31 tab = NULL ; | |
32 size = 0 ; | |
33 } | |
34 | |
35 BitTable( int s ) // Initalize a bit table with size s. | |
36 { | |
37 if ( s == 0 ) | |
38 s = UNIT_SIZE ; | |
39 | |
40 if ( s & UNIT_MASK ) | |
41 { | |
42 asize = s / UNIT_SIZE + 1 ; | |
43 tab = new UINT64[ asize ] ; | |
44 } | |
45 else | |
46 { | |
47 asize = s / UNIT_SIZE ; | |
48 tab = new UINT64[ asize ] ; | |
49 } | |
50 | |
51 size = s ; | |
52 Reset() ; | |
53 } | |
54 | |
55 ~BitTable() | |
56 { | |
57 //printf( "hi %d\n", size ) ; | |
58 //printf( "%s\n", __func__ ) ; | |
59 //if ( tab != NULL ) | |
60 // delete [] tab ; | |
61 //size = -1 ; | |
62 | |
63 // Manually release the memory. | |
64 } | |
65 | |
66 void Init( int s ) // Initialize a bit table with size s. | |
67 { | |
68 if ( tab != NULL ) | |
69 delete [] tab ; | |
70 | |
71 if ( s == 0 ) | |
72 s = UNIT_SIZE ; | |
73 | |
74 if ( s & UNIT_MASK ) | |
75 { | |
76 asize = s / UNIT_SIZE + 1 ; | |
77 tab = new UINT64[ asize ] ; | |
78 } | |
79 else | |
80 { | |
81 asize = s / UNIT_SIZE ; | |
82 tab = new UINT64[ asize ] ; | |
83 } | |
84 | |
85 size = s ; | |
86 Reset() ; | |
87 } | |
88 | |
89 void Release() | |
90 { | |
91 if ( tab != NULL ) | |
92 delete[] tab ; | |
93 tab = NULL ; | |
94 } | |
95 | |
96 void Reset() // Make every value 0. | |
97 { | |
98 for ( int i = 0 ; i < asize ; ++i ) | |
99 tab[i] = 0 ; | |
100 } | |
101 | |
102 void Set( int i ) // Set the ith bit. | |
103 { | |
104 int ind, offset ; | |
105 ind = i / UNIT_SIZE ; | |
106 offset = i & UNIT_MASK ; | |
107 //printf( "%d,%d %d,%d: %llx", 311 / UNIT_SIZE, 311 & UNIT_MASK, 279 / UNIT_SIZE, 279 & UNIT_MASK, tab[ind] ) ; | |
108 tab[ind] |= ( (UINT64)1 << offset ) ; | |
109 //printf( " %llx %d\n", tab[ind], UNIT_SIZE ) ; | |
110 } | |
111 | |
112 void Unset( int i ) // Unset the ith bit | |
113 { | |
114 int ind, offset ; | |
115 ind = i / UNIT_SIZE ; | |
116 offset = i & UNIT_MASK ; | |
117 | |
118 tab[ind] &= ( (UINT64)-1 ^ ( (UINT64)1 << offset ) ) ; | |
119 } | |
120 | |
121 void Flip( int i ) // Flip the ith bit. Same as xor 1. | |
122 { | |
123 int ind, offset ; | |
124 ind = i / UNIT_SIZE ; | |
125 offset = i & UNIT_MASK ; | |
126 | |
127 tab[ind] ^= ( (UINT64)1 << offset ) ; | |
128 } | |
129 | |
130 bool Test( unsigned int i ) const // Test the ith bit. | |
131 { | |
132 if ( i >= (unsigned int)size ) | |
133 return false ; | |
134 | |
135 unsigned int ind, offset ; | |
136 ind = i / UNIT_SIZE ; | |
137 offset = i & UNIT_MASK ; | |
138 | |
139 if ( tab[ind] & ( (UINT64)1 << offset ) ) | |
140 return true ; | |
141 else | |
142 return false ; | |
143 } | |
144 | |
145 void Not() // Not all the bits. | |
146 { | |
147 int i ; | |
148 for ( i = 0 ; i < asize ; ++i ) | |
149 { | |
150 tab[i] = ~tab[i] ; | |
151 } | |
152 } | |
153 | |
154 void And( const BitTable &in ) // Do the "and" on each bits. | |
155 { | |
156 if ( asize != in.asize ) | |
157 return ; | |
158 int i ; | |
159 for ( i = 0 ; i < asize ; ++i ) | |
160 tab[i] &= in.tab[i] ; | |
161 } | |
162 | |
163 void Or( const BitTable &in ) // Do the "or" on each bits. | |
164 { | |
165 if ( asize != in.asize ) | |
166 return ; | |
167 int i ; | |
168 for ( i = 0 ; i < asize ; ++i ) | |
169 tab[i] |= in.tab[i] ; | |
170 } | |
171 | |
172 void Xor( const BitTable &in ) | |
173 { | |
174 if ( asize != in.asize ) | |
175 return ; | |
176 int i ; | |
177 for ( i = 0 ; i < asize ; ++i ) | |
178 tab[i] ^= in.tab[i] ; | |
179 } | |
180 | |
181 // Unset all the bits outside [s,e] | |
182 void MaskRegionOutside( unsigned int s, unsigned int e ) | |
183 { | |
184 int i ; | |
185 // mask out [0, s-1]. | |
186 int ind, offset ; | |
187 if ( s > 0 ) | |
188 { | |
189 ind = (s - 1) / UNIT_SIZE ; | |
190 offset = ( s - 1 ) & UNIT_MASK ; | |
191 for ( i = 0 ; i <= ind - 1 ; ++i ) | |
192 tab[i] = 0 ; | |
193 if ( offset + 1 >= 64 ) | |
194 tab[i] = 0 ; | |
195 else | |
196 tab[i] = ( tab[i] >> (UINT64)( offset + 1 ) ) << (UINT64)( offset + 1 ) ; | |
197 } | |
198 | |
199 // mask out [e+1, size-1] | |
200 if ( e < ( (unsigned int)size - 1 ) ) | |
201 { | |
202 ind = ( e + 1 ) / UNIT_SIZE ; | |
203 offset = ( e + 1 ) & UNIT_MASK ; | |
204 for ( i = ind + 1 ; i < asize ; ++i ) | |
205 tab[i] = 0 ; | |
206 | |
207 if ( UNIT_SIZE - offset >= 64 ) | |
208 tab[ind] = 0 ; | |
209 else | |
210 tab[ind] = ( tab[ind] << (UINT64)( UNIT_SIZE - offset ) ) >> (UINT64)( UNIT_SIZE - offset ) ; | |
211 } | |
212 } | |
213 | |
214 // Given further information about the position of first and last 1's | |
215 void MaskRegionOutsideInRange( int s, int e, int first, int last ) | |
216 { | |
217 int i ; | |
218 int start, to ; | |
219 start = first / UNIT_SIZE ; | |
220 to = last / UNIT_SIZE ; | |
221 // mask out [0, s-1]. | |
222 int ind, offset ; | |
223 if ( s > 0 ) | |
224 { | |
225 ind = (s - 1) / UNIT_SIZE ; | |
226 offset = ( s - 1 ) & UNIT_MASK ; | |
227 for ( i = start ; i <= ind - 1 ; ++i ) | |
228 tab[i] = 0 ; | |
229 if ( offset + 1 >= 64 ) | |
230 tab[i] = 0 ; | |
231 else | |
232 tab[i] = ( tab[i] >> (UINT64)( offset + 1 ) ) << (UINT64)( offset + 1 ) ; | |
233 } | |
234 | |
235 // mask out [e+1, size-1] | |
236 if ( e < size - 1 ) | |
237 { | |
238 ind = ( e + 1 ) / UNIT_SIZE ; | |
239 offset = ( e + 1 ) & UNIT_MASK ; | |
240 for ( i = ind + 1 ; i <= to ; ++i ) | |
241 tab[i] = 0 ; | |
242 | |
243 if ( UNIT_SIZE - offset >= 64 ) | |
244 tab[ind] = 0 ; | |
245 else | |
246 tab[ind] = ( tab[ind] << (UINT64)( UNIT_SIZE - offset ) ) >> (UINT64)( UNIT_SIZE - offset ) ; | |
247 } | |
248 } | |
249 void ShiftOneLeft() | |
250 { | |
251 int i ; | |
252 UINT64 carry = 0 ; | |
253 UINT64 lastTabMask ; | |
254 if ( ( size & UNIT_MASK ) == 0 ) | |
255 lastTabMask = (UINT64)(-1) ; | |
256 else | |
257 lastTabMask = ( 1 << ( size & UNIT_MASK ) ) - 1 ; | |
258 | |
259 for ( i = 0 ; i < asize - 1 ; ++i ) | |
260 { | |
261 UINT64 tmp = ( tab[i] >> ( UNIT_SIZE - 1 ) ) & 1 ; | |
262 tab[i] = ( tab[i] << 1 ) | carry ; | |
263 carry = tmp ; | |
264 } | |
265 tab[i] = ( ( tab[i] << 1 ) | carry ) & lastTabMask ; | |
266 } | |
267 | |
268 void ShiftOneRight() | |
269 { | |
270 int i ; | |
271 UINT64 carry = ( tab[ asize - 1 ] & 1 ) ; | |
272 tab[ asize - 1 ] >>= 1 ; | |
273 for ( i = asize - 2 ; i >= 0 ; --i ) | |
274 { | |
275 UINT64 tmp = ( tab[i] & 1 ) ; | |
276 tab[i] = ( tab[i] >> 1 ) | ( carry << ( UNIT_SIZE - 1 ) ) ; | |
277 carry = tmp ; | |
278 } | |
279 } | |
280 | |
281 bool IsAllZero() | |
282 { | |
283 int i ; | |
284 for ( i = 0 ; i < asize ; ++i ) | |
285 if ( tab[i] != 0 ) | |
286 return false ; | |
287 return true ; | |
288 } | |
289 | |
290 int Count() const // Count how many 1. | |
291 { | |
292 if ( size <= 0 ) | |
293 return 0 ; | |
294 UINT64 k ; | |
295 int i, ret = 0 ; | |
296 for ( i = 0 ; i < asize - 1 ; ++i ) | |
297 { | |
298 k = tab[i] ; | |
299 while ( k ) | |
300 //for ( j = 0 ; j < UNIT_SIZE ; ++j ) | |
301 { | |
302 if ( k & 1 ) | |
303 ++ret ; | |
304 //printf( "### %d %d %d %d\n", ret, asize, size, k ) ; | |
305 k /= 2 ; | |
306 } | |
307 } | |
308 //printf( "(%d) ", ret ) ; | |
309 k = tab[ asize - 1 ] ; | |
310 for ( i = 0 ; i <= (int)( ( size - 1 ) & UNIT_MASK ) ; ++i ) | |
311 { | |
312 if ( k & 1 ) | |
313 ++ret ; | |
314 k /= 2 ; | |
315 } | |
316 //for ( i = 0 ; i < asize ; ++i ) | |
317 // printf( "%llu ", tab[i] ) ; | |
318 //printf( "(%d)\n", ret ) ; | |
319 return ret ; | |
320 } | |
321 | |
322 void GetOnesIndices( std::vector<int> &indices ) | |
323 { | |
324 if ( size <= 0 ) | |
325 return ; | |
326 UINT64 k ; | |
327 int i ; | |
328 int ind = 0 ; | |
329 for ( i = 0 ; i < asize - 1 ; ++i ) | |
330 { | |
331 k = tab[i] ; | |
332 ind = i * UNIT_SIZE ; | |
333 while ( k ) | |
334 //for ( j = 0 ; j < UNIT_SIZE ; ++j ) | |
335 { | |
336 if ( k & 1 ) | |
337 indices.push_back( ind ) ; | |
338 //printf( "### %d %d %d %d\n", ret, asize, size, k ) ; | |
339 k /= 2 ; | |
340 ++ind ; | |
341 } | |
342 } | |
343 //printf( "(%d) ", ret ) ; | |
344 k = tab[ asize - 1 ] ; | |
345 ind = i * UNIT_SIZE ; | |
346 for ( i = 0 ; i <= (int)( ( size - 1 ) & UNIT_MASK ) ; ++i ) | |
347 { | |
348 if ( k & 1ull ) | |
349 indices.push_back( ind ) ; | |
350 k /= 2ull ; | |
351 ++ind ; | |
352 } | |
353 } | |
354 | |
355 bool IsEqual( const BitTable &in ) const// Test wether two bit tables equal. | |
356 { | |
357 int i ; | |
358 if ( in.size != size ) | |
359 return false ; | |
360 //printf( "== %d %d\n", in.size, size ) ; | |
361 //if ( size & UNIT_MASK ) | |
362 // k = size / UNIT_SIZE + 1 ; | |
363 //else | |
364 // k = size / UNIT_SIZE ; | |
365 | |
366 for ( i = 0 ; i < asize ; ++i ) | |
367 if ( tab[i] != in.tab[i] ) | |
368 return false ; | |
369 return true ; | |
370 } | |
371 | |
372 // Return the location of the first difference. -1 if the same. | |
373 int GetFirstDifference( const BitTable &in ) const | |
374 { | |
375 int as = asize < in.asize ? asize : in.asize ; | |
376 //int s = size < in.size ? size : in.size ; | |
377 int i, j ; | |
378 | |
379 for ( i = 0 ; i < as ; ++i ) | |
380 { | |
381 if ( tab[i] != in.tab[i] ) | |
382 { | |
383 UINT64 k1 = tab[i] ; | |
384 UINT64 k2 = in.tab[i] ; | |
385 for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) | |
386 { | |
387 if ( ( k1 & 1 ) != ( k2 & 1 ) ) | |
388 { | |
389 return j + UNIT_SIZE * i ; | |
390 } | |
391 k1 >>= 1 ; | |
392 k2 >>= 1 ; | |
393 } | |
394 } | |
395 } | |
396 | |
397 for ( ; i < asize ; ++i ) | |
398 { | |
399 if ( tab[i] != 0 ) | |
400 { | |
401 UINT64 k = tab[i] ; | |
402 for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) | |
403 { | |
404 if ( k & 1 ) | |
405 return j + UNIT_SIZE * i ; | |
406 k >>= 1 ; | |
407 } | |
408 } | |
409 } | |
410 | |
411 for ( ; i < in.asize ; ++i ) | |
412 { | |
413 if ( in.tab[i] != 0 ) | |
414 { | |
415 UINT64 k = in.tab[i] ; | |
416 for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) | |
417 { | |
418 if ( k & 1 ) | |
419 return j + UNIT_SIZE * i ; | |
420 k >>= 1 ; | |
421 } | |
422 } | |
423 } | |
424 return -1 ; | |
425 } | |
426 | |
427 void Duplicate( BitTable &in ) | |
428 { | |
429 if ( tab != NULL ) | |
430 delete [] tab ; | |
431 int i ; | |
432 size = in.size ; | |
433 asize = in.asize ; | |
434 tab = new UINT64[ asize ] ; | |
435 for ( i = 0 ; i < asize ; ++i ) | |
436 tab[i] = in.tab[i] ; | |
437 } | |
438 | |
439 /*void SetBulk( int ind, uint64_t val ) | |
440 { | |
441 tab[ind] = val ; | |
442 }*/ | |
443 | |
444 void Assign( BitTable &in ) | |
445 { | |
446 int i ; | |
447 for ( i = 0 ; i < asize ; ++i ) | |
448 tab[i] = in.tab[i] ; | |
449 } | |
450 | |
451 void Nullify() | |
452 { | |
453 tab = NULL ; | |
454 } | |
455 | |
456 int GetSize() | |
457 { | |
458 return size ; | |
459 } | |
460 | |
461 void Print() | |
462 { | |
463 int i ; | |
464 for ( i = 0 ; i < asize; ++i ) | |
465 printf( "%llu ", tab[i] ) ; | |
466 printf( "\n" ) ; | |
467 } | |
468 } ; | |
469 | |
470 | |
471 #endif |