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

303 lines
7.9 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Christian Schulte <schulte@gecode.org>
*
* Contributing authors:
* Guido Tack <tack@gecode.org>
*
* Copyright:
* Christian Schulte, 2004
* Guido Tack, 2004
*
* 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.
*
*/
namespace Gecode {
/**
* \brief Lists of ranges (intervals)
*
* This class implements a simple datastructure for storing sets of
* integers as lists of ranges (intervals). Memory is managed as
* space-allocated free lists.
*
* \ingroup FuncMemSpace
*/
class RangeList : public FreeList {
protected:
/// Minimum of range
int _min;
/// Maximum of range
int _max;
public:
/// \name Constructors
//@{
/// Default constructor (noop)
RangeList(void);
/// Initialize with minimum \a min and maximum \a max
RangeList(int min, int max);
/// Initialize with minimum \a min and maximum \a max and successor \a n
RangeList(int min, int max, RangeList* n);
//@}
/// \name Access
//@{
/// Return minimum
int min(void) const;
/// Return maximum
int max(void) const;
/// Return width (distance between maximum and minimum)
unsigned int width(void) const;
/// Return next element
RangeList* next(void) const;
/// Return pointer to next element
RangeList** nextRef(void);
//@}
/// \name Update
//@{
/// Set minimum to \a n
void min(int n);
/// Set maximum to \a n
void max(int n);
/// Set next range to \a n
void next(RangeList* n);
//@}
/// \name Iterator operations
//@{
/// Create rangelist \a r from range iterator \a i
template<class Iter>
static void copy(Space& home, RangeList*& r, Iter& i);
/// Overwrite rangelist \a r with ranges from range iterator \a i
template<class Iter>
static void overwrite(Space& home, RangeList*& r, Iter& i);
/// Insert (as union) ranges from iterator \a i into \a r
template<class I>
static void insert(Space& home, RangeList*& r, I& i);
//@}
/// \name Memory management
//@{
/// Free memory for all elements between this and \a l (inclusive)
void dispose(Space& home, RangeList* l);
/// Free memory for all elements reachable from this
void dispose(Space& home);
/// Allocate memory from space
static void* operator new(size_t s, Space& home);
/// Placement-new operator (noop)
static void* operator new(size_t s, void* p);
/// No-op (for exceptions)
static void operator delete(void*);
/// No-op (use dispose instead)
static void operator delete(void*, Space& home);
/// No-op (use dispose instead)
static void operator delete(void*, void*);
//@}
};
/*
* Range lists
*
*/
forceinline
RangeList::RangeList(void) {}
forceinline
RangeList::RangeList(int min, int max, RangeList* n)
: FreeList(n), _min(min), _max(max) {}
forceinline
RangeList::RangeList(int min, int max)
: _min(min), _max(max) {}
forceinline RangeList*
RangeList::next(void) const {
return static_cast<RangeList*>(FreeList::next());
}
forceinline RangeList**
RangeList::nextRef(void) {
return reinterpret_cast<RangeList**>(FreeList::nextRef());
}
forceinline void
RangeList::min(int n) {
_min = n;
}
forceinline void
RangeList::max(int n) {
_max = n;
}
forceinline void
RangeList::next(RangeList* n) {
FreeList::next(n);
}
forceinline int
RangeList::min(void) const {
return _min;
}
forceinline int
RangeList::max(void) const {
return _max;
}
forceinline unsigned int
RangeList::width(void) const {
return static_cast<unsigned int>(_max - _min + 1);
}
forceinline void
RangeList::operator delete(void*) {}
forceinline void
RangeList::operator delete(void*, Space&) {
GECODE_NEVER;
}
forceinline void
RangeList::operator delete(void*, void*) {
GECODE_NEVER;
}
forceinline void*
RangeList::operator new(size_t, Space& home) {
return home.fl_alloc<sizeof(RangeList)>();
}
forceinline void*
RangeList::operator new(size_t, void* p) {
return p;
}
forceinline void
RangeList::dispose(Space& home, RangeList* l) {
home.fl_dispose<sizeof(RangeList)>(this,l);
}
forceinline void
RangeList::dispose(Space& home) {
RangeList* l = this;
while (l->next() != nullptr)
l=l->next();
dispose(home,l);
}
template<class Iter>
forceinline void
RangeList::copy(Space& home, RangeList*& r, Iter& i) {
RangeList sentinel; sentinel.next(r);
RangeList* p = &sentinel;
while (i()) {
RangeList* n = new (home) RangeList(i.min(),i.max());
p->next(n); p=n; ++i;
}
p->next(nullptr);
r = sentinel.next();
}
template<class Iter>
forceinline void
RangeList::overwrite(Space& home, RangeList*& r, Iter& i) {
RangeList sentinel; sentinel.next(r);
RangeList* p = &sentinel;
RangeList* c = p->next();
while ((c != nullptr) && i()) {
c->min(i.min()); c->max(i.max());
p=c; c=c->next(); ++i;
}
if ((c == nullptr) && !i())
return;
if (c == nullptr) {
assert(i());
// New elements needed
do {
RangeList* n = new (home) RangeList(i.min(),i.max());
p->next(n); p=n; ++i;
} while (i());
} else {
// Dispose excess elements
while (c->next() != nullptr)
c=c->next();
p->next()->dispose(home,c);
}
p->next(nullptr);
r = sentinel.next();
}
template<class I>
forceinline void
RangeList::insert(Space& home, RangeList*& r, I& i) {
RangeList sentinel;
sentinel.next(r);
RangeList* p = &sentinel;
RangeList* c = p->next();
while ((c != nullptr) && i()) {
if ((c->max()+1 < i.min())) {
p=c; c=c->next();
} else if (i.max()+1 < c->min()) {
RangeList* n = new (home) RangeList(i.min(),i.max(),c);
p->next(n); p=n; ++i;
} else {
int min = std::min(c->min(),i.min());
int max = std::max(c->max(),i.max());
RangeList* f=c;
p=c; c=c->next(); ++i;
next:
if ((c != nullptr) && (c->min() <= max+1)) {
max = std::max(max,c->max());
p=c; c=c->next();
goto next;
}
if (i() && (i.min() <= max+1)) {
max = std::max(max,i.max());
++i;
goto next;
}
// Dispose now unused elements
if (f->next() != p)
f->next()->dispose(home,p);
f->min(min); f->max(max); f->next(c);
}
}
if (c == nullptr) {
while (i()) {
RangeList* n = new (home) RangeList(i.min(),i.max());
p->next(n); p=n;
++i;
}
p->next(nullptr);
}
r = sentinel.next();
}
}
// STATISTICS: kernel-other