📄 bmfunc.h
字号:
register const T* pend = pcurr + (*pcurr >> 3); register unsigned bits_counter = 0; ++pcurr; if (*buf & 1) { bits_counter += *pcurr + 1; ++pcurr; } ++pcurr; // set GAP to 1 while (pcurr <= pend) { bits_counter += *pcurr - *(pcurr-1); pcurr += 2; // jump to the next positive GAP } return bits_counter;}/*! \brief Counts 1 bits in GAP buffer in the closed [left, right] diapason. \param buf - GAP buffer pointer. \param left - leftmost bit index to start from \param right- rightmost bit index \return Number of non-zero bits.*/template<typename T>unsigned gap_bit_count_range(const T* buf, T left, T right){ BM_ASSERT(left <= right); const T* pcurr = buf; const T* pend = pcurr + (*pcurr >> 3); unsigned bits_counter = 0; unsigned is_set; unsigned start_pos = gap_bfind(buf, left, &is_set); pcurr = buf + start_pos; if (right <= *pcurr) // we are in the target block right now { if (is_set) bits_counter = (right - left + 1); return bits_counter; } if (is_set) bits_counter += *pcurr - left + 1; unsigned prev_gap = *pcurr++; is_set ^= 1; while (right > *pcurr) { if (is_set) bits_counter += *pcurr - prev_gap; if (pcurr == pend) return bits_counter; prev_gap = *pcurr++; is_set ^= 1; } if (is_set) bits_counter += right - prev_gap; return bits_counter;}/*! \brief Lexicographical comparison of GAP buffers. \param buf1 - First GAP buffer pointer. \param buf2 - Second GAP buffer pointer. \return <0 - less, =0 - equal, >0 - greater. @ingroup gapfunc*/template<typename T> int gapcmp(const T* buf1, const T* buf2){ const T* pcurr1 = buf1; const T* pend1 = pcurr1 + (*pcurr1 >> 3); unsigned bitval1 = *buf1 & 1; ++pcurr1; const T* pcurr2 = buf2; unsigned bitval2 = *buf2 & 1; ++pcurr2; while (pcurr1 <= pend1) { if (*pcurr1 == *pcurr2) { if (bitval1 != bitval2) { return (bitval1) ? 1 : -1; } } else { if (bitval1 == bitval2) { if (bitval1) { return (*pcurr1 < *pcurr2) ? -1 : 1; } else { return (*pcurr1 < *pcurr2) ? 1 : -1; } } else { return (bitval1) ? 1 : -1; } } ++pcurr1; ++pcurr2; bitval1 ^= 1; bitval2 ^= 1; } return 0;}/*! \brief Abstract operation for GAP buffers. Receives functor F as a template argument \param dest - destination memory buffer. \param vect1 - operand 1 GAP encoded buffer. \param vect1_mask - XOR mask for starting bitflag for vector1 can be 0 or 1 (1 inverts the vector) \param vect2 - operand 2 GAP encoded buffer. \param vect2_mask - same as vect1_mask \param f - operation functor. \note Internal function. @ingroup gapfunc*/template<typename T, class F> void gap_buff_op(T* BMRESTRICT dest, const T* BMRESTRICT vect1, unsigned vect1_mask, const T* BMRESTRICT vect2, unsigned vect2_mask, F f){ register const T* cur1 = vect1; register const T* cur2 = vect2; unsigned bitval1 = (*cur1++ & 1) ^ vect1_mask; unsigned bitval2 = (*cur2++ & 1) ^ vect2_mask; unsigned bitval = f(bitval1, bitval2); unsigned bitval_prev = bitval; register T* res = dest; *res = bitval; ++res; while (1) { bitval = f(bitval1, bitval2); // Check if GAP value changes and we need to // start the next one. if (bitval != bitval_prev) { ++res; bitval_prev = bitval; } if (*cur1 < *cur2) { *res = *cur1; ++cur1; bitval1 ^= 1; } else // >= { *res = *cur2; if (*cur2 < *cur1) { bitval2 ^= 1; } else // equal { if (*cur2 == (bm::gap_max_bits - 1)) { break; } ++cur1; bitval1 ^= 1; bitval2 ^= 1; } ++cur2; } } // while unsigned dlen = (unsigned)(res - dest); *dest = (*dest & 7) + (dlen << 3);}/*! \brief Abstract distance(similarity) operation for GAP buffers. Receives functor F as a template argument \param vect1 - operand 1 GAP encoded buffer. \param vect2 - operand 2 GAP encoded buffer. \param f - operation functor. \note Internal function. @ingroup gapfunc*//*template<typename T, class F> unsigned gap_buff_count_op(const T* vect1, const T* vect2, F f){ register const T* cur1 = vect1; register const T* cur2 = vect2; unsigned bitval1 = (*cur1++ & 1); unsigned bitval2 = (*cur2++ & 1); unsigned bitval = f(bitval1, bitval2); unsigned bitval_prev = bitval; unsigned count = 0; T res; T res_prev; while (1) { bitval = f(bitval1, bitval2); // Check if GAP value changes and we need to // start the next one. if (bitval != bitval_prev) { bitval_prev = bitval; } if (*cur1 < *cur2) { if (bitval) count += *cur1; ++cur1; bitval1 ^= 1; } else // >= { if (bitval) count += *cur2; if (*cur2 < *cur1) { bitval2 ^= 1; } else // equal { if (*cur2 == (bm::gap_max_bits - 1)) { break; } ++cur1; bitval1 ^= 1; bitval2 ^= 1; } ++cur2; } } // while return count;}*//*! \brief Sets or clears bit in the GAP buffer. \param val - new bit value \param buf - GAP buffer. \param pos - Index of bit to set. \param is_set - (OUT) flag if bit was actually set. \return New GAP buffer length. @ingroup gapfunc*/template<typename T> unsigned gap_set_value(unsigned val, T* BMRESTRICT buf, unsigned pos, unsigned* BMRESTRICT is_set){ BM_ASSERT(pos < bm::gap_max_bits); unsigned curr = gap_bfind(buf, pos, is_set); register T end = (*buf >> 3); if (*is_set == val) { *is_set = 0; return end; } *is_set = 1; register T* pcurr = buf + curr; register T* pprev = pcurr - 1; register T* pend = buf + end; // Special case, first bit GAP operation. There is no platform beside it. // initial flag must be inverted. if (pos == 0) { *buf ^= 1; if ( buf[1] ) // We need to insert a 1 bit platform here. { ::memmove(&buf[2], &buf[1], (end - 1) * sizeof(gap_word_t)); buf[1] = 0; ++end; } else // Only 1 bit in the GAP. We need to delete the first GAP. { pprev = buf + 1; pcurr = pprev + 1; do { *pprev++ = *pcurr++; } while (pcurr < pend); --end; } } else if (curr > 1 && ((unsigned)(*pprev))+1 == pos) // Left border bit { ++(*pprev); if (*pprev == *pcurr) // Curr. GAP to be merged with prev.GAP. { --end; if (pcurr != pend) // GAP merge: 2 GAPS to be deleted { --end; ++pcurr; do { *pprev++ = *pcurr++; } while (pcurr < pend); } } } else if (*pcurr == pos) // Rightmost bit in the GAP. Border goes left. { --(*pcurr); if (pcurr == pend) { ++end; } } else // Worst case we need to split current block. { ::memmove(pcurr+2, pcurr,(end - curr + 1)*sizeof(T)); *pcurr++ = pos - 1; *pcurr = pos; end+=2; } // Set correct length word. *buf = (*buf & 7) + (end << 3); buf[end] = bm::gap_max_bits - 1; return end;}//------------------------------------------------------------------------/** \brief Searches for the next 1 bit in the GAP block \param buf - GAP buffer \param nbit - bit index to start checking from. \param prev - returns previously checked value @ingroup gapfunc*/template<typename T> int gap_find_in_block(const T* buf, unsigned nbit, bm::id_t* prev){ BM_ASSERT(nbit < bm::gap_max_bits); unsigned bitval; unsigned gap_idx = bm::gap_bfind(buf, nbit, &bitval); if (bitval) // positive block. { return 1; } register unsigned val = buf[gap_idx] + 1; *prev += val - nbit; return (val != bm::gap_max_bits); // no bug here.}/*! \brief Sets bits to 1 in the bitblock. \param dest - Bitset buffer. \param bitpos - Offset of the start bit. \param bitcount - number of bits to set. @ingroup bitfunc*/ inline void or_bit_block(unsigned* dest, unsigned bitpos, unsigned bitcount){ unsigned nbit = unsigned(bitpos & bm::set_block_mask); unsigned nword = unsigned(nbit >> bm::set_word_shift); 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) bit interval to 1 in the bitblock. \param dest - Bitset buffer. \param bitpos - Offset of the start bit. \param bitcount - number of bits to set. @ingroup bitfunc*/ inline void sub_bit_block(unsigned* dest, unsigned bitpos, unsigned bitcount){ unsigned nbit = unsigned(bitpos & bm::set_block_mask); unsigned nword = unsigned(nbit >> bm::set_word_shift); 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++ = 0; } if (bitcount) { *word &= ~block_set_table<true>::_left[bitcount-1]; }}/*! \brief XOR bit interval to 1 in the bitblock. \param dest - Bitset buffer. \param bitpos - Offset of the start bit. \param bitcount - number of bits to set. @ingroup bitfunc*/ inline void xor_bit_block(unsigned* dest, unsigned bitpos, unsigned bitcount){ unsigned nbit = unsigned(bitpos & bm::set_block_mask); unsigned nword = unsigned(nbit >> bm::set_word_shift);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -