📄 bmfunc.h
字号:
nbit &= bm::set_word_mask; bm::word_t* word = dest + nword; if (bitcount == 1) // special case (only 1 bit to set) { *word ^= unsigned(1 << nbit); return; } if (nbit) // starting position is not aligned { unsigned right_margin = nbit + bitcount; // here we checking if we setting bits only in the current // word. Example: 00111000000000000000000000000000 (32 bits word) if (right_margin < 32) { unsigned mask = block_set_table<true>::_right[nbit] & block_set_table<true>::_left[right_margin-1]; *word ^= mask; return; // we are done } else { *word ^= block_set_table<true>::_right[nbit]; bitcount -= 32 - nbit; } ++word; } // now we are word aligned, lets find out how many words we // can now turn ON using loop for ( ;bitcount >= 32; bitcount -= 32) { *word++ ^= 0xffffffff; } if (bitcount) { *word ^= block_set_table<true>::_left[bitcount-1]; }}/*! \brief SUB (AND NOT) GAP block to bitblock. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc*/template<typename T> void gap_sub_to_bitset(unsigned* dest, const T* buf){ register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; if (*buf & 1) // Starts with 1 { sub_bit_block(dest, 0, *pcurr + 1); ++pcurr; } ++pcurr; // now we are in GAP "1" again while (pcurr <= pend) { unsigned bitpos = *(pcurr-1) + 1; BM_ASSERT(*pcurr > *(pcurr-1)); unsigned gap_len = *pcurr - *(pcurr-1); sub_bit_block(dest, bitpos, gap_len); pcurr += 2; }}/*! \brief XOR GAP block to bitblock. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc*/template<typename T> void gap_xor_to_bitset(unsigned* dest, const T* buf){ register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; if (*buf & 1) // Starts with 1 { xor_bit_block(dest, 0, *pcurr + 1); ++pcurr; } ++pcurr; // now we are in GAP "1" again while (pcurr <= pend) { unsigned bitpos = *(pcurr-1) + 1; BM_ASSERT(*pcurr > *(pcurr-1)); unsigned gap_len = *pcurr - *(pcurr-1); xor_bit_block(dest, bitpos, gap_len); pcurr += 2; }}/*! \brief Adds(OR) GAP block to bitblock. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc*/template<typename T> void gap_add_to_bitset(unsigned* dest, const T* buf){ register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; if (*buf & 1) // Starts with 1 { or_bit_block(dest, 0, *pcurr + 1); ++pcurr; } ++pcurr; // now we are in GAP "1" again while (pcurr <= pend) { unsigned bitpos = *(pcurr-1) + 1; BM_ASSERT(*pcurr > *(pcurr-1)); unsigned gap_len = *pcurr - *(pcurr-1); or_bit_block(dest, bitpos, gap_len); pcurr += 2; }}/*! \brief ANDs GAP block to bitblock. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc*/template<typename T> void gap_and_to_bitset(unsigned* dest, const T* buf){ register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; if (! (*buf & 1) ) // Starts with 0 { // Instead of AND we can SUB 0 gaps here sub_bit_block(dest, 0, *pcurr + 1); ++pcurr; } ++pcurr; // now we are in GAP "0" again while (pcurr <= pend) { unsigned bitpos = *(pcurr-1) + 1; BM_ASSERT(*pcurr > *(pcurr-1)); unsigned gap_len = *pcurr - *(pcurr-1); sub_bit_block(dest, bitpos, gap_len); pcurr += 2; }}/*! \brief Compute bitcount of bit block AND masked by GAP block. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc bitfunc*/template<typename T> bm::id_t gap_bitset_and_count(const unsigned* block, const T* buf){ BM_ASSERT(block); register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; bm::id_t count = 0; if (*buf & 1) // Starts with 1 { count += bit_block_calc_count_range(block, 0, *pcurr); ++pcurr; } ++pcurr; // now we are in GAP "1" again while (pcurr <= pend) { bm::id_t c = bit_block_calc_count_range(block, *(pcurr-1)+1, *pcurr); count += c; pcurr += 2; } return count;}/*! \brief Compute bitcount of bit block SUB masked by GAP block. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc bitfunc*/template<typename T> bm::id_t gap_bitset_sub_count(const unsigned* block, const T* buf){ BM_ASSERT(block); register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; bm::id_t count = 0; if (!(*buf & 1)) // Starts with 0 { count += bit_block_calc_count_range(block, 0, *pcurr); ++pcurr; } ++pcurr; // now we are in GAP "0" again for (;pcurr <= pend; pcurr+=2) { count += bit_block_calc_count_range(block, *(pcurr-1)+1, *pcurr); } return count;}/*! \brief Compute bitcount of bit block XOR masked by GAP block. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc bitfunc*/template<typename T> bm::id_t gap_bitset_xor_count(const unsigned* block, const T* buf){ BM_ASSERT(block); register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; unsigned bitval = *buf & 1; register bm::id_t count = bit_block_calc_count_range(block, 0, *pcurr); if (bitval) { count = *pcurr + 1 - count; } for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { T prev = *(pcurr-1)+1; bm::id_t c = bit_block_calc_count_range(block, prev, *pcurr); if (bitval) // 1 gap; means Result = Total_Bits - BitCount; { c = (*pcurr - prev + 1) - c; } count += c; } return count;}/*! \brief Compute bitcount of bit block OR masked by GAP block. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. @ingroup gapfunc bitfunc*/template<typename T> bm::id_t gap_bitset_or_count(const unsigned* block, const T* buf){ BM_ASSERT(block); register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; unsigned bitval = *buf & 1; register bm::id_t count; if (bitval) { count = *pcurr + 1; } else { count = bit_block_calc_count_range(block, 0, *pcurr); } for (bitval^=1, ++pcurr; pcurr <= pend; bitval^=1, ++pcurr) { T prev = *(pcurr-1)+1; bm::id_t c; if (bitval) { c = (*pcurr - prev + 1); } else { c = bit_block_calc_count_range(block, prev, *pcurr); } count += c; } return count;}/*! \brief Bitblock memset operation. \param dst - destination block. \param value - value to set. @ingroup bitfunc*/inline void bit_block_set(bm::word_t* BMRESTRICT dst, bm::word_t value){//#ifdef BMVECTOPT// VECT_SET_BLOCK(dst, dst + bm::set_block_size, value);//#else ::memset(dst, value, bm::set_block_size * sizeof(bm::word_t));//#endif}/*! \brief GAP block to bitblock conversion. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. \param dest_size - length of the destination buffer. @ingroup gapfunc*/template<typename T> void gap_convert_to_bitset(unsigned* dest, const T* buf, unsigned){ bit_block_set(dest, 0);// ::memset(dest, 0, dest_len * sizeof(unsigned)); gap_add_to_bitset(dest, buf);}/*! \brief Smart GAP block to bitblock conversion. Checks if GAP block is ALL-ZERO or ALL-ON. In those cases returns pointer on special static bitblocks. \param dest - bitblock buffer pointer. \param buf - GAP buffer pointer. \param dest_size - length of the destination buffer. \param set_max - max possible bitset length @ingroup gapfunc*/template<typename T> unsigned* gap_convert_to_bitset_smart(unsigned* dest, const T* buf, unsigned dest_size, id_t set_max){ if (buf[1] == set_max - 1) { return (buf[0] & 1) ? FULL_BLOCK_ADDR : 0; } gap_convert_to_bitset(dest, buf, dest_size); return dest;}/*! \brief Calculates sum of all words in GAP block. (For debugging purposes) \note For debugging and testing ONLY. \param buf - GAP buffer pointer. \return Sum of all words. @ingroup gapfunc*/template<typename T> unsigned gap_control_sum(const T* buf){ unsigned end = *buf >> 3; register const T* pcurr = buf; register const T* pend = pcurr + (*pcurr >> 3); ++pcurr; if (*buf & 1) // Starts with 1 { ++pcurr; } ++pcurr; // now we are in GAP "1" again while (pcurr <= pend) { BM_ASSERT(*pcurr > *(pcurr-1)); pcurr += 2; } return buf[end];}/*! \brief Sets all bits to 0 or 1 (GAP) \param buf - GAP buffer pointer. \param set_max - max possible bitset length @ingroup gapfunc*/template<class T> void gap_set_all(T* buf, unsigned set_max, unsigned value){ BM_ASSERT(value == 0 || value == 1); *buf = (*buf & 6u) + (1u << 3) + value; *(++buf) = set_max - 1;}/*! \brief Init gap block so it has block in it (can be whole block) \param buf - GAP buffer pointer. \param from - one block start \param to - one block end \param value - (block value)1 or 0 \param set_max - max possible bitset length @ingroup gapfunc*/template<class T> void gap_init_range_block(T* buf, unsigned from, unsigned to, unsigned value, unsigned set_max){ BM_ASSERT(value == 0 || value == 1); unsigned gap_len; if (from == 0) { if (to == set_max - 1) { gap_set_all(buf, set_max, value); } else { gap_len = 2; buf[1] = to; buf[2] = set_max - 1; buf[0] = (*buf & 6u) + (gap_len << 3) + value; } return; } // from != 0 value = !value; if (to == set_max - 1) { gap_len = 2; buf[1] = from - 1; buf[2] = set_max - 1; } else { gap_len = 3; buf[1] = from - 1; buf[2] = to; buf[3] = set_max - 1; } buf[0] = (*buf & 6u) + (gap_len << 3) + value;}/*! \brief Inverts all bits in the GAP buffer. \param buf - GAP buffer pointer. @ingroup gapfunc*/template<typename T> void gap_invert(T* buf){ *buf ^= 1;}/*! \brief Temporary inverts all bits in the GAP buffer. In this function const-ness of the buffer means nothing. Calling this function again restores the status of the buffer. \param buf - GAP buffer pointer. (Buffer IS changed) @ingroup gapfunc*//*template<typename T> void gap_temp_invert(const T* buf){ T* buftmp = const_cast<T*>(buf); *buftmp ^= 1;}*//*! \brief Checks if GAP block is all-zero. \param buf - GAP buffer pointer. \param set_max - max possible bitset length \returns true if all-zero. @ingroup gapfunc*/template<typename T> bool gap_is_all_zero(const T* buf, unsigned set_max){ return (((*buf & 1)==0) && (*(++buf) == set_max - 1));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -