bitset-base.hpp climits /usr/include/gecode/support.hh Gecode::Support::BitSetData Gecode::Support::BitSetBase Gecode Gecode::Support /*-*-mode:C++;c-basic-offset:2;indent-tabs-mode:nil-*-*/ /* *Mainauthors: *MikaelLagerkvist<lagerkvist@gecode.org> * *Contributingauthors: *ChristianSchulte<schulte@gecode.org> * *Copyright: *MikaelLagerkvist,2007 *ChristianSchulte,2007 * *Lastmodified: *$Date:2012-07-1302:37:25+0200(Fri,13Jul2012)$by$Author:tack$ *$Revision:12962$ * *ThisfileispartofGecode,thegenericconstraint *developmentenvironment: *http://www.gecode.org * *Permissionisherebygranted,freeofcharge,toanypersonobtaining *acopyofthissoftwareandassociateddocumentationfiles(the *"Software"),todealintheSoftwarewithoutrestriction,including *withoutlimitationtherightstouse,copy,modify,merge,publish, *distribute,sublicense,and/orsellcopiesoftheSoftware,andto *permitpersonstowhomtheSoftwareisfurnishedtodoso,subjectto *thefollowingconditions: * *Theabovecopyrightnoticeandthispermissionnoticeshallbe *includedinallcopiesorsubstantialportionsoftheSoftware. * *THESOFTWAREISPROVIDED"ASIS",WITHOUTWARRANTYOFANYKIND, *EXPRESSORIMPLIED,INCLUDINGBUTNOTLIMITEDTOTHEWARRANTIESOF *MERCHANTABILITY,FITNESSFORAPARTICULARPURPOSEAND *NONINFRINGEMENT.INNOEVENTSHALLTHEAUTHORSORCOPYRIGHTHOLDERSBE *LIABLEFORANYCLAIM,DAMAGESOROTHERLIABILITY,WHETHERINANACTION *OFCONTRACT,TORTOROTHERWISE,ARISINGFROM,OUTOFORINCONNECTION *WITHTHESOFTWAREORTHEUSEOROTHERDEALINGSINTHESOFTWARE. * */ #include<climits> #ifdef_MSC_VER #include<intrin.h> #ifdefined(_M_IX86) #pragmaintrinsic(_BitScanForward) #defineGECODE_SUPPORT_MSVC_32 #endif #ifdefined(_M_X64)||defined(_M_IA64) #pragmaintrinsic(_BitScanForward64) #defineGECODE_SUPPORT_MSVC_64 #endif #endif namespaceGecode{namespaceSupport{ classBitSetBase; classBitSetData{ friendclassBitSetBase; protected: #ifdefGECODE_SUPPORT_MSVC_64 typedefunsigned__int64Base; #else typedefunsignedlongintBase; #endif Basebits; staticconstunsignedintbpb= static_cast<unsignedint>(CHAR_BIT*sizeof(Base)); public: voidinit(boolset=false); staticunsignedintdata(unsignedints); booloperator ()(unsignedinti=0U)const; boolget(unsignedinti)const; voidset(unsignedinti); voidclear(unsignedinti); unsignedintnext(unsignedinti=0U)const; boolall(void)const; boolall(unsignedinti)const; boolnone(void)const; boolnone(unsignedinti)const; }; enumBitSetStatus{ BSS_NONE, BSS_ALL, BSS_SOME }; classBitSetBase{ protected: staticconstunsignedintbpb=BitSetData::bpb; unsignedintsz; BitSetData*data; bool_get(unsignedinti)const; void_set(unsignedinti); private: BitSetBase(constBitSetBase&); BitSetBase&operator=(constBitSetBase&); public: BitSetBase(void); template<classA> BitSetBase(A&a,unsignedints,boolset=false); template<classA> BitSetBase(A&a,constBitSetBase&bs); template<classA> voidinit(A&a,unsignedints,boolset=false); unsignedintsize(void)const; boolget(unsignedinti)const; voidset(unsignedinti); voidclear(unsignedinti); unsignedintnext(unsignedinti)const; BitSetStatusstatus(void)const; template<classA> voidresize(A&a,unsignedintn,boolset=false); template<classA> voiddispose(A&a); }; /* *Bitsetdata * */ forceinlinevoid BitSetData::init(boolset){ bits=set?~static_cast<Base>(0):static_cast<Base>(0); } forceinlineunsignedint BitSetData::data(unsignedints){ returns==0?0:((s-1)/bpb+1); } forceinlinebool BitSetData::operator ()(unsignedinti)const{ return(bits>>i)!=static_cast<Base>(0U); } forceinlinebool BitSetData::get(unsignedinti)const{ return(bits&(static_cast<Base>(1U)<<i))!=static_cast<Base>(0U); } forceinlinevoid BitSetData::set(unsignedinti){ bits|=(static_cast<Base>(1U)<<i); } forceinlinevoid BitSetData::clear(unsignedinti){ bits&=~(static_cast<Base>(1U)<<i); } forceinlineunsignedint BitSetData::next(unsignedinti)const{ assert(bits!=static_cast<Base>(0)); #ifdefined(GECODE_SUPPORT_MSVC_32) assert(bpb==32); unsignedlongintp; _BitScanForward(&p,bits>>i); returnstatic_cast<unsignedint>(p)+i; #elifdefined(GECODE_SUPPORT_MSVC_64) assert(bpb==64); unsignedlongintp; _BitScanForward64(&p,bits>>i); returnstatic_cast<unsignedint>(p)+i; #elifdefined(GECODE_HAS_BUILTIN_FFSL) if((bpb==32)||(bpb==64)){ intp=__builtin_ffsl(bits>>i); assert(p>0); returnstatic_cast<unsignedint>(p-1)+i; } #else while(!get(i))i++; returni; #endif } forceinlinebool BitSetData::all(void)const{ returnbits==~static_cast<Base>(0U); } forceinlinebool BitSetData::all(unsignedinti)const{ constBasemask=(static_cast<Base>(1U)<<i)-static_cast<Base>(1U); return(bits&mask)==mask; } forceinlinebool BitSetData::none(void)const{ returnbits==static_cast<Base>(0U); } forceinlinebool BitSetData::none(unsignedinti)const{ constBasemask=(static_cast<Base>(1U)<<i)-static_cast<Base>(1U); return(bits&mask)==static_cast<Base>(0U); } /* *Basicbitsets * */ forceinlinebool BitSetBase::_get(unsignedinti)const{ returndata[i/bpb].get(i%bpb); } forceinlinevoid BitSetBase::_set(unsignedinti){ data[i/bpb].set(i%bpb); } template<classA> void BitSetBase::resize(A&a,unsignedintn,boolset){ if(n>sz){ data=a.templaterealloc<BitSetData>(data,BitSetData::data(sz+1), BitSetData::data(n+1)); for(unsignedinti=BitSetData::data(sz)+1; i<BitSetData::data(n+1);i++){ data[i].init(set); } for(unsignedinti=(sz%bpb);i<bpb;i++) if(set) data[sz/bpb].set(i); else data[sz/bpb].clear(i); } sz=n;_set(sz); } template<classA> forceinlinevoid BitSetBase::dispose(A&a){ a.templatefree<BitSetData>(data,BitSetData::data(sz+1)); } forceinline BitSetBase::BitSetBase(void) :sz(0),data(NULL){} template<classA> forceinline BitSetBase::BitSetBase(A&a,unsignedints,boolset) :sz(s), data(a.templatealloc<BitSetData>(BitSetData::data(sz+1))){ for(unsignedinti=BitSetData::data(sz+1);i--;) data[i].init(set); //Setabitatpositionszassentinel(forefficientnext) _set(sz); } template<classA> forceinline BitSetBase::BitSetBase(A&a,constBitSetBase&bs) :sz(bs.sz), data(a.templatealloc<BitSetData>(BitSetData::data(sz+1))){ for(unsignedinti=BitSetData::data(sz+1);i--;) data[i]=bs.data[i]; //Setabitatpositionszassentinel(forefficientnext) _set(sz); } template<classA> forceinlinevoid BitSetBase::init(A&a,unsignedints,boolset){ assert((sz==0)&&(data==NULL)); sz=s;data=a.templatealloc<BitSetData>(BitSetData::data(sz+1)); for(unsignedinti=BitSetData::data(sz+1);i--;) data[i].init(set); //Setabitatpositionszassentinel(forefficientnext) _set(sz); } forceinlineunsignedint BitSetBase::size(void)const{ returnsz; } forceinlinebool BitSetBase::get(unsignedinti)const{ assert(i<sz); return_get(i); } forceinlinevoid BitSetBase::set(unsignedinti){ assert(i<sz); _set(i); } forceinlinevoid BitSetBase::clear(unsignedinti){ assert(i<sz); data[i/bpb].clear(i%bpb); } forceinlineunsignedint BitSetBase::next(unsignedinti)const{ assert(i<=sz); unsignedintpos=i/bpb; unsignedintbit=i%bpb; if(data[pos](bit)) returnpos*bpb+data[pos].next(bit); //Thesentinelbitguaranteesthatthisloopalwaysterminates do{ pos++; }while(!data[pos]()); returnpos*bpb+data[pos].next(); } forceinlineBitSetStatus BitSetBase::status(void)const{ unsignedintpos=sz/bpb; unsignedintbits=sz%bpb; if(pos>0){ if(data[0].all()){ for(unsignedinti=1;i<pos;i++) if(!data[i].all()) returnBSS_SOME; returndata[pos].all(bits)?BSS_ALL:BSS_SOME; }elseif(data[0].none()){ for(unsignedinti=1;i<pos;i++) if(!data[i].none()) returnBSS_SOME; returndata[pos].none(bits)?BSS_NONE:BSS_SOME; }else{ returnBSS_SOME; } } if(data[0].all(bits)) returnBSS_ALL; if(data[0].none(bits)) returnBSS_NONE; returnBSS_SOME; } }} #ifdefGECODE_SUPPORT_MSVC_32 #undefGECODE_SUPPORT_MSVC_32 #endif #ifdefGECODE_SUPPORT_MSVC_64 #undefGECODE_SUPPORT_MSVC_64 #endif //STATISTICS:support-any