dlvhex  2.5.0
vs10/bm/bmvmin.h
Go to the documentation of this file.
00001 #ifndef BMVMIN__H__INCLUDED__
00002 #define BMVMIN__H__INCLUDED__
00003 /*
00004 Copyright(c) 2002-2005 Anatoliy Kuznetsov(anatoliy_kuznetsov at yahoo.com)
00005 
00006 Permission is hereby granted, free of charge, to any person 
00007 obtaining a copy of this software and associated documentation 
00008 files (the "Software"), to deal in the Software without restriction, 
00009 including without limitation the rights to use, copy, modify, merge, 
00010 publish, distribute, sublicense, and/or sell copies of the Software, 
00011 and to permit persons to whom the Software is furnished to do so, 
00012 subject to the following conditions:
00013 
00014 The above copyright notice and this permission notice shall be included 
00015 in all copies or substantial portions of the Software.
00016 
00017 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
00018 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
00019 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
00020 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
00021 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 
00022 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
00023 OTHER DEALINGS IN THE SOFTWARE.
00024 
00025 For more information please visit:  http://bmagic.sourceforge.net
00026 
00027 */
00028 
00029 #ifdef _MSC_VER
00030 #pragma warning( push )
00031 #pragma warning( disable : 4100)
00032 #endif
00033 
00034 namespace bm
00035 {
00036 
00037 
00038 #define BM_MINISET_GAPLEN (bm::gap_len_table<true>::_len[0])
00039 #define BM_MINISET_ARRSIZE(x) ((x / 32) + ( (x % 32) && 1 ))
00040 
00058 template <class A, size_t N> class miniset
00059 {
00060 public:
00061 
00062     miniset() 
00063         : m_buf(0),
00064           m_type(1)
00065     {}
00066 
00067     miniset(const miniset& mset)
00068     {
00069         if (mset.m_buf)
00070         {
00071             if (mset.m_type)
00072                 init_gapbuf(mset.m_buf);
00073             else
00074                 init_bitbuf(mset.m_buf);
00075         }
00076         else
00077         {
00078             m_type = mset.m_type;
00079             m_buf = 0;
00080         }
00081     }
00082 
00083     ~miniset()
00084     {
00085         if (m_buf)
00086         {
00087             A::deallocate(m_buf, m_type ? 
00088                 (BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t)))
00089                 : 
00090                 (BM_MINISET_ARRSIZE(N)));
00091         }
00092     }
00093 
00095     unsigned test(bm::id_t n) const 
00096     { 
00097         return
00098             !m_buf ? 0 
00099             :
00100             m_type ? 
00101               gap_test((gap_word_t*)m_buf, n)
00102               : 
00103               m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
00104     }
00105 
00106     void set(bm::id_t n, bool val=true)
00107     {
00108         if (m_type == 0)
00109         {
00110             if (!m_buf)
00111             {
00112                 if (!val) return;
00113                 init_bitbuf(0);
00114             }
00115 
00116             unsigned nword  = n >> bm::set_word_shift; 
00117             unsigned mask = unsigned(1) << (n & bm::set_word_mask);
00118 
00119             val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
00120         }
00121         else
00122         {
00123             if (!m_buf)
00124             {
00125                 if (!val) return;
00126                 init_gapbuf(0);
00127             }
00128             
00129             unsigned is_set;
00130             unsigned new_block_len = 
00131                 gap_set_value(val, (gap_word_t*)m_buf, n, &is_set);
00132 
00133             if (new_block_len > unsigned(BM_MINISET_GAPLEN-4))
00134             {
00135                 convert_buf();
00136             }
00137         }
00138     }
00139 
00140     unsigned mem_used() const
00141     {
00142         return sizeof(*this) +
00143                m_buf ? 
00144                  (m_type ? (BM_MINISET_GAPLEN * sizeof(gap_word_t))
00145                         : (BM_MINISET_ARRSIZE(N) * sizeof(bm::word_t)))
00146                 : 0; 
00147     }
00148 
00149     void swap(miniset& mset)
00150     {
00151         bm::word_t* buftmp = m_buf;
00152         m_buf = mset.m_buf;
00153         mset.m_buf = buftmp;
00154         unsigned typetmp = m_type;
00155         m_type = mset.m_type;
00156         mset.m_type = typetmp;
00157     }
00158 
00159 
00160 private:
00161 
00162     void init_bitbuf(bm::word_t* buf)
00163     {
00164         unsigned arr_size = BM_MINISET_ARRSIZE(N);
00165         m_buf = A::allocate(arr_size, 0);
00166         if (buf)
00167         {
00168             ::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
00169         }
00170         else
00171         {
00172             ::memset(m_buf, 0, arr_size * sizeof(bm::word_t));
00173         }
00174         m_type = 0;
00175     }
00176 
00177     void init_gapbuf(bm::word_t* buf)
00178     {
00179         unsigned arr_size = 
00180             BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
00181         m_buf = A::allocate(arr_size, 0);
00182         if (buf)
00183         {
00184             ::memcpy(m_buf, buf, arr_size * sizeof(bm::word_t));
00185         }
00186         else
00187         {
00188             *m_buf = 0;
00189             gap_set_all((gap_word_t*)m_buf, bm::gap_max_bits, 0);
00190         }
00191         m_type = 1;
00192     }
00193 
00194     void convert_buf()
00195     {
00196         unsigned arr_size = BM_MINISET_ARRSIZE(N);
00197         bm::word_t* buf = A::allocate(arr_size, 0);
00198 
00199         gap_convert_to_bitset(buf, (gap_word_t*) m_buf, arr_size);
00200         arr_size = 
00201             BM_MINISET_GAPLEN / (sizeof(bm::word_t) / sizeof(bm::gap_word_t));
00202         A::deallocate(m_buf, arr_size);
00203         m_buf = buf;
00204         m_type = 0;
00205     }
00206 
00207 private:
00208     bm::word_t*   m_buf;      
00209     unsigned      m_type;     
00210 };
00211 
00212 
00221 template<size_t N> class bvmini
00222 {
00223 public:
00224 
00225     bvmini(int start_strategy = 0) 
00226     {
00227         ::memset(m_buf, 0, sizeof(m_buf));
00228     }
00229 
00230     bvmini(const bvmini& mset)
00231     {
00232         ::memcpy(m_buf, mset.m_buf, sizeof(m_buf));
00233     }
00234 
00235 
00237     unsigned test(bm::id_t n) const 
00238     { 
00239         return m_buf[n>>bm::set_word_shift] & (1<<(n & bm::set_word_mask));
00240     }
00241 
00242     void set(bm::id_t n, bool val=true)
00243     {
00244         unsigned nword  = n >> bm::set_word_shift; 
00245         unsigned mask = unsigned(1) << (n & bm::set_word_mask);
00246 
00247         val ? (m_buf[nword] |= mask) : (m_buf[nword] &= ~mask);
00248     }
00249 
00250     unsigned mem_used() const
00251     {
00252         return sizeof(*this);
00253     }
00254 
00255     void swap(bvmini& mset)
00256     {
00257         for (unsigned i = 0; i < BM_MINISET_ARRSIZE(N); ++i)
00258         {
00259             bm::word_t tmp = m_buf[i];
00260             m_buf[i] = mset.m_buf[i];
00261             mset.m_buf[i] = tmp;
00262         }
00263     }
00264 
00265 private:
00266     bm::word_t   m_buf[BM_MINISET_ARRSIZE(N)];
00267 };
00268 
00269 
00278 template<class A> class bvector_mini
00279 {
00280 public:
00281     bvector_mini(unsigned size) 
00282       : m_buf(0),
00283         m_size(size)
00284     {
00285         unsigned arr_size = (size / 32) + 1; 
00286         m_buf = A::allocate(arr_size, 0);
00287         ::memset(m_buf, 0, arr_size * sizeof(unsigned));
00288     }
00289     bvector_mini(const bvector_mini& bvect)
00290        : m_size(bvect.m_size)
00291     {
00292         unsigned arr_size = (m_size / 32) + 1;
00293         m_buf = A::allocate(arr_size, 0);
00294         ::memcpy(m_buf, bvect.m_buf, arr_size * sizeof(unsigned));        
00295     }
00296 
00297     ~bvector_mini()
00298     {
00299         A::deallocate(m_buf, (m_size / 32) + 1); 
00300     }
00301 
00303     int is_bit_true(unsigned pos) const
00304     {
00305         unsigned char  mask = (unsigned char)((char)0x1 << (pos & 7));
00306         unsigned char* offs = (unsigned char*)m_buf + (pos >> 3); // m_buf + (pos/8)
00307 
00308         return (*offs) & mask;
00309     }
00310 
00312     void set_bit(unsigned pos)
00313     {
00314         unsigned char  mask = (unsigned char)(0x1 << (pos & 7));
00315         unsigned char* offs = (unsigned char*)m_buf + (pos >> 3); 
00316         *offs |= mask;
00317     }
00318 
00319 
00321     void clear_bit(unsigned pos)
00322     {
00323         unsigned char  mask = (unsigned char)(0x1 << (pos & 7));
00324         unsigned char* offs = (unsigned char*)m_buf + (pos >> 3); 
00325 
00326         *offs &= ~mask;
00327     }
00328 
00330     unsigned bit_count() const
00331     {
00332         register unsigned count = 0;
00333         const unsigned* end = m_buf + (m_size / 32)+1;    
00334 
00335         for (unsigned* start = m_buf; start < end; ++start)
00336         {
00337             register unsigned value = *start;
00338             for (count += (value!=0); value &= value - 1; ++count);
00339         }
00340         return count;
00341     }
00342 
00344     int compare(const bvector_mini& bvect)
00345     {
00346         unsigned cnt1 = bit_count();
00347         unsigned cnt2 = bvect.bit_count();
00348 
00349         if (!cnt1 && !cnt2) return 0;
00350 
00351         unsigned cnt_min = cnt1 < cnt2 ? cnt1 : cnt2;
00352 
00353         if (!cnt_min) return cnt1 ? 1 : -1;
00354 
00355         unsigned idx1 = get_first();
00356         unsigned idx2 = bvect.get_first();
00357 
00358         for (unsigned i = 0; i < cnt_min; ++i)
00359         {
00360             if (idx1 != idx2)
00361             {
00362                 return idx1 < idx2 ? 1 : -1;
00363             }
00364             idx1 = get_next(idx1);
00365             idx2 = bvect.get_next(idx2);
00366         }
00367 
00368         //BM_ASSERT(idx1==0 || idx2==0);
00369 
00370         if (idx1 != idx2)
00371         {
00372             if (!idx1) return -1;
00373             if (!idx2) return  1;
00374             return idx1 < idx2 ? 1 : -1;
00375         }
00376 
00377         return 0;
00378     }
00379 
00380 
00382     unsigned get_first() const
00383     {
00384         unsigned pos = 0;
00385         const unsigned char* ptr = (unsigned char*) m_buf;
00386 
00387         for (unsigned i = 0; i < (m_size/8)+1; ++i)
00388         {
00389             register unsigned char w = ptr[i];
00390 
00391 
00392             if (w != 0)
00393             {
00394                 while ((w & 1) == 0)
00395                 {
00396                     w >>= 1;
00397                     ++pos;
00398                 }
00399                 return pos;
00400             }
00401             pos += sizeof(unsigned char) * 8;
00402         }
00403         return 0;
00404     }
00405 
00406 
00408     unsigned get_next(unsigned idx) const
00409     {
00410         register unsigned i;
00411 
00412         for (i = idx+1; i < m_size; ++i)
00413         {
00414             unsigned char* offs = (unsigned char*)m_buf + (i >> 3); 
00415             if (*offs)
00416             {
00417                 unsigned char mask = (unsigned char)((char)0x1 << (i & 7));
00418 
00419                 if (*offs & mask)
00420                 {
00421                     return i;
00422                 }
00423             }
00424             else
00425             {
00426                 i += 7;
00427             }
00428         }
00429         return 0;
00430     }
00431 
00432 
00433     void combine_and(const bvector_mini& bvect)
00434     {
00435         const unsigned* end = m_buf + (m_size / 32)+1;
00436     
00437         const unsigned* src = bvect.get_buf();
00438 
00439         for (unsigned* start = m_buf; start < end; ++start)
00440         {
00441             *start &= *src++;
00442         }
00443     }
00444 
00445     void combine_xor(const bvector_mini& bvect)
00446     {
00447         const unsigned* end = m_buf + (m_size / 32)+1;
00448     
00449         const unsigned* src = bvect.get_buf();
00450 
00451         for (unsigned* start = m_buf; start < end; ++start)
00452         {
00453             *start ^= *src++;
00454         }
00455     }
00456 
00457 
00458     void combine_or(const bvector_mini& bvect)
00459     {
00460         const unsigned* end = m_buf + (m_size / 32)+1;
00461     
00462         const unsigned* src = bvect.get_buf();
00463 
00464         for (unsigned* start = m_buf; start < end; ++start)
00465         {
00466             *start |= *src++;
00467         }
00468     }
00469 
00470     void combine_sub(const bvector_mini& bvect)
00471     {
00472         const unsigned* end = m_buf + (m_size / 32)+1;
00473     
00474         const unsigned* src = bvect.get_buf();
00475 
00476         for (unsigned* start = m_buf; start < end; ++start)
00477         {
00478             *start &= ~(*src++);
00479         }
00480     }
00481 
00482     const unsigned* get_buf() const { return m_buf; }
00483     unsigned mem_used() const
00484     {
00485         return sizeof(bvector_mini) + (m_size / 32) + 1;
00486     }
00487 
00488     void swap(bvector_mini& bvm)
00489     {
00490         BM_ASSERT(m_size == bvm.m_size);
00491         bm::word_t* buftmp = m_buf;
00492         m_buf = bvm.m_buf;
00493         bvm.m_buf = buftmp;
00494     }
00495 
00496 private:
00497     bm::word_t*   m_buf;
00498     unsigned      m_size;
00499 };
00500 
00501 
00502 
00503 } // namespace bm
00504 
00505 #ifdef _MSC_VER
00506 #pragma warning( pop )
00507 #endif
00508 
00509 #endif