Mercurial > repos > lsong10 > psiclass
view 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 |
line wrap: on
line source
/** Use an 64bit integer to represent bit table. Li Song July 24, 2012 - Modified again from May 27, 2017. */ #ifndef _BIT_TABLE_HEADER #define _BIT_TABLE_HEADER #include <stdio.h> typedef unsigned long long int UINT64 ; #define UNIT_SIZE (sizeof( UINT64 ) * 8 ) #define UNIT_MASK ((UINT64)63) class BitTable { private: UINT64 *tab ; // The bits int size ; // The size of the table int asize ; // The size of the array (size/64). public: BitTable() // Intialize a bit table. { //tab = new UINT64[1] ; //size = UNIT_SIZE ; tab = NULL ; size = 0 ; } BitTable( int s ) // Initalize a bit table with size s. { if ( s == 0 ) s = UNIT_SIZE ; if ( s & UNIT_MASK ) { asize = s / UNIT_SIZE + 1 ; tab = new UINT64[ asize ] ; } else { asize = s / UNIT_SIZE ; tab = new UINT64[ asize ] ; } size = s ; Reset() ; } ~BitTable() { //printf( "hi %d\n", size ) ; //printf( "%s\n", __func__ ) ; //if ( tab != NULL ) // delete [] tab ; //size = -1 ; // Manually release the memory. } void Init( int s ) // Initialize a bit table with size s. { if ( tab != NULL ) delete [] tab ; if ( s == 0 ) s = UNIT_SIZE ; if ( s & UNIT_MASK ) { asize = s / UNIT_SIZE + 1 ; tab = new UINT64[ asize ] ; } else { asize = s / UNIT_SIZE ; tab = new UINT64[ asize ] ; } size = s ; Reset() ; } void Release() { if ( tab != NULL ) delete[] tab ; tab = NULL ; } void Reset() // Make every value 0. { for ( int i = 0 ; i < asize ; ++i ) tab[i] = 0 ; } void Set( int i ) // Set the ith bit. { int ind, offset ; ind = i / UNIT_SIZE ; offset = i & UNIT_MASK ; //printf( "%d,%d %d,%d: %llx", 311 / UNIT_SIZE, 311 & UNIT_MASK, 279 / UNIT_SIZE, 279 & UNIT_MASK, tab[ind] ) ; tab[ind] |= ( (UINT64)1 << offset ) ; //printf( " %llx %d\n", tab[ind], UNIT_SIZE ) ; } void Unset( int i ) // Unset the ith bit { int ind, offset ; ind = i / UNIT_SIZE ; offset = i & UNIT_MASK ; tab[ind] &= ( (UINT64)-1 ^ ( (UINT64)1 << offset ) ) ; } void Flip( int i ) // Flip the ith bit. Same as xor 1. { int ind, offset ; ind = i / UNIT_SIZE ; offset = i & UNIT_MASK ; tab[ind] ^= ( (UINT64)1 << offset ) ; } bool Test( unsigned int i ) const // Test the ith bit. { if ( i >= (unsigned int)size ) return false ; unsigned int ind, offset ; ind = i / UNIT_SIZE ; offset = i & UNIT_MASK ; if ( tab[ind] & ( (UINT64)1 << offset ) ) return true ; else return false ; } void Not() // Not all the bits. { int i ; for ( i = 0 ; i < asize ; ++i ) { tab[i] = ~tab[i] ; } } void And( const BitTable &in ) // Do the "and" on each bits. { if ( asize != in.asize ) return ; int i ; for ( i = 0 ; i < asize ; ++i ) tab[i] &= in.tab[i] ; } void Or( const BitTable &in ) // Do the "or" on each bits. { if ( asize != in.asize ) return ; int i ; for ( i = 0 ; i < asize ; ++i ) tab[i] |= in.tab[i] ; } void Xor( const BitTable &in ) { if ( asize != in.asize ) return ; int i ; for ( i = 0 ; i < asize ; ++i ) tab[i] ^= in.tab[i] ; } // Unset all the bits outside [s,e] void MaskRegionOutside( unsigned int s, unsigned int e ) { int i ; // mask out [0, s-1]. int ind, offset ; if ( s > 0 ) { ind = (s - 1) / UNIT_SIZE ; offset = ( s - 1 ) & UNIT_MASK ; for ( i = 0 ; i <= ind - 1 ; ++i ) tab[i] = 0 ; if ( offset + 1 >= 64 ) tab[i] = 0 ; else tab[i] = ( tab[i] >> (UINT64)( offset + 1 ) ) << (UINT64)( offset + 1 ) ; } // mask out [e+1, size-1] if ( e < ( (unsigned int)size - 1 ) ) { ind = ( e + 1 ) / UNIT_SIZE ; offset = ( e + 1 ) & UNIT_MASK ; for ( i = ind + 1 ; i < asize ; ++i ) tab[i] = 0 ; if ( UNIT_SIZE - offset >= 64 ) tab[ind] = 0 ; else tab[ind] = ( tab[ind] << (UINT64)( UNIT_SIZE - offset ) ) >> (UINT64)( UNIT_SIZE - offset ) ; } } // Given further information about the position of first and last 1's void MaskRegionOutsideInRange( int s, int e, int first, int last ) { int i ; int start, to ; start = first / UNIT_SIZE ; to = last / UNIT_SIZE ; // mask out [0, s-1]. int ind, offset ; if ( s > 0 ) { ind = (s - 1) / UNIT_SIZE ; offset = ( s - 1 ) & UNIT_MASK ; for ( i = start ; i <= ind - 1 ; ++i ) tab[i] = 0 ; if ( offset + 1 >= 64 ) tab[i] = 0 ; else tab[i] = ( tab[i] >> (UINT64)( offset + 1 ) ) << (UINT64)( offset + 1 ) ; } // mask out [e+1, size-1] if ( e < size - 1 ) { ind = ( e + 1 ) / UNIT_SIZE ; offset = ( e + 1 ) & UNIT_MASK ; for ( i = ind + 1 ; i <= to ; ++i ) tab[i] = 0 ; if ( UNIT_SIZE - offset >= 64 ) tab[ind] = 0 ; else tab[ind] = ( tab[ind] << (UINT64)( UNIT_SIZE - offset ) ) >> (UINT64)( UNIT_SIZE - offset ) ; } } void ShiftOneLeft() { int i ; UINT64 carry = 0 ; UINT64 lastTabMask ; if ( ( size & UNIT_MASK ) == 0 ) lastTabMask = (UINT64)(-1) ; else lastTabMask = ( 1 << ( size & UNIT_MASK ) ) - 1 ; for ( i = 0 ; i < asize - 1 ; ++i ) { UINT64 tmp = ( tab[i] >> ( UNIT_SIZE - 1 ) ) & 1 ; tab[i] = ( tab[i] << 1 ) | carry ; carry = tmp ; } tab[i] = ( ( tab[i] << 1 ) | carry ) & lastTabMask ; } void ShiftOneRight() { int i ; UINT64 carry = ( tab[ asize - 1 ] & 1 ) ; tab[ asize - 1 ] >>= 1 ; for ( i = asize - 2 ; i >= 0 ; --i ) { UINT64 tmp = ( tab[i] & 1 ) ; tab[i] = ( tab[i] >> 1 ) | ( carry << ( UNIT_SIZE - 1 ) ) ; carry = tmp ; } } bool IsAllZero() { int i ; for ( i = 0 ; i < asize ; ++i ) if ( tab[i] != 0 ) return false ; return true ; } int Count() const // Count how many 1. { if ( size <= 0 ) return 0 ; UINT64 k ; int i, ret = 0 ; for ( i = 0 ; i < asize - 1 ; ++i ) { k = tab[i] ; while ( k ) //for ( j = 0 ; j < UNIT_SIZE ; ++j ) { if ( k & 1 ) ++ret ; //printf( "### %d %d %d %d\n", ret, asize, size, k ) ; k /= 2 ; } } //printf( "(%d) ", ret ) ; k = tab[ asize - 1 ] ; for ( i = 0 ; i <= (int)( ( size - 1 ) & UNIT_MASK ) ; ++i ) { if ( k & 1 ) ++ret ; k /= 2 ; } //for ( i = 0 ; i < asize ; ++i ) // printf( "%llu ", tab[i] ) ; //printf( "(%d)\n", ret ) ; return ret ; } void GetOnesIndices( std::vector<int> &indices ) { if ( size <= 0 ) return ; UINT64 k ; int i ; int ind = 0 ; for ( i = 0 ; i < asize - 1 ; ++i ) { k = tab[i] ; ind = i * UNIT_SIZE ; while ( k ) //for ( j = 0 ; j < UNIT_SIZE ; ++j ) { if ( k & 1 ) indices.push_back( ind ) ; //printf( "### %d %d %d %d\n", ret, asize, size, k ) ; k /= 2 ; ++ind ; } } //printf( "(%d) ", ret ) ; k = tab[ asize - 1 ] ; ind = i * UNIT_SIZE ; for ( i = 0 ; i <= (int)( ( size - 1 ) & UNIT_MASK ) ; ++i ) { if ( k & 1ull ) indices.push_back( ind ) ; k /= 2ull ; ++ind ; } } bool IsEqual( const BitTable &in ) const// Test wether two bit tables equal. { int i ; if ( in.size != size ) return false ; //printf( "== %d %d\n", in.size, size ) ; //if ( size & UNIT_MASK ) // k = size / UNIT_SIZE + 1 ; //else // k = size / UNIT_SIZE ; for ( i = 0 ; i < asize ; ++i ) if ( tab[i] != in.tab[i] ) return false ; return true ; } // Return the location of the first difference. -1 if the same. int GetFirstDifference( const BitTable &in ) const { int as = asize < in.asize ? asize : in.asize ; //int s = size < in.size ? size : in.size ; int i, j ; for ( i = 0 ; i < as ; ++i ) { if ( tab[i] != in.tab[i] ) { UINT64 k1 = tab[i] ; UINT64 k2 = in.tab[i] ; for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) { if ( ( k1 & 1 ) != ( k2 & 1 ) ) { return j + UNIT_SIZE * i ; } k1 >>= 1 ; k2 >>= 1 ; } } } for ( ; i < asize ; ++i ) { if ( tab[i] != 0 ) { UINT64 k = tab[i] ; for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) { if ( k & 1 ) return j + UNIT_SIZE * i ; k >>= 1 ; } } } for ( ; i < in.asize ; ++i ) { if ( in.tab[i] != 0 ) { UINT64 k = in.tab[i] ; for ( j = 0 ; j < (int)UNIT_SIZE ; ++j ) { if ( k & 1 ) return j + UNIT_SIZE * i ; k >>= 1 ; } } } return -1 ; } void Duplicate( BitTable &in ) { if ( tab != NULL ) delete [] tab ; int i ; size = in.size ; asize = in.asize ; tab = new UINT64[ asize ] ; for ( i = 0 ; i < asize ; ++i ) tab[i] = in.tab[i] ; } /*void SetBulk( int ind, uint64_t val ) { tab[ind] = val ; }*/ void Assign( BitTable &in ) { int i ; for ( i = 0 ; i < asize ; ++i ) tab[i] = in.tab[i] ; } void Nullify() { tab = NULL ; } int GetSize() { return size ; } void Print() { int i ; for ( i = 0 ; i < asize; ++i ) printf( "%llu ", tab[i] ) ; printf( "\n" ) ; } } ; #endif