1
0
This repository has been archived on 2025-03-06. You can view files and clone it, but cannot push or open issues or pull requests.
Jip J. Dekker 1d9faf38de Squashed 'software/gecode/' content from commit 313e8764
git-subtree-dir: software/gecode
git-subtree-split: 313e87646da4fc2752a70e83df16d993121a8e40
2021-06-16 14:02:33 +10:00

636 lines
18 KiB
C++
Executable File

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Mikael Lagerkvist <lagerkvist@gecode.org>
*
* Contributing authors:
* Linnea Ingmar <linnea.ingmar@hotmail.com>
* Christian Schulte <schulte@gecode.org>
*
* 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 <climits>
#ifdef _MSC_VER
#include <intrin.h>
#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<unsigned int>(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<class A>
RawBitSetBase(A& a, unsigned int sz, bool setbits=false);
/// Copy from bitset \a bs with allocator \a a
template<class A>
RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs);
/// Allocate for \a sz bits and allocator \a a (only after default constructor)
template<class A>
void allocate(A& a, unsigned int sz);
/// Initialize for \a sz bits and allocator \a a (only after default constructor)
template<class A>
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<class A>
void resize(A& a, unsigned int sz, unsigned int n, bool setbits=false);
/// Dispose memory for bit set
template<class A>
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<class A>
BitSetBase(A& a, unsigned int s, bool setbits=false);
/// Copy from bitset \a bs with allocator \a a
template<class A>
BitSetBase(A& a, const BitSetBase& bs);
/// Initialize for \a s bits and allocator \a a (only after default constructor)
template<class A>
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<class A>
void resize(A& a, unsigned int n, bool setbits=false);
/// Dispose memory for bit set
template<class A>
void dispose(A& a);
};
/*
* Bitset data
*
*/
forceinline void
BitSetData::init(bool setbits) {
bits = setbits ? ~static_cast<Base>(0) : static_cast<Base>(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<Base>(0U);
}
forceinline bool
BitSetData::get(unsigned int i) const {
return (bits & (static_cast<Base>(1U) << i)) != static_cast<Base>(0U);
}
forceinline void
BitSetData::set(unsigned int i) {
bits |= (static_cast<Base>(1U) << i);
}
forceinline void
BitSetData::clear(unsigned int i) {
bits &= ~(static_cast<Base>(1U) << i);
}
forceinline unsigned int
BitSetData::next(unsigned int i) const {
assert(bits != static_cast<Base>(0));
#if defined(GECODE_SUPPORT_MSVC_32)
assert(bpb == 32);
unsigned long int p;
_BitScanForward(&p,bits >> i);
return static_cast<unsigned int>(p)+i;
#elif defined(GECODE_SUPPORT_MSVC_64)
assert(bpb == 64);
unsigned long int p;
_BitScanForward64(&p,bits >> i);
return static_cast<unsigned int>(p)+i;
#elif defined(GECODE_HAS_BUILTIN_FFSLL)
if (bpb == 64) {
int p = __builtin_ffsll(bits >> i);
assert(p > 0);
return static_cast<unsigned int>(p-1)+i;
}
#else
while (!get(i)) i++;
return i;
#endif
}
forceinline bool
BitSetData::all(void) const {
return bits == ~static_cast<Base>(0U);
}
forceinline bool
BitSetData::all(unsigned int i) const {
const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
return (bits & mask) == mask;
}
forceinline bool
BitSetData::none(void) const {
return bits == static_cast<Base>(0U);
}
forceinline bool
BitSetData::none(unsigned int i) const {
const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(1U);
return (bits & mask) == static_cast<Base>(0U);
}
forceinline unsigned int
BitSetData::ones(void) const {
#if defined(GECODE_SUPPORT_MSVC_32)
assert(bpb == 32);
return static_cast<unsigned int>(__popcnt(bits));
#elif defined(GECODE_SUPPORT_MSVC_64)
assert(bpb == 64);
return static_cast<unsigned int>(__popcnt64(bits));
#elif defined(GECODE_HAS_BUILTIN_POPCOUNTLL)
if (bpb == 64)
return static_cast<unsigned int>(__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<unsigned int>(b & 0x7f);
#endif
}
forceinline unsigned int
BitSetData::zeroes(void) const {
return bpb - ones();
}
forceinline bool
BitSetData::one(void) const {
return (bits & (bits - static_cast<Base>(1U))) ==
static_cast<Base>(0U);
}
forceinline void
BitSetData::a(BitSetData a) {
bits &= a.bits;
}
forceinline void
BitSetData::a(BitSetData a, unsigned int i) {
const Base mask = (static_cast<Base>(1U) << i) - static_cast<Base>(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<Base>(1U) << i) - static_cast<Base>(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<class A>
void
RawBitSetBase::resize(A& a, unsigned int sz, unsigned int n, bool setbits) {
if (n>sz) {
data = a.template realloc<BitSetData>(data,BitSetData::data(sz+1),
BitSetData::data(n+1));
for (unsigned int i=BitSetData::data(sz)+1;
i<BitSetData::data(n+1); i++) {
data[i].init(setbits);
}
for (unsigned int i=(sz%bpb); i<bpb; i++)
if (setbits)
data[sz / bpb].set(i);
else
data[sz / bpb].clear(i);
}
set(n);
}
template<class A>
forceinline void
RawBitSetBase::dispose(A& a, unsigned int sz) {
a.template free<BitSetData>(data,BitSetData::data(sz+1));
}
forceinline
RawBitSetBase::RawBitSetBase(void)
: data(nullptr) {}
template<class A>
forceinline
RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, bool setbits)
: data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
data[i].init(setbits);
// Set a bit at position sz as sentinel (for efficient next)
set(sz);
}
template<class A>
forceinline
RawBitSetBase::RawBitSetBase(A& a, unsigned int sz, const RawBitSetBase& bs)
: data(a.template alloc<BitSetData>(BitSetData::data(sz+1))) {
for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
data[i] = bs.data[i];
// Set a bit at position sz as sentinel (for efficient next)
set(sz);
}
template<class A>
forceinline void
RawBitSetBase::allocate(A& a, unsigned int sz) {
assert(data == nullptr);
data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
}
template<class A>
forceinline void
RawBitSetBase::init(A& a, unsigned int sz, bool setbits) {
assert(data == nullptr);
data=a.template alloc<BitSetData>(BitSetData::data(sz+1));
for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
data[i].init(setbits);
// Set a bit at position sz as sentinel (for efficient next)
set(sz);
}
forceinline void
RawBitSetBase::copy(unsigned int sz, const RawBitSetBase& bs) {
for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
data[i] = bs.data[i];
}
forceinline void
RawBitSetBase::clearall(unsigned int sz, bool setbits) {
for (unsigned int i=0U; i<BitSetData::data(sz+1); i++)
data[i].init(setbits);
}
forceinline unsigned int
RawBitSetBase::next(unsigned int i) const {
unsigned int pos = i / bpb;
unsigned int bit = i % bpb;
if (data[pos](bit))
return pos * bpb + data[pos].next(bit);
// The sentinel bit guarantees that this loop always terminates
do {
pos++;
} while (!data[pos]());
return pos * bpb + data[pos].next();
}
forceinline BitSetStatus
RawBitSetBase::status(unsigned int sz) const {
unsigned int pos = sz / bpb;
unsigned int bits = sz % bpb;
if (pos > 0) {
if (data[0].all()) {
for (unsigned int i=1; i<pos; i++)
if (!data[i].all())
return BSS_SOME;
return data[pos].all(bits) ? BSS_ALL : BSS_SOME;
} else if (data[0].none()) {
for (unsigned int i=1; i<pos; i++)
if (!data[i].none())
return BSS_SOME;
return data[pos].none(bits) ? BSS_NONE : BSS_SOME;
} else {
return BSS_SOME;
}
}
if (data[0].all(bits))
return BSS_ALL;
if (data[0].none(bits))
return BSS_NONE;
return BSS_SOME;
}
forceinline bool
RawBitSetBase::all(unsigned int sz) const {
return status(sz) == BSS_ALL;
}
forceinline bool
RawBitSetBase::none(unsigned int sz) const {
return status(sz) == BSS_NONE;
}
template<class A>
void
BitSetBase::resize(A& a, unsigned int n, bool setbits) {
RawBitSetBase::resize(a,sz,n,setbits); sz=n;
}
template<class A>
forceinline void
BitSetBase::dispose(A& a) {
RawBitSetBase::dispose(a,sz);
}
forceinline
BitSetBase::BitSetBase(void)
: sz(0U) {}
template<class A>
forceinline
BitSetBase::BitSetBase(A& a, unsigned int s, bool setbits)
: RawBitSetBase(a,s,setbits), sz(s) {}
template<class A>
forceinline
BitSetBase::BitSetBase(A& a, const BitSetBase& bs)
: RawBitSetBase(a,bs.sz,bs), sz(bs.sz) {}
template<class A>
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