//////////////////////////////////////////////////////////////////////// /// \class RAT::DS::BitMask /// /// \brief A dynamic bit mask. /// /// \author Phil G Jones /// /// REVISION HISTORY:\n /// 2014-04-04: P G Jones - New file /// /// \details A dynamic bit mask made of multiple (by default 1) ULong64_t /// types. Each ULong64_t is referred to as an element. Any operation on /// the BitMask involving another BitMask (comparisons/bit operations) /// includes padding the BitMask with 0x0 such that the number of elements /// is equivalent in both. In practice instances of this object can be /// used as one would with a integer bit mask. /// //////////////////////////////////////////////////////////////////////// #ifndef __RAT_DS_BitMask__ #define __RAT_DS_BitMask__ #include #include #include #include #include #include namespace RAT { namespace DS { class BitMask : public TObject { public: /// Generic constructor, start with 1 element in the flags BitMask() : TObject() { flags.resize( 1, 0 ); } /// Create a BitMask using a ULong64_t value i.e. a int inline BitMask( const ULong64_t value ); /// Set a bit in the mask at index to value /// /// @param[in] index of the bit to set /// @param[in] value to set it to inline void Set( size_t index, const Bool_t value = true ); /// Get the value of the bit at index in the mask /// /// @param[in] index of the bit to get /// @return the value of the bit inline Bool_t Get( size_t index ) const; /// Get the values of the bits at index to index + length /// /// The result is shifted such that the index bit is at 0 in the result /// /// @param[in] index of the bits to return /// @param[in] length of the bits after index to return /// @return the bits from index to index + length shifted s.t. index is at 0 in the result inline ULong64_t GetBits( const size_t index, const size_t length ) const; /// Get a ULong64_t from this BitMask /// /// If the startIndex is such that this BitMask has no data in the bits /// [index, index+64) then 0x0 is returned. Additionally any bits not defined /// in this mask will be set to false/0. /// /// @param[in] startIndex of the 64 bit word i.e. a value of 1 asks to return bits [64, 127] /// @return a ULong64_t with filled with the relevant set bits in this mask inline ULong64_t GetULong64_t( const size_t startIndex ) const; /// Convert to a string for easy output /// /// @return a string representation in hex inline std::string ToString() const; /// one's complement operator, switches every 1 bit to a 0 bit and vice versa /// /// @return reference to this inline BitMask& operator~(); /// Bitwise AND operator /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to AND this with /// @return the result of this & rhs inline BitMask operator&( const BitMask& rhs ) const; /// Bitwise AND operator, store result in this /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to AND this with /// @return reference to this inline BitMask& operator&=( const BitMask& rhs ); /// Bitwise OR operator /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to OR this with /// @return the result of this | rhs inline BitMask operator|( const BitMask& rhs ) const; /// Bitwise OR operator, store result in this /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to OR this with /// @return reference to this inline BitMask& operator|=( const BitMask& rhs ); /// Bitwise XOR/EOR operator /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to XOR/EOR this with /// @return the result of this ^ rhs inline BitMask operator^( const BitMask& rhs ) const; /// Bitwise XOR/EOR operator, store result in this /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to XOR/EOR this with /// @return reference to this inline BitMask& operator^=( const BitMask& rhs ); /// Comparison operator /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to compare this against /// @return true if this and rhs have the same bits set inline Bool_t operator==( const BitMask& rhs ) const; /// Not comparison operator /// /// this or rhs are padded with 0x0 elements till the number of elements match /// /// @param[in] rhs to compare this against /// @return true if this and rhs do not have the same bits set inline Bool_t operator!=( const BitMask& rhs ) const; /// Cast to bool operator /// /// @return true if any element is not equal to 0x0, i.e. if any bit is set inline operator Bool_t() const; // This ROOT macro adds dictionary methods to this class. // The number should be incremented whenever this class's members are changed. // It assumes this class has no virtual methods, use ClassDef if change this. ClassDefNV( BitMask, 1 ); protected: std::vector flags; }; BitMask::BitMask( const ULong64_t value ) : TObject() { flags.resize( 1, 0 ); flags[0] = value; } inline void BitMask::Set( size_t index, const Bool_t value ) { const size_t element = index / ( sizeof( ULong64_t ) * CHAR_BIT ); if( index >= flags.size() * sizeof( ULong64_t ) * CHAR_BIT ) flags.resize( element + 1, 0 ); index -= element * sizeof( ULong64_t ) * CHAR_BIT; // Index is now the bit in ULong64_t element if( value ) flags[element] |= ( (ULong64_t)0x1 << index ); else flags[element] &= ~( (ULong64_t)0x1 << index ); } inline Bool_t BitMask::Get( size_t index ) const { const size_t element = index / ( sizeof( ULong64_t ) * CHAR_BIT ); if( index >= flags.size() * sizeof( ULong64_t ) * CHAR_BIT ) return false; index -= element * sizeof( ULong64_t ) * CHAR_BIT;// Index is now the bit in ULong64_t element return static_cast( flags[element] & ( (ULong64_t)0x1 << index ) ); } inline ULong64_t BitMask::GetBits( const size_t start, const size_t length ) const { ULong64_t result = 0; for( size_t index = start; index < start + length; index++ ) { if( Get( index ) ) result |= ( (ULong64_t)0x1 << ( index - start ) ); } return result; } inline ULong64_t BitMask::GetULong64_t( const size_t startIndex ) const { ULong64_t result = 0x0; for( size_t index = 0; index < sizeof( ULong64_t ) * CHAR_BIT; index++ ) if( Get( index + startIndex * sizeof( ULong64_t ) * CHAR_BIT ) ) result |= ((ULong64_t)0x1 << index); return result; } inline std::string BitMask::ToString() const { std::stringstream result; result << "0x" << std::hex; for( std::vector::const_reverse_iterator iTer = flags.rbegin(); iTer != flags.rend(); iTer++ ) result << *iTer; return result.str(); } inline BitMask & BitMask::operator~() { for( size_t element = 0; element < flags.size(); element++ ) flags[element] = ~flags[element]; return *this; } inline BitMask BitMask::operator&( const BitMask& rhs ) const { BitMask result; for( size_t element = 0; element < std::max( flags.size(), rhs.flags.size() ); element++ ) { const ULong64_t left = element < flags.size() ? flags.at( element ) : 0x0; const ULong64_t right = element < rhs.flags.size() ? rhs.flags.at( element ) : 0x0; result.flags.push_back( left & right ); } return result; } inline BitMask& BitMask::operator&=( const BitMask& rhs ) { *this = *this & rhs; return *this; } inline BitMask BitMask::operator|( const BitMask& rhs ) const { BitMask result; for( size_t element = 0; element < std::max( flags.size(), rhs.flags.size() ); element++ ) { const ULong64_t left = element < flags.size() ? flags.at( element ) : 0x0; const ULong64_t right = element < rhs.flags.size() ? rhs.flags.at( element ) : 0x0; result.flags.push_back( left | right ); } return result; } inline BitMask& BitMask::operator|=( const BitMask& rhs ) { *this = *this | rhs; return *this; } inline BitMask BitMask::operator^( const BitMask& rhs ) const { BitMask result; for( size_t element = 0; element < std::max( flags.size(), rhs.flags.size() ); element++ ) { const ULong64_t left = element < flags.size() ? flags.at( element ) : 0x0; const ULong64_t right = element < rhs.flags.size() ? rhs.flags.at( element ) : 0x0; result.flags.push_back( left ^ right ); } return result; } inline BitMask& BitMask::operator^=( const BitMask& rhs ) { *this = *this ^ rhs; return *this; } inline Bool_t BitMask::operator==( const BitMask& rhs ) const { for( size_t element = 0; element < std::max( flags.size(), rhs.flags.size() ); element++ ) { const ULong64_t left = element < flags.size() ? flags.at( element ) : 0x0; const ULong64_t right = element < rhs.flags.size() ? rhs.flags.at( element ) : 0x0; if( left != right ) return false; } return true; } inline Bool_t BitMask::operator!=( const BitMask& rhs ) const { return !(*this == rhs); } inline BitMask::operator Bool_t() const { for( size_t element = 0; element < flags.size(); element++ ) if( flags.at( element ) != 0 ) return true; return false; } } // namespace DS } // namespace RAT #endif