📄 bmfunc.h
字号:
/* * =========================================================================== * PRODUCTION $Log: bmfunc.h,v $ * PRODUCTION Revision 1000.1 2004/06/01 19:39:08 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.3 * PRODUCTION * =========================================================================== *//*Copyright (c) 2002,2003 Anatoliy Kuznetsov.Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.*/#ifndef BMFUNC__H__INCLUDED__#define BMFUNC__H__INCLUDED__#include <memory.h>#ifdef _MSC_VER# pragma warning( disable: 4146 )#endifnamespace bm{/*! @defgroup gapfunc GAP functions * GAP functions implement different opereations on GAP compressed blocks * and serve as a minimal building blocks. * *//*! @defgroup bitfunc BIT functions * Bit functions implement different opereations on bit blocks * and serve as a minimal building blocks. * *//*! @brief Default GAP lengths table. @ingroup gapfunc*/template<bool T> struct gap_len_table{ static const gap_word_t _len[bm::gap_levels];};template<bool T>const gap_word_t gap_len_table<T>::_len[] = { 128, 256, 512, bm::gap_max_buff_len }; /*! @brief Alternative GAP lengths table. Good for for memory saver mode and very sparse bitsets. @ingroup gapfunc*/template<bool T> struct gap_len_table_min{ static const gap_word_t _len[bm::gap_levels];};template<bool T>const gap_word_t gap_len_table_min<T>::_len[] = { 32, 96, 128, 512 }; //---------------------------------------------------------------------/** Structure to aid in counting bits table contains count of bits in 0-255 diapason of numbers @ingroup bitfunc*/template<bool T> struct bit_count_table { static const unsigned char _count[256];};template<bool T>const unsigned char bit_count_table<T>::_count[] = { 0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4,1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 1,2,2,3,2,3,3,4,2,3,3,4,3,4,4,5,2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 2,3,3,4,3,4,4,5,3,4,4,5,4,5,5,6,3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7, 3,4,4,5,4,5,5,6,4,5,5,6,5,6,6,7,4,5,5,6,5,6,6,7,5,6,6,7,6,7,7,8};//---------------------------------------------------------------------/** Structure keeps all-left/right ON bits masks. @ingroup bitfunc */template<bool T> struct block_set_table{ static const unsigned _left[32]; static const unsigned _right[32];};template<bool T>const unsigned block_set_table<T>::_left[] = { 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff, 0x1ff, 0x3ff, 0x7ff, 0xfff, 0x1fff, 0x3fff, 0x7fff, 0xffff, 0x1ffff, 0x3ffff, 0x7ffff, 0xfffff, 0x1fffff, 0x3fffff, 0x7fffff, 0xffffff, 0x1ffffff, 0x3ffffff, 0x7ffffff, 0xfffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff};template<bool T>const unsigned block_set_table<T>::_right[] = { 0xffffffff, 0xfffffffe, 0xfffffffc, 0xfffffff8, 0xfffffff0, 0xffffffe0, 0xffffffc0, 0xffffff80, 0xffffff00, 0xfffffe00, 0xfffffc00, 0xfffff800, 0xfffff000, 0xffffe000, 0xffffc000, 0xffff8000, 0xffff0000, 0xfffe0000, 0xfffc0000, 0xfff80000, 0xfff00000, 0xffe00000, 0xffc00000, 0xff800000, 0xff000000, 0xfe000000, 0xfc000000, 0xf8000000, 0xf0000000, 0xe0000000, 0xc0000000, 0x80000000};/** Structure keeps index of first ON bit for every byte. @ingroup bitfunc */template<bool T> struct first_bit_table{ static const char _idx[256];};template<bool T>const char first_bit_table<T>::_idx[] = { -1, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0, 1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1, 0,2,0,1,0,3,0, 1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1, 0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0, 2,0,1,0,3,0,1,0,2,0,1,0,7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0,3,0,1,0,2,0, 1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6,0,1,0,2,0,1,0,3,0,1, 0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5,0,1,0,2,0,1,0, 3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0 };/*! Define calculates number of 1 bits in 32-bit word. @ingroup bitfunc */#define BM_INCWORD_BITCOUNT(cnt, w) cnt += \ bm::bit_count_table<true>::_count[(unsigned char)(w)] + \ bm::bit_count_table<true>::_count[(unsigned char)((w) >> 8)] + \ bm::bit_count_table<true>::_count[(unsigned char)((w) >> 16)] + \ bm::bit_count_table<true>::_count[(unsigned char)((w) >> 24)];#ifdef BM64OPT/*! Function calculates number of 1 bits in 64-bit word. @ingroup bitfunc */inline bm::id_t word_bitcount64(bm::id64_t w){ w = (w & 0x5555555555555555LU) + (w >> 1 & 0x5555555555555555LU); w = (w & 0x3333333333333333LU) + (w >> 2 & 0x3333333333333333LU); w = w + (w >> 4) & 0x0F0F0F0F0F0F0F0FLU; w = w + (w >> 8); w = w + (w >> 16); w = w + (w >> 32) & 0x0000007F; return (bm::id_t)w;}#endif//---------------------------------------------------------------------/** Bit operations enumeration.*/enum operation{ BM_AND = 0, BM_OR, BM_SUB, BM_XOR};//---------------------------------------------------------------------/** Structure carries pointer on bit block with all bits 1 @ingroup bitfunc */template<bool T> struct all_set{ struct all_set_block { bm::word_t _p[bm::set_block_size]; all_set_block() { ::memset(_p, 0xFF, sizeof(_p)); } }; static all_set_block _block;};template<bool T> typename all_set<T>::all_set_block all_set<T>::_block;//---------------------------------------------------------------------/*! \brief Lexicographical comparison of two words as bit strings. Auxiliary implementation for testing and reference purposes. \param buf1 - First word. \param buf2 - Second word. \return <0 - less, =0 - equal, >0 - greater. @ingroup bitfunc */template<typename T> int wordcmp0(T w1, T w2){ while (w1 != w2) { int res = (w1 & 1) - (w2 & 1); if (res != 0) return res; w1 >>= 1; w2 >>= 1; } return 0;}/*! \brief Lexicographical comparison of two words as bit strings. Auxiliary implementation for testing and reference purposes. \param buf1 - First word. \param buf2 - Second word. \return <0 - less, =0 - equal, >0 - greater. @ingroup bitfunc *//*template<typename T> int wordcmp(T w1, T w2){ T diff = w1 ^ w2; return diff ? ((w1 & diff & (diff ^ (diff - 1)))? 1 : -1) : 0; }*/template<typename T> int wordcmp(T a, T b){ T diff = a ^ b; return diff? ( (a & diff & -diff)? 1 : -1 ) : 0;}// Low bit extraction// x & (x ^ (x-1))/** Internal structure. Copyright information.*/template<bool T> struct _copyright{ static const char _p[];};template<bool T> const char _copyright<T>::_p[] = "BitMagic Library. v.3.2.1 (c) 2002-2003 Anatoliy Kuznetsov.";/*! \brief Byte orders recognized by the library.*/enum ByteOrder{ BigEndian = 0, LittleEndian = 1};/** Internal structure. Different global settings.*/template<bool T> struct globals{ struct bo { ByteOrder _byte_order; bo() { unsigned x; unsigned char *s = (unsigned char *)&x; s[0] = 1; s[1] = 2; s[2] = 3; s[3] = 4; if(x == 0x04030201) { _byte_order = LittleEndian; return; } if(x == 0x01020304) { _byte_order = BigEndian; return; } BM_ASSERT(0); // "Invalid Byte Order\n" _byte_order = LittleEndian; } }; static bo _bo; static ByteOrder byte_order() { return _bo._byte_order; }};template<bool T> typename globals<T>::bo globals<T>::_bo;/* \brief Binary search for the block where bit = pos located. \param buf - GAP buffer pointer. \param pos - index of the element. \param is_set - output. GAP value (0 or 1). \return GAP index. @ingroup gapfunc*/template<typename T> unsigned gap_bfind(const T* buf, unsigned pos, unsigned* is_set){ BM_ASSERT(pos < bm::gap_max_bits); *is_set = (*buf) & 1; register unsigned start = 1; register unsigned end = 1 + ((*buf) >> 3); while ( start != end ) { unsigned curr = (start + end) >> 1; if ( buf[curr] < pos ) start = curr + 1; else end = curr; } *is_set ^= ((start-1) & 1); return start; }/*! \brief Tests if bit = pos is true. \param buf - GAP buffer pointer. \param pos - index of the element. \return true if position is in "1" gap @ingroup gapfunc*/template<typename T> unsigned gap_test(const T* buf, unsigned pos){ BM_ASSERT(pos < bm::gap_max_bits); unsigned start = 1; unsigned end = 1 + ((*buf) >> 3); if (end - start < 10) { unsigned sv = *buf & 1; unsigned sv1= sv ^ 1; if (buf[1] >= pos) return sv; if (buf[2] >= pos) return sv1; if (buf[3] >= pos) return sv; if (buf[4] >= pos) return sv1; if (buf[5] >= pos) return sv; if (buf[6] >= pos) return sv1; if (buf[7] >= pos) return sv; if (buf[8] >= pos) return sv1; if (buf[9] >= pos) return sv; BM_ASSERT(0); } else while ( start != end ) { unsigned curr = (start + end) >> 1; if ( buf[curr] < pos ) start = curr + 1; else end = curr; } return ((*buf) & 1) ^ ((--start) & 1); }/*! For each non-zero block executes supplied function.*/template<class T, class F> void for_each_nzblock(T*** root, unsigned size1, unsigned size2, F& f){ unsigned block_idx = 0; for (unsigned i = 0; i < size1; ++i) { T** blk_blk = root[i]; if (!blk_blk) { block_idx += bm::set_array_size; continue; } for (unsigned j = 0;j < size2; ++j, ++block_idx) { if (blk_blk[j]) f(blk_blk[j], block_idx); } } }/*! For each non-zero block executes supplied function-predicate. Function returns if function-predicate returns true*/template<class T, class F> bool for_each_nzblock_if(T*** root, unsigned size1, unsigned size2, F& f){ unsigned block_idx = 0; for (unsigned i = 0; i < size1; ++i) { T** blk_blk = root[i]; if (!blk_blk) { block_idx += bm::set_array_size; continue; } for (unsigned j = 0;j < size2; ++j, ++block_idx) { if (blk_blk[j]) if (f(blk_blk[j], block_idx)) return true; } } return false;}/*! For each block executes supplied function.*/template<class T, class F> void for_each_block(T*** root, unsigned size1, unsigned size2, F& f){ unsigned block_idx = 0; for (unsigned i = 0; i < size1; ++i) { T** blk_blk = root[i]; if (blk_blk) { for (unsigned j = 0;j < size2; ++j, ++block_idx) { f(blk_blk[j], block_idx); } } else { for (unsigned j = 0;j < size2; ++j, ++block_idx) { f(0, block_idx); } } } }/*! Special BM optimized analog of STL for_each*/template<class T, class F> F bmfor_each(T first, T last, F f){ do { f(*first); ++first; } while (first < last); return f;}/*! Computes SUM of all elements of the sequence*/template<class T> T sum_arr(T* first, T* last){ T sum = 0; while (first < last) { sum += *first; ++first; } return sum;}/*! \brief Calculates number of bits ON in GAP buffer. \param buf - GAP buffer pointer. \return Number of non-zero bits. @ingroup gapfunc*/template<typename T> unsigned gap_bit_count(const T* buf) { register const T* pcurr = buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -