/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Mikael Lagerkvist * * Contributing authors: * Linnea Ingmar * Christian Schulte * * Copyright: * Linnea Ingmar, 2017 * Mikael Lagerkvist, 2007 * Christian Schulte, 2007 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * 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. * */ #include #ifdef _MSC_VER #include #if defined(_M_IX86) #pragma intrinsic(_BitScanForward) #pragma intrinsic(__popcnt) #define GECODE_SUPPORT_MSVC_32 #endif #if defined(_M_X64) || defined(_M_IA64) #pragma intrinsic(_BitScanForward64) #pragma intrinsic(__popcnt64) #define GECODE_SUPPORT_MSVC_64 #endif #endif namespace Gecode { namespace Support { class RawBitSetBase; /// Date item for bitsets class BitSetData { friend class RawBitSetBase; protected: #if defined(GECODE_SUPPORT_MSVC_32) /// Basetype for bits typedef unsigned long int Base; #else /// Basetype for bits typedef unsigned long long int Base; #endif /// The bits Base bits; public: /// Bits per base static const unsigned int bpb = static_cast(CHAR_BIT * sizeof(Base)); /// Initialize with all bits set if \a setbits void init(bool setbits=false); /// Get number of data elements for \a s bits static unsigned int data(unsigned int s); /// Test wether any bit with position greater or equal to \a i is set bool operator ()(unsigned int i=0U) const; /// Access value at bit \a i bool get(unsigned int i) const; /// Set bit \a i void set(unsigned int i); /// Clear bit \a i void clear(unsigned int i); /// Return next set bit with position greater or equal to \a i (there must be a bit) unsigned int next(unsigned int i=0U) const; /// Whether all bits are set bool all(void) const; /// Whether all bits from bit 0 to bit \a i are set bool all(unsigned int i) const; /// Whether no bits are set bool none(void) const; /// Whether no bits from bit 0 to bit \a i are set bool none(unsigned int i) const; /// Return the number of bits set unsigned int ones(void) const; /// Return the number of bits not set unsigned int zeroes(void) const; /// Check whether exactly one bit is set bool one(void) const; /// Perform "and" with \a a void a(BitSetData a); /// Perform "and" with \a a for bits 0 to \a i void a(BitSetData a, unsigned int i); /// Return "and" of \a a and \a b static BitSetData a(BitSetData a, BitSetData b); /// Perform "or" with \a a void o(BitSetData a); /// Perform "or" with \a a for bits 0 to \a i void o(BitSetData a, unsigned int i); /// Return "or" of \a a and \a b static BitSetData o(BitSetData a, BitSetData b); /// Check if bits are the same as for \a a bool operator ==(BitSetData a) const; /// Check if bits are not the same as for \a a bool operator !=(BitSetData a) const; /// Invert all bits in \a b BitSetData operator ~(void) const; }; /// Status of a bitset enum BitSetStatus { BSS_NONE, ///< No bits set BSS_ALL, ///< All bits set BSS_SOME ///< Some but not all bits set }; /// Basic bitset support (without stored size information) class RawBitSetBase { protected: /// Bits per base static const unsigned int bpb = BitSetData::bpb; /// Stored bits BitSetData* data; private: /// Copy constructor (disabled) RawBitSetBase(const RawBitSetBase&); /// Assignment operator (disabled) RawBitSetBase& operator =(const RawBitSetBase&); public: /// Default constructor (yields empty set) RawBitSetBase(void); /// Initialize for \a sz bits and allocator \a a template RawBitSetBase(A& a, unsigned int sz, bool setbits=false); /// Copy from bitset \a bs with allocator \a a template RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs); /// Allocate for \a sz bits and allocator \a a (only after default constructor) template void allocate(A& a, unsigned int sz); /// Initialize for \a sz bits and allocator \a a (only after default constructor) template void init(A& a, unsigned int sz, bool setbits=false); /// Clear \a sz bits void clearall(unsigned int sz, bool setbits=false); /// Copy \a sz bits from \a bs void copy(unsigned int sz, const RawBitSetBase& bs); /// Access value at bit \a i bool get(unsigned int i) const; /// Set bit \a i void set(unsigned int i); /// Clear bit \a i void clear(unsigned int i); /// Return position greater or equal \a i of next set bit (\a i is allowed to be equal to size) unsigned int next(unsigned int i) const; /// Return status of bitset BitSetStatus status(unsigned int sz) const; /// Test whether all bits are set bool all(unsigned int sz) const; /// Test whether no bits are set bool none(unsigned int sz) const; /// Resize bitset from \a sz to \a n elememts template void resize(A& a, unsigned int sz, unsigned int n, bool setbits=false); /// Dispose memory for bit set template void dispose(A& a, unsigned int sz); }; /// Basic bitset support class BitSetBase : public RawBitSetBase { protected: /// Size of bitset (number of bits) unsigned int sz; private: /// Copy constructor (disabled) BitSetBase(const BitSetBase&); /// Assignment operator (disabled) BitSetBase& operator =(const BitSetBase&); public: /// Default constructor (yields empty set) BitSetBase(void); /// Initialize for \a s bits and allocator \a a template BitSetBase(A& a, unsigned int s, bool setbits=false); /// Copy from bitset \a bs with allocator \a a template BitSetBase(A& a, const BitSetBase& bs); /// Initialize for \a s bits and allocator \a a (only after default constructor) template void init(A& a, unsigned int s, bool setbits=false); /// Clear \a sz bits void clearall(bool setbits=false); /// Copy \a sz bits from \a bs void copy(const BitSetBase& bs); /// Return size of bitset (number of bits) unsigned int size(void) const; /// Access value at bit \a i bool get(unsigned int i) const; /// Set bit \a i void set(unsigned int i); /// Clear bit \a i void clear(unsigned int i); /// Return position greater or equal \a i of next set bit (\a i is allowed to be equal to size) unsigned int next(unsigned int i) const; /// Return status of bitset BitSetStatus status(void) const; /// Test whether all bits are set bool all(void) const; /// Test whether no bits are set bool none(void) const; /// Resize bitset to \a n elememts template void resize(A& a, unsigned int n, bool setbits=false); /// Dispose memory for bit set template void dispose(A& a); }; /* * Bitset data * */ forceinline void BitSetData::init(bool setbits) { bits = setbits ? ~static_cast(0) : static_cast(0); } forceinline unsigned int BitSetData::data(unsigned int s) { return s == 0 ? 0 : ((s-1) / bpb + 1); } forceinline bool BitSetData::operator ()(unsigned int i) const { return (bits >> i) != static_cast(0U); } forceinline bool BitSetData::get(unsigned int i) const { return (bits & (static_cast(1U) << i)) != static_cast(0U); } forceinline void BitSetData::set(unsigned int i) { bits |= (static_cast(1U) << i); } forceinline void BitSetData::clear(unsigned int i) { bits &= ~(static_cast(1U) << i); } forceinline unsigned int BitSetData::next(unsigned int i) const { assert(bits != static_cast(0)); #if defined(GECODE_SUPPORT_MSVC_32) assert(bpb == 32); unsigned long int p; _BitScanForward(&p,bits >> i); return static_cast(p)+i; #elif defined(GECODE_SUPPORT_MSVC_64) assert(bpb == 64); unsigned long int p; _BitScanForward64(&p,bits >> i); return static_cast(p)+i; #elif defined(GECODE_HAS_BUILTIN_FFSLL) if (bpb == 64) { int p = __builtin_ffsll(bits >> i); assert(p > 0); return static_cast(p-1)+i; } #else while (!get(i)) i++; return i; #endif } forceinline bool BitSetData::all(void) const { return bits == ~static_cast(0U); } forceinline bool BitSetData::all(unsigned int i) const { const Base mask = (static_cast(1U) << i) - static_cast(1U); return (bits & mask) == mask; } forceinline bool BitSetData::none(void) const { return bits == static_cast(0U); } forceinline bool BitSetData::none(unsigned int i) const { const Base mask = (static_cast(1U) << i) - static_cast(1U); return (bits & mask) == static_cast(0U); } forceinline unsigned int BitSetData::ones(void) const { #if defined(GECODE_SUPPORT_MSVC_32) assert(bpb == 32); return static_cast(__popcnt(bits)); #elif defined(GECODE_SUPPORT_MSVC_64) assert(bpb == 64); return static_cast(__popcnt64(bits)); #elif defined(GECODE_HAS_BUILTIN_POPCOUNTLL) if (bpb == 64) return static_cast(__builtin_popcountll(bits)); #else const unsigned long long int m1 = 0x5555555555555555; const unsigned long long int m2 = 0x3333333333333333; const unsigned long long int m4 = 0x0f0f0f0f0f0f0f0f; unsigned long long int b = bits; b -= (b >> 1) & m1; b = (b & m2) + ((b >> 2) & m2); b = (b + (b >> 4)) & m4; b += b >> 8; b += b >> 16; b += b >> 32; return static_cast(b & 0x7f); #endif } forceinline unsigned int BitSetData::zeroes(void) const { return bpb - ones(); } forceinline bool BitSetData::one(void) const { return (bits & (bits - static_cast(1U))) == static_cast(0U); } forceinline void BitSetData::a(BitSetData a) { bits &= a.bits; } forceinline void BitSetData::a(BitSetData a, unsigned int i) { const Base mask = (static_cast(1U) << i) - static_cast(1U); bits &= (a.bits & mask); } forceinline BitSetData BitSetData::a(BitSetData a, BitSetData b) { BitSetData ab; ab.bits = a.bits & b.bits; return ab; } forceinline void BitSetData::o(BitSetData a) { bits |= a.bits; } forceinline void BitSetData::o(BitSetData a, unsigned int i) { const Base mask = (static_cast(1U) << i) - static_cast(1U); bits |= (a.bits & mask); } forceinline BitSetData BitSetData::o(BitSetData a, BitSetData b) { BitSetData ab; ab.bits = a.bits | b.bits; return ab; } forceinline BitSetData BitSetData::operator ~(void) const { BitSetData iv; iv.bits = ~bits; return iv; } forceinline bool BitSetData::operator ==(BitSetData a) const { return bits == a.bits; } forceinline bool BitSetData::operator !=(BitSetData a) const { return bits != a.bits; } /* * Basic bit sets * */ forceinline bool RawBitSetBase::get(unsigned int i) const { return data[i / bpb].get(i % bpb); } forceinline void RawBitSetBase::set(unsigned int i) { data[i / bpb].set(i % bpb); } forceinline void RawBitSetBase::clear(unsigned int i) { data[i / bpb].clear(i % bpb); } template void RawBitSetBase::resize(A& a, unsigned int sz, unsigned int n, bool setbits) { if (n>sz) { data = a.template realloc(data,BitSetData::data(sz+1), BitSetData::data(n+1)); for (unsigned int i=BitSetData::data(sz)+1; i forceinline void RawBitSetBase::dispose(A& a, unsigned int sz) { a.template free(data,BitSetData::data(sz+1)); } forceinline RawBitSetBase::RawBitSetBase(void) : data(nullptr) {} template forceinline RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, bool setbits) : data(a.template alloc(BitSetData::data(sz+1))) { for (unsigned int i=0U; i forceinline RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs) : data(a.template alloc(BitSetData::data(sz+1))) { for (unsigned int i=0U; i forceinline void RawBitSetBase::allocate(A& a, unsigned int sz) { assert(data == nullptr); data=a.template alloc(BitSetData::data(sz+1)); } template forceinline void RawBitSetBase::init(A& a, unsigned int sz, bool setbits) { assert(data == nullptr); data=a.template alloc(BitSetData::data(sz+1)); for (unsigned int i=0U; i 0) { if (data[0].all()) { for (unsigned int i=1; i void BitSetBase::resize(A& a, unsigned int n, bool setbits) { RawBitSetBase::resize(a,sz,n,setbits); sz=n; } template forceinline void BitSetBase::dispose(A& a) { RawBitSetBase::dispose(a,sz); } forceinline BitSetBase::BitSetBase(void) : sz(0U) {} template forceinline BitSetBase::BitSetBase(A& a, unsigned int s, bool setbits) : RawBitSetBase(a,s,setbits), sz(s) {} template forceinline BitSetBase::BitSetBase(A& a, const BitSetBase& bs) : RawBitSetBase(a,bs.sz,bs), sz(bs.sz) {} template forceinline void BitSetBase::init(A& a, unsigned int s, bool setbits) { assert(sz == 0); RawBitSetBase::init(a,s,setbits); sz=s; } forceinline void BitSetBase::copy(const BitSetBase& bs) { assert(sz == bs.sz); RawBitSetBase::copy(sz,bs); } forceinline void BitSetBase::clearall(bool setbits) { RawBitSetBase::clearall(sz,setbits); } forceinline unsigned int BitSetBase::size(void) const { return sz; } forceinline bool BitSetBase::get(unsigned int i) const { assert(i < sz); return RawBitSetBase::get(i); } forceinline void BitSetBase::set(unsigned int i) { assert(i < sz); RawBitSetBase::set(i); } forceinline void BitSetBase::clear(unsigned int i) { assert(i < sz); RawBitSetBase::clear(i); } forceinline unsigned int BitSetBase::next(unsigned int i) const { assert(i <= sz); return RawBitSetBase::next(i); } forceinline BitSetStatus BitSetBase::status(void) const { return RawBitSetBase::status(sz); } forceinline bool BitSetBase::all(void) const { return RawBitSetBase::all(sz); } forceinline bool BitSetBase::none(void) const { return RawBitSetBase::none(sz); } }} #ifdef GECODE_SUPPORT_MSVC_32 #undef GECODE_SUPPORT_MSVC_32 #endif #ifdef GECODE_SUPPORT_MSVC_64 #undef GECODE_SUPPORT_MSVC_64 #endif // STATISTICS: support-any