Generated on Tue Apr 18 10:22:14 2017 for Gecode by doxygen 1.6.3

bitset-base.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00005  *
00006  *  Contributing authors:
00007  *     Christian Schulte <schulte@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Mikael Lagerkvist, 2007
00011  *     Christian Schulte, 2007
00012  *
00013  *  Last modified:
00014  *     $Date: 2016-04-19 17:19:45 +0200 (Tue, 19 Apr 2016) $ by $Author: schulte $
00015  *     $Revision: 14967 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 #include <climits>
00043 
00044 #ifdef _MSC_VER
00045 
00046 #include <intrin.h>
00047 
00048 #if defined(_M_IX86)
00049 #pragma intrinsic(_BitScanForward)
00050 #define GECODE_SUPPORT_MSVC_32
00051 #endif
00052 
00053 #if defined(_M_X64) || defined(_M_IA64)
00054 #pragma intrinsic(_BitScanForward64)
00055 #define GECODE_SUPPORT_MSVC_64
00056 #endif
00057 
00058 #endif
00059 
00060 namespace Gecode { namespace Support {
00061 
00062   class RawBitSetBase;
00063 
00065   class BitSetData {
00066     friend class RawBitSetBase;
00067   protected:
00068 #ifdef GECODE_SUPPORT_MSVC_64
00069 
00070     typedef unsigned __int64 Base;
00071 #else
00072 
00073     typedef unsigned long int Base;
00074 #endif
00075 
00076     Base bits;
00078     static const unsigned int bpb =
00079       static_cast<unsigned int>(CHAR_BIT * sizeof(Base));
00080   public:
00082     void init(bool setbits=false);
00084     static unsigned int data(unsigned int s);
00086     bool operator ()(unsigned int i=0U) const;
00088     bool get(unsigned int i) const;
00090     void set(unsigned int i);
00092     void clear(unsigned int i);
00094     unsigned int next(unsigned int i=0U) const;
00096     bool all(void) const;
00098     bool all(unsigned int i) const;
00100     bool none(void) const;
00102     bool none(unsigned int i) const;
00104     void a(BitSetData a);
00106     void a(BitSetData a, unsigned int i);
00108     static BitSetData a(BitSetData a, BitSetData b);
00110     void o(BitSetData a);
00112     void o(BitSetData a, unsigned int i);
00114     static BitSetData o(BitSetData a, BitSetData b);
00115   };
00116 
00118   enum BitSetStatus {
00119     BSS_NONE, 
00120     BSS_ALL,  
00121     BSS_SOME  
00122   };
00123 
00125   class RawBitSetBase {
00126   protected:
00128     static const unsigned int bpb = BitSetData::bpb;
00130     BitSetData* data;
00131   private:
00133     RawBitSetBase(const RawBitSetBase&);
00135     RawBitSetBase& operator =(const RawBitSetBase&);
00136   public:
00138     RawBitSetBase(void);
00140     template<class A>
00141     RawBitSetBase(A& a, unsigned int sz, bool setbits=false);
00143     template<class A>
00144     RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs);
00146     template<class A>
00147     void allocate(A& a, unsigned int sz);
00149     template<class A>
00150     void init(A& a, unsigned int sz, bool setbits=false);
00152     void clearall(unsigned int sz, bool setbits=false);
00154     void copy(unsigned int sz, const RawBitSetBase& bs);
00156     bool get(unsigned int i) const;
00158     void set(unsigned int i);
00160     void clear(unsigned int i);
00162     unsigned int next(unsigned int i) const;
00164     BitSetStatus status(unsigned int sz) const;
00166     bool all(unsigned int sz) const;
00168     bool none(unsigned int sz) const;
00170     template<class A>
00171     void resize(A& a, unsigned int sz, unsigned int n, bool setbits=false);
00173     template<class A>
00174     void dispose(A& a, unsigned int sz);
00175   };
00176 
00178   class BitSetBase : public RawBitSetBase {
00179   protected:
00181     unsigned int sz;
00182   private:
00184     BitSetBase(const BitSetBase&);
00186     BitSetBase& operator =(const BitSetBase&);
00187   public:
00189     BitSetBase(void);
00191     template<class A>
00192     BitSetBase(A& a, unsigned int s, bool setbits=false);
00194     template<class A>
00195     BitSetBase(A& a, const BitSetBase& bs);
00197     template<class A>
00198     void init(A& a, unsigned int s, bool setbits=false);
00200     void clearall(bool setbits=false);
00202     void copy(const BitSetBase& bs);
00204     unsigned int size(void) const;
00206     bool get(unsigned int i) const;
00208     void set(unsigned int i);
00210     void clear(unsigned int i);
00212     unsigned int next(unsigned int i) const;
00214     BitSetStatus status(void) const;
00216     bool all(void) const;
00218     bool none(void) const;
00220     template<class A>
00221     void resize(A& a, unsigned int n, bool setbits=false);
00223     template<class A>
00224     void dispose(A& a);
00225   };
00226 
00227 
00228   /*
00229    * Bitset data
00230    *
00231    */
00232 
00233   forceinline void
00234   BitSetData::init(bool setbits) {
00235     bits = setbits ? ~static_cast<Base>(0) : static_cast<Base>(0);
00236   }
00237   forceinline unsigned int
00238   BitSetData::data(unsigned int s) {
00239     return s == 0 ? 0 : ((s-1) / bpb + 1);
00240   }
00241   forceinline bool
00242   BitSetData::operator ()(unsigned int i) const {
00243     return (bits >> i) != static_cast<Base>(0U);
00244   }
00245   forceinline bool
00246   BitSetData::get(unsigned int i) const {
00247     return (bits & (static_cast<Base>(1U) << i)) != static_cast<Base>(0U);
00248   }
00249   forceinline void
00250   BitSetData::set(unsigned int i) {
00251     bits |= (static_cast<Base>(1U) << i);
00252   }
00253   forceinline void
00254   BitSetData::clear(unsigned int i) {
00255     bits &= ~(static_cast<Base>(1U) << i);
00256   }
00257   forceinline unsigned int
00258   BitSetData::next(unsigned int i) const {
00259     assert(bits != static_cast<Base>(0));
00260 #if defined(GECODE_SUPPORT_MSVC_32)
00261     assert(bpb == 32);
00262     unsigned long int p;
00263     _BitScanForward(&p,bits >> i);
00264     return static_cast<unsigned int>(p)+i;
00265 #elif defined(GECODE_SUPPORT_MSVC_64)
00266     assert(bpb == 64);
00267     unsigned long int p;
00268     _BitScanForward64(&p,bits >> i);
00269     return static_cast<unsigned int>(p)+i;
00270 #elif defined(GECODE_HAS_BUILTIN_FFSL)
00271     if ((bpb == 32) || (bpb == 64)) {
00272       int p = __builtin_ffsl(bits >> i);
00273       assert(p > 0);
00274       return static_cast<unsigned int>(p-1)+i;
00275     }
00276 #else
00277     while (!get(i)) i++;
00278     return i;
00279 #endif
00280   }
00281   forceinline bool
00282   BitSetData::all(void) const {
00283     return bits == ~static_cast<Base>(0U);
00284   }
00285   forceinline bool
00286   BitSetData::all(unsigned int i) const {
00287     const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
00288     return (bits & mask) == mask;
00289   }
00290   forceinline bool
00291   BitSetData::none(void) const {
00292     return bits == static_cast<Base>(0U);
00293   }
00294   forceinline bool
00295   BitSetData::none(unsigned int i) const {
00296     const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
00297     return (bits & mask) == static_cast<Base>(0U);
00298   }
00299 
00300   forceinline void
00301   BitSetData::a(BitSetData a) {
00302     bits &= a.bits;
00303   }
00304   forceinline void
00305   BitSetData::a(BitSetData a, unsigned int i) {
00306     const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
00307     bits &= (a.bits & mask);
00308   }
00309   forceinline BitSetData
00310   BitSetData::a(BitSetData a, BitSetData b) {
00311     BitSetData ab;
00312     ab.bits = a.bits & b.bits;
00313     return ab;
00314   }
00315 
00316   forceinline void
00317   BitSetData::o(BitSetData a) {
00318     bits |= a.bits;
00319   }
00320   forceinline void
00321   BitSetData::o(BitSetData a, unsigned int i) {
00322     const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
00323     bits |= (a.bits & mask);
00324   }
00325   forceinline BitSetData
00326   BitSetData::o(BitSetData a, BitSetData b) {
00327     BitSetData ab;
00328     ab.bits = a.bits | b.bits;
00329     return ab;
00330   }
00331 
00332 
00333   /*
00334    * Basic bit sets
00335    *
00336    */
00337 
00338   forceinline bool
00339   RawBitSetBase::get(unsigned int i) const {
00340     return data[i / bpb].get(i % bpb);
00341   }
00342   forceinline void
00343   RawBitSetBase::set(unsigned int i) {
00344     data[i / bpb].set(i % bpb);
00345   }
00346   forceinline void
00347   RawBitSetBase::clear(unsigned int i) {
00348     data[i / bpb].clear(i % bpb);
00349   }
00350 
00351   template<class A>
00352   void
00353   RawBitSetBase::resize(A& a, unsigned int sz, unsigned int n, bool setbits) {
00354     if (n>sz) {
00355       data = a.template realloc<BitSetData>(data,BitSetData::data(sz+1),
00356                                             BitSetData::data(n+1));
00357       for (unsigned int i=BitSetData::data(sz)+1;
00358            i<BitSetData::data(n+1); i++) {
00359         data[i].init(setbits);
00360       }
00361       for (unsigned int i=(sz%bpb); i<bpb; i++)
00362         if (setbits)
00363           data[sz / bpb].set(i);
00364         else
00365           data[sz / bpb].clear(i);
00366     }
00367     set(n);
00368   }
00369 
00370   template<class A>
00371   forceinline void
00372   RawBitSetBase::dispose(A& a, unsigned int sz) {
00373     a.template free<BitSetData>(data,BitSetData::data(sz+1));
00374   }
00375 
00376   forceinline
00377   RawBitSetBase::RawBitSetBase(void)
00378     : data(NULL) {}
00379 
00380   template<class A>
00381   forceinline
00382   RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, bool setbits)
00383     : data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
00384     for (unsigned int i = BitSetData::data(sz+1); i--; )
00385       data[i].init(setbits);
00386     // Set a bit at position sz as sentinel (for efficient next)
00387     set(sz);
00388   }
00389 
00390   template<class A>
00391   forceinline
00392   RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs)
00393     : data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
00394     for (unsigned int i = BitSetData::data(sz+1); i--; )
00395       data[i] = bs.data[i];
00396     // Set a bit at position sz as sentinel (for efficient next)
00397     set(sz);
00398   }
00399 
00400   template<class A>
00401   forceinline void
00402   RawBitSetBase::allocate(A& a, unsigned int sz) {
00403     assert(data == NULL);
00404     data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
00405   }
00406 
00407   template<class A>
00408   forceinline void
00409   RawBitSetBase::init(A& a, unsigned int sz, bool setbits) {
00410     assert(data == NULL);
00411     data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
00412     for (unsigned int i=BitSetData::data(sz+1); i--; )
00413       data[i].init(setbits);
00414     // Set a bit at position sz as sentinel (for efficient next)
00415     set(sz);
00416   }
00417 
00418   forceinline void
00419   RawBitSetBase::copy(unsigned int sz, const RawBitSetBase& bs) {
00420     for (unsigned int i=BitSetData::data(sz+1); i--; )
00421       data[i] = bs.data[i];
00422   }
00423 
00424   forceinline void
00425   RawBitSetBase::clearall(unsigned int sz, bool setbits) {
00426     for (unsigned int i=BitSetData::data(sz+1); i--; )
00427       data[i].init(setbits);
00428   }
00429 
00430   forceinline unsigned int
00431   RawBitSetBase::next(unsigned int i) const {
00432     unsigned int pos = i / bpb;
00433     unsigned int bit = i % bpb;
00434     if (data[pos](bit))
00435       return pos * bpb + data[pos].next(bit);
00436     // The sentinel bit guarantees that this loop always terminates
00437     do {
00438       pos++;
00439     } while (!data[pos]());
00440     return pos * bpb + data[pos].next();
00441   }
00442 
00443   forceinline BitSetStatus
00444   RawBitSetBase::status(unsigned int sz) const {
00445     unsigned int pos = sz / bpb;
00446     unsigned int bits = sz % bpb;
00447     if (pos > 0) {
00448       if (data[0].all()) {
00449         for (unsigned int i=1; i<pos; i++)
00450           if (!data[i].all())
00451             return BSS_SOME;
00452         return data[pos].all(bits) ? BSS_ALL : BSS_SOME;
00453       } else if (data[0].none()) {
00454         for (unsigned int i=1; i<pos; i++)
00455           if (!data[i].none())
00456             return BSS_SOME;
00457         return data[pos].none(bits) ? BSS_NONE : BSS_SOME;
00458       } else {
00459         return BSS_SOME;
00460       }
00461     }
00462     if (data[0].all(bits))
00463       return BSS_ALL;
00464     if (data[0].none(bits))
00465       return BSS_NONE;
00466     return BSS_SOME;
00467   }
00468 
00469   forceinline bool
00470   RawBitSetBase::all(unsigned int sz) const {
00471     return status(sz) == BSS_ALL;
00472   }
00473 
00474   forceinline bool
00475   RawBitSetBase::none(unsigned int sz) const {
00476     return status(sz) == BSS_NONE;
00477   }
00478 
00479 
00480   template<class A>
00481   void
00482   BitSetBase::resize(A& a, unsigned int n, bool setbits) {
00483     RawBitSetBase::resize(a,sz,n,setbits); sz=n;
00484   }
00485 
00486   template<class A>
00487   forceinline void
00488   BitSetBase::dispose(A& a) {
00489     RawBitSetBase::dispose(a,sz);
00490   }
00491 
00492   forceinline
00493   BitSetBase::BitSetBase(void)
00494     : sz(0U) {}
00495 
00496   template<class A>
00497   forceinline
00498   BitSetBase::BitSetBase(A& a, unsigned int s, bool setbits)
00499     : RawBitSetBase(a,s,setbits), sz(s) {}
00500 
00501   template<class A>
00502   forceinline
00503   BitSetBase::BitSetBase(A& a, const BitSetBase& bs)
00504     : RawBitSetBase(a,bs.sz,bs), sz(bs.sz) {}
00505 
00506   template<class A>
00507   forceinline void
00508   BitSetBase::init(A& a, unsigned int s, bool setbits) {
00509     assert(sz == 0);
00510     RawBitSetBase::init(a,s,setbits); sz=s;
00511   }
00512 
00513   forceinline void
00514   BitSetBase::copy(const BitSetBase& bs) {
00515     assert(sz == bs.sz);
00516     RawBitSetBase::copy(sz,bs);
00517   }
00518 
00519   forceinline void
00520   BitSetBase::clearall(bool setbits) {
00521     RawBitSetBase::clearall(sz,setbits);
00522   }
00523 
00524   forceinline unsigned int
00525   BitSetBase::size(void) const {
00526     return sz;
00527   }
00528 
00529   forceinline bool
00530   BitSetBase::get(unsigned int i) const {
00531     assert(i < sz);
00532     return RawBitSetBase::get(i);
00533   }
00534   forceinline void
00535   BitSetBase::set(unsigned int i) {
00536     assert(i < sz);
00537     RawBitSetBase::set(i);
00538   }
00539   forceinline void
00540   BitSetBase::clear(unsigned int i) {
00541     assert(i < sz);
00542     RawBitSetBase::clear(i);
00543   }
00544 
00545   forceinline unsigned int
00546   BitSetBase::next(unsigned int i) const {
00547     assert(i <= sz);
00548     return RawBitSetBase::next(i);
00549   }
00550 
00551   forceinline BitSetStatus
00552   BitSetBase::status(void) const {
00553     return RawBitSetBase::status(sz);
00554   }
00555 
00556   forceinline bool
00557   BitSetBase::all(void) const {
00558     return RawBitSetBase::all(sz);
00559   }
00560 
00561   forceinline bool
00562   BitSetBase::none(void) const {
00563     return RawBitSetBase::none(sz);
00564   }
00565 
00566 }}
00567 
00568 #ifdef GECODE_SUPPORT_MSVC_32
00569 #undef GECODE_SUPPORT_MSVC_32
00570 #endif
00571 #ifdef GECODE_SUPPORT_MSVC_64
00572 #undef GECODE_SUPPORT_MSVC_64
00573 #endif
00574 
00575 // STATISTICS: support-any
00576