/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * Guido Tack * * Contributing authors: * Gregory Crosswhite * * Copyright: * Gregory Crosswhite, 2011 * Christian Schulte, 2003 * Guido Tack, 2004 * * Last modified: * $Date: 2011-08-18 20:10:04 +1000 (Thu, 18 Aug 2011) $ by $Author: tack $ * $Revision: 12313 $ * * 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 #include #include #include namespace Gecode { template class VarArray; template class VarArgArray; /** \brief Traits of arrays in %Gecode * * This class collects the traits of an array in Gecode. * The traits used are the following. * - typedef Type StorageType where \c Type is the type * of an appropriate storage type for this array. * - typedef Type ValueType where \c Type is the type * of the elements of this array. * - typedef Type ArgsType where \c Type is the type * of the appropriate Args-array type (e.g., \c BoolVarArgs if \c A is * \c BoolVarArray). */ template class ArrayTraits {}; /** * \brief %Variable arrays * * %Variable arrays store variables. They are typically used * for storing the variables being part of a solution. * * Never use them for temporary purposes, use argument arrays * instead. * * %Variable arrays can be enlarged dynamically. For memory efficiency, the * initial array is allocated in the space. When adding variables, it is * automatically resized and allocated on the heap. * * \ingroup TaskVar */ template class VarArray { protected: /// Number of variables (size) int n; /// Array of variables Var* x; public: /// \name Associated types //@{ /// Type of the variable stored in this array typedef Var value_type; /// Type of a reference to the value type typedef Var& reference; /// Type of a constant reference to the value type typedef const Var& const_reference; /// Type of a pointer to the value type typedef Var* pointer; /// Type of a read-only pointer to the value type typedef const Var* const_pointer; /// Type of the iterator used to iterate through this array's elements typedef Var* iterator; /// Type of the iterator used to iterate read-only through this array's elements typedef const Var* const_iterator; /// Type of the iterator used to iterate backwards through this array's elements typedef std::reverse_iterator reverse_iterator; /// Type of the iterator used to iterate backwards and read-only through this array's elements typedef std::reverse_iterator const_reverse_iterator; //@} //@{ /// \name Constructors and initialization //@{ /// Default constructor (array of size 0) VarArray(void); /// Allocate array with \a m variables VarArray(Space& home, int m); /// Initialize from variable argument array \a a (copy elements) VarArray(Space& home, const VarArgArray&); /// Initialize from variable array \a a (share elements) VarArray(const VarArray& a); /// Initialize from variable array \a a (share elements) const VarArray& operator =(const VarArray& a); //@} /// \name Array size //@{ /// Return size of array (number of elements) int size(void) const; //@} /// \name Array elements //@{ /// Return variable at position \a i Var& operator [](int i); /// Return variable at position \a i const Var& operator [](int i) const; /** Return slice \f$y\f$ of length at most \a n such that forall \f$0\leq i >::ArgsType slice(int start, int inc=1, int n=-1); //@} /// \name Array iteration //@{ /// Return an iterator at the beginning of the array iterator begin(void); /// Return a read-only iterator at the beginning of the array const_iterator begin(void) const; /// Return an iterator past the end of the array iterator end(void); /// Return a read-only iterator past the end of the array const_iterator end(void) const; /// Return a reverse iterator at the end of the array reverse_iterator rbegin(void); /// Return a reverse and read-only iterator at the end of the array const_reverse_iterator rbegin(void) const; /// Return a reverse iterator past the beginning of the array reverse_iterator rend(void); /// Return a reverse and read-only iterator past the beginning of the array const_reverse_iterator rend(void) const; //@} /// Test if all variables are assigned bool assigned(void) const; /// \name Cloning //@{ /** * \brief Update array to be a clone of array \a a * * If \a share is true, sharing is retained for all shared * data structures. Otherwise, for each of them an independent * copy is created. */ void update(Space&, bool share, VarArray& a); //@} private: static void* operator new(size_t); static void operator delete(void*,size_t); }; /** Concatenate \a x and \a y and return result * \relates VarArray */ template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const VarArgArray& y); /** Concatenate \a x and \a y and return result * \relates VarArray */ template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const VarArray& y); /** Concatenate \a x and \a y and return result * \relates VarArray */ template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const VarArray& y); /** Concatenate \a x and \a y and return result * \relates VarArray */ template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const T& y); /** Concatenate \a x and \a y and return result * \relates VarArray */ template typename ArrayTraits >::ArgsType operator +(const T& x, const VarArray& y); /** * \brief View arrays * * View arrays store views. They are typically used for storing the * views with which propagators and branchers compute. * \ingroup TaskActor */ template class ViewArray { private: /// Number of views (size) int n; /// Views View* x; /// Sort order for views template class ViewLess { public: bool operator ()(const X&, const X&); }; /// Sort \a n views \a x according to \a ViewLess static void sort(View* x, int n); public: /// \name Associated types //@{ /// Type of the view stored in this array typedef View value_type; /// Type of a reference to the value type typedef View& reference; /// Type of a constant reference to the value type typedef const View& const_reference; /// Type of a pointer to the value type typedef View* pointer; /// Type of a read-only pointer to the value type typedef const View* const_pointer; /// Type of the iterator used to iterate through this array's elements typedef View* iterator; /// Type of the iterator used to iterate read-only through this array's elements typedef const View* const_iterator; /// Type of the iterator used to iterate backwards through this array's elements typedef std::reverse_iterator reverse_iterator; /// Type of the iterator used to iterate backwards and read-only through this array's elements typedef std::reverse_iterator const_reverse_iterator; //@} /// \name Constructors and initialization //@{ /// Default constructor (array of size 0) ViewArray(void); /// Allocate array with \a m views ViewArray(Space& home, int m); /// Allocate array with \a m views ViewArray(Region& r, int m); /// Initialize from view array \a a (share elements) ViewArray(const ViewArray& a); /// Initialize from view array \a a (copy elements) ViewArray(Space& home, const ViewArray& a); /// Initialize from view array \a a (copy elements) ViewArray(Region& r, const ViewArray& a); /// Initialize from view array \a a (share elements) const ViewArray& operator =(const ViewArray& a); /** * \brief Initialize from variable argument array \a a (copy elements) * * Note that the view type \a View must provide a constructor * for the associated \a Var type. */ template ViewArray(Space& home, const VarArgArray& a) : n(a.size()) { // This may not be in the hpp file (to satisfy the MS compiler) if (n>0) { x = home.alloc(n); for (int i=n; i--; ) x[i]=a[i]; } else { x = NULL; } } /** * \brief Initialize from variable argument array \a a (copy elements) * * Note that the view type \a View must provide a constructor * for the associated \a Var type. */ template ViewArray(Region& r, const VarArgArray& a) : n(a.size()) { // This may not be in the hpp file (to satisfy the MS compiler) if (n>0) { x = r.alloc(n); for (int i=n; i--; ) x[i]=a[i]; } else { x = NULL; } } //@} /// \name Array size //@{ /// Return size of array (number of elements) int size(void) const; /// Decrease size of array (number of elements) void size(int n); //@} /// \name Array elements //@{ /// Return view at position \a i View& operator [](int i); /// Return view at position \a i const View& operator [](int i) const; //@} /// \name Array iteration //@{ /// Return an iterator at the beginning of the array iterator begin(void); /// Return a read-only iterator at the beginning of the array const_iterator begin(void) const; /// Return an iterator past the end of the array iterator end(void); /// Return a read-only iterator past the end of the array const_iterator end(void) const; /// Return a reverse iterator at the end of the array reverse_iterator rbegin(void); /// Return a reverse and read-only iterator at the end of the array const_reverse_iterator rbegin(void) const; /// Return a reverse iterator past the beginning of the array reverse_iterator rend(void); /// Return a reverse and read-only iterator past the beginning of the array const_reverse_iterator rend(void) const; //@} /// \name Dependencies //@{ /** * \brief Subscribe propagator \a p with propagation condition \a pc to variable * * In case \a process is false, the propagator is just subscribed but * not processed for execution (this must be used when creating * subscriptions during propagation). */ void subscribe(Space& home, Propagator& p, PropCond pc, bool process=true); /// Cancel subscription of propagator \a p with propagation condition \a pc to all views void cancel(Space& home, Propagator& p, PropCond pc); /// Subscribe advisor \a a to variable void subscribe(Space& home, Advisor& a); /// Cancel subscription of advisor \a a void cancel(Space& home, Advisor& a); //@} /// \name Cloning //@{ /** * \brief Update array to be a clone of array \a a * * If \a share is true, sharing is retained for all shared * data structures. Otherwise, for each of them an independent * copy is created. */ void update(Space&, bool share, ViewArray& a); //@} /// \name Moving elements //@{ /// Move view from position 0 to position \a i (shift elements to the left) void move_fst(int i); /// Move view from position \c size()-1 to position \a i (truncate array by one) void move_lst(int i); /** \brief Move view from position 0 to position \a i (shift elements to the left) * * Before moving, cancel subscription of propagator \a p with * propagation condition \a pc to view at position \a i. */ void move_fst(int i, Space& home, Propagator& p, PropCond pc); /** \brief Move view from position \c size()-1 to position \a i (truncate array by one) * * Before moving, cancel subscription of propagator \a p with * propagation condition \a pc to view at position \a i. */ void move_lst(int i, Space& home, Propagator& p, PropCond pc); /** \brief Move view from position 0 to position \a i (shift elements to the left) * * Before moving, cancel subscription of advisor \a a * to view at position \a i. */ void move_fst(int i, Space& home, Advisor& a); /** \brief Move view from position \c size()-1 to position \a i (truncate array by one) * * Before moving, cancel subscription of advisor \a a to view * at position \a i. */ void move_lst(int i, Space& home, Advisor& a); //@} /// \name Dropping elements //@{ /// Drop views from positions 0 to \a i-1 from array void drop_fst(int i); /// Drop views from positions \a i+1 to \c size()-1 from array void drop_lst(int i); /** \brief Drop views from positions 0 to \a i-1 from array * * Before moving, cancel subscription of propagator \a p with * propagation condition \a pc to views at positions 0 to \a i-1. */ void drop_fst(int i, Space& home, Propagator& p, PropCond pc); /** \brief Drop assigned views from positions \a i+1 to \c size()-1 from array * * Before moving, cancel subscription of propagator \a p with * propagation condition \a pc to views at positions \a i+1 to * \c size()-1. */ void drop_lst(int i, Space& home, Propagator& p, PropCond pc); /** \brief Drop views from positions 0 to \a i-1 from array * * Before moving, cancel subscription of advisor \a a to views at * positions 0 to \a i-1. */ void drop_fst(int i, Space& home, Advisor& a); /** \brief Drop assigned views from positions \a i+1 to \c size()-1 from array * * Before moving, cancel subscription of advisor \a a to views at * positions \a i+1 to \c size()-1. */ void drop_lst(int i, Space& home, Advisor& a); //@} /// Test if all variables are assigned bool assigned(void) const; /// \name View equality //@{ /** * \brief Test whether array has multiple occurence of the same view * * Note that assigned views are ignored. */ bool same(const Space& home) const; /** * \brief Test whether array contains a view being the same as \a y * * Note that assigned views are ignored. */ bool same(const Space& home, const View& y) const; /// Remove all duplicate views from array (changes element order) void unique(const Space& home); //@} /// \name View sharing //@{ /** * \brief Test whether array contains shared views * * Note that assigned views are ignored. */ bool shared(const Space& home) const; /** * \brief Test whether array contains a view being shared with \a y * * Note that assigned views are ignored. */ template bool shared(const Space& home, const ViewY& y) const; /** * \brief Test whether array together with array \a y contains shared views * * Note that assigned views are ignored. */ template bool shared(const Space& home, const ViewArray& y) const; //@} private: static void* operator new(size_t); static void operator delete(void*,size_t); }; /** * \brief Base-class for argument arrays * * Argument arrays are used as convenient mechanism of passing arguments * when calling functions as they combine both the size and the elements * of an array. For a small number of elements, memory is allocated by * creating an argument array object. Otherwise the memory is allocated * from the heap. * * This base-class is not to be used directly, use PrimArgArray for * argument arrays of primitive types, VarArgArray for argument * arrays storing variables, and ArgArray for any other type. */ template class ArgArrayBase { protected: /// Number of elements int n; /// Allocated size of the array int capacity; /// Element array T* a; /// How many elements are possible inside array static const int onstack_size = 16; /// In-array storage for elements T onstack[onstack_size]; /// Allocate memory for \a n elements T* allocate(int n); /// Resize to hold at least \a i additional elements void resize(int i); /// Return this array concatenated with \a x template A concat(const ArgArrayBase& x) const; /// Return this array concatenated with \a x template A concat(const T& x) const; /// Insert a new element \a x at the end of the array (increase size by 1) template A& append(const T& x); /// Append \a x to the end of the array template A& append(const ArgArrayBase& x); /** Return slice \f$y\f$ of length at most \a n such that forall \f$0\leq i A slice(int start, int inc=1, int n=-1); public: /// \name Associated types //@{ /// Type of the view stored in this array typedef T value_type; /// Type of a reference to the value type typedef T& reference; /// Type of a constant reference to the value type typedef const T& const_reference; /// Type of a pointer to the value type typedef T* pointer; /// Type of a read-only pointer to the value type typedef const T* const_pointer; /// Type of the iterator used to iterate through this array's elements typedef T* iterator; /// Type of the iterator used to iterate read-only through this array's elements typedef const T* const_iterator; /// Type of the iterator used to iterate backwards through this array's elements typedef std::reverse_iterator reverse_iterator; /// Type of the iterator used to iterate backwards and read-only through this array's elements typedef std::reverse_iterator const_reverse_iterator; //@} /// \name Constructors and initialization //@{ /// Allocate empty array ArgArrayBase(void); /// Allocate array with \a n elements explicit ArgArrayBase(int n); /// Initialize from argument array \a a (copy elements) ArgArrayBase(const ArgArrayBase& a); /// Initialize from view array \a a (copy elements) const ArgArrayBase& operator =(const ArgArrayBase& a); //@} /// \name Array size //@{ /// Return size of array (number of elements) int size(void) const; //@} /// \name Array elements //@{ /// Return element at position \a i T& operator [](int i); /// Return element at position \a i const T& operator [](int i) const; //@} /// \name Array iteration //@{ /// Return an iterator at the beginning of the array iterator begin(void); /// Return a read-only iterator at the beginning of the array const_iterator begin(void) const; /// Return an iterator past the end of the array iterator end(void); /// Return a read-only iterator past the end of the array const_iterator end(void) const; /// Return a reverse iterator at the end of the array reverse_iterator rbegin(void); /// Return a reverse and read-only iterator at the end of the array const_reverse_iterator rbegin(void) const; /// Return a reverse iterator past the beginning of the array reverse_iterator rend(void); /// Return a reverse and read-only iterator past the beginning of the array const_reverse_iterator rend(void) const; //@} /// \name Destructor //@{ /// Destructor ~ArgArrayBase(void); //@} private: static void* operator new(size_t); static void operator delete(void*,size_t); }; template class PrimArgArray; /** Concatenate \a x and \a y and return result * \relates PrimArgArray */ template typename ArrayTraits >::ArgsType operator +(const PrimArgArray& x, const PrimArgArray& y); /** Concatenate \a x and \a y and return result * \relates PrimArgArray */ template typename ArrayTraits >::ArgsType operator +(const PrimArgArray& x, const T& y); /** Concatenate \a x and \a y and return result * \relates PrimArgArray */ template typename ArrayTraits >::ArgsType operator +(const T& x, const PrimArgArray& y); /** * \brief Argument array for primtive types * * Argument arrays are used as convenient mechanism of passing arguments * when calling functions as they combine both the size and the elements * of an array. For a small number of elements, memory is allocated by * creating an argument array object. Otherwise the memory is allocated * from the heap. * * \ingroup TaskVar */ template class PrimArgArray : public ArgArrayBase { protected: using ArgArrayBase::a; public: using ArgArrayBase::size; /// \name Constructors and initialization //@{ /// Allocate empty array PrimArgArray(void); /// Allocate array with \a n elements explicit PrimArgArray(int n); /// Allocate array with \a n elements and initialize with \a e0, ... PrimArgArray(int n, T e0, ...); /// Allocate array with \a n elements and initialize with elements from array \a e PrimArgArray(int n, const T* e); /// Initialize from primitive argument array \a a (copy elements) PrimArgArray(const PrimArgArray& a); //@} /// \name Array elements //@{ /** Return slice \f$y\f$ of length at most \a n such that forall \f$0\leq i >::ArgsType slice(int start, int inc=1, int n=-1); //@} /// \name Appending elements //@{ /// Insert a new element \a x at the end of the array (increase size by 1) typename ArrayTraits >::ArgsType& operator <<(const T& x); /// Append \a x to the end of the array typename ArrayTraits >::ArgsType& operator <<(const PrimArgArray& x); //@} friend typename ArrayTraits >::ArgsType operator + <>(const PrimArgArray& x, const PrimArgArray& y); friend typename ArrayTraits >::ArgsType operator + <>(const PrimArgArray& x, const T& y); friend typename ArrayTraits >::ArgsType operator + <>(const T& x, const PrimArgArray& y); }; template class ArgArray; /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const ArgArray& x, const ArgArray& y); /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const ArgArray& x, const T& y); /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const T& x, const ArgArray& y); /** * \brief Argument array for non-primitive types * * Argument arrays are used as convenient mechanism of passing arguments * when calling functions as they combine both the size and the elements * of an array. For a small number of elements, memory is allocated by * creating an argument array object. Otherwise the memory is allocated * from the heap. * * \ingroup TaskVar */ template class ArgArray : public ArgArrayBase { protected: using ArgArrayBase::a; public: using ArgArrayBase::size; /// \name Constructors and initialization //@{ /// Allocate empty array ArgArray(void); /// Allocate array with \a n elements explicit ArgArray(int n); /// Allocate array with \a n elements and initialize with elements from array \a e ArgArray(int n, const T* e); /// Initialize from primitive argument array \a a (copy elements) ArgArray(const ArgArray& a); //@} /// \name Array elements //@{ /// Return slice \f$y\f$ of length \a n such that forall \f$0\leq i >::ArgsType slice(int start, int inc=1, int n=-1); //@} /// \name Appending elements //@{ /// Insert a new element \a x at the end of the array (increase size by 1) typename ArrayTraits >::ArgsType& operator <<(const T& x); /// Append \a x to the end of the array typename ArrayTraits >::ArgsType& operator <<(const ArgArray& x); //@} friend typename ArrayTraits >::ArgsType operator + <>(const ArgArray& x, const ArgArray& y); friend typename ArrayTraits >::ArgsType operator + <>(const ArgArray& x, const T& y); friend typename ArrayTraits >::ArgsType operator + <>(const T& x, const ArgArray& y); }; template class VarArgArray; /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const VarArgArray& y); /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const Var& y); /** Concatenate \a x and \a y and return result * \relates ArgArray */ template typename ArrayTraits >::ArgsType operator +(const Var& x, const VarArgArray& y); /** * \brief Argument array for variables * * Argument arrays are used as convenient mechanism of passing arguments * when calling functions as they combine both the size and the elements * of an array. For a small number of elements, memory is allocated by * creating an argument array object. Otherwise the memory is allocated * from the heap. * * \ingroup TaskVar */ template class VarArgArray : public ArgArrayBase { protected: using ArgArrayBase::a; using ArgArrayBase::n; /// Sort order for variables class VarLess { public: bool operator ()(const Var&, const Var&); }; public: using ArgArrayBase::size; /// \name Constructors and initialization //@{ /// Allocate empty array VarArgArray(void); /// Allocate array with \a n elements explicit VarArgArray(int n); /// Initialize from variable argument array \a a (copy elements) VarArgArray(const VarArgArray& a); /// Initialize from variable array \a a (copy elements) VarArgArray(const VarArray& a); //@} /// \name Array elements //@{ /// Return slice \f$y\f$ of length \a n such that forall \f$0\leq i >::ArgsType slice(int start, int inc=1, int n=-1); //@} /// \name Appending elements //@{ /// Insert a new element \a x at the end of the array (increase size by 1) typename ArrayTraits >::ArgsType& operator <<(const Var& x); /// Append \a x to the end of the array typename ArrayTraits >::ArgsType& operator <<(const VarArgArray& x); //@} /// Test if all variables are assigned bool assigned(void) const; friend typename ArrayTraits >::ArgsType operator + <>(const VarArgArray& x, const VarArgArray& y); friend typename ArrayTraits >::ArgsType operator + <>(const VarArgArray& x, const Var& y); friend typename ArrayTraits >::ArgsType operator + <>(const Var& x, const VarArgArray& y); /// \name Variable equality //@{ /** * \brief Test whether array contains same variable multiply * * Note that assigned variables are ignored. */ bool same(const Space& home) const; /** * \brief Test whether array contains variable \a y * * Note that assigned variables are ignored. */ bool same(const Space& home, const Var& y) const; /** * \brief Test whether all elements from array and \a y contains same variable multiply * * Note that assigned variables are ignored. */ bool same(const Space& home, const VarArgArray& y) const; //@} }; /** * \brief Print array elements enclosed in curly brackets * \relates VarArray */ template std::basic_ostream& operator <<(std::basic_ostream& os, const VarArray& x); /** * \brief Print array elements enclosed in curly brackets * \relates ViewArray */ template std::basic_ostream& operator <<(std::basic_ostream& os, const ViewArray& x); /** * \brief Print array elements enclosed in curly brackets * \relates ArgArrayBase */ template std::basic_ostream& operator <<(std::basic_ostream& os, const ArgArrayBase& x); /* * Implementation * */ /* * Variable arrays * * These arrays are usually allocated in the space, but if they are resized, * the new array is allocated on the heap. The size (n) and capacity show * where the array is allocated: it is in the space if and only if * n==capacity. * */ template forceinline VarArray::VarArray(void) : n(0), x(NULL) {} template forceinline VarArray::VarArray(Space& home, int n0) : n(n0) { // Allocate from space x = (n>0) ? home.alloc(n) : NULL; } template forceinline VarArray::VarArray(const VarArray& a) { n = a.n; x = a.x; } template inline const VarArray& VarArray::operator =(const VarArray& a) { n = a.n; x = a.x; return *this; } template forceinline int VarArray::size(void) const { return n; } template forceinline Var& VarArray::operator [](int i) { assert((i >= 0) && (i < size())); return x[i]; } template forceinline const Var& VarArray::operator [](int i) const { assert((i >= 0) && (i < size())); return x[i]; } template typename ArrayTraits >::ArgsType VarArray::slice(int start, int inc, int maxN) { assert(n==0 || start < n); if (n==0 || maxN<0) maxN = n; int s; if (inc == 0) s = n-start; else if (inc > 0) s = (n-start)/inc + ((n-start) % inc == 0 ? 0 : 1); else s = (start+1)/-inc + ((start+1) % -inc == 0 ? 0 : 1); typename ArrayTraits >::ArgsType r(std::min(maxN,s)); for (int i=0; i forceinline typename VarArray::iterator VarArray::begin(void) { return x; } template forceinline typename VarArray::const_iterator VarArray::begin(void) const { return x; } template forceinline typename VarArray::iterator VarArray::end(void) { return x+n; } template forceinline typename VarArray::const_iterator VarArray::end(void) const { return x+n; } template forceinline typename VarArray::reverse_iterator VarArray::rbegin(void) { return reverse_iterator(x+n); } template forceinline typename VarArray::const_reverse_iterator VarArray::rbegin(void) const { return const_reverse_iterator(x+n); } template forceinline typename VarArray::reverse_iterator VarArray::rend(void) { return reverse_iterator(x); } template forceinline typename VarArray::const_reverse_iterator VarArray::rend(void) const { return const_reverse_iterator(x); } template forceinline void VarArray::update(Space& home, bool share, VarArray& a) { n = a.n; if (n > 0) { x = home.alloc(n); for (int i = n; i--;) x[i].update(home, share, a.x[i]); } else { x = NULL; } } template forceinline bool VarArray::assigned(void) const { for (int i = n; i--;) if (!x[i].assigned()) return false; return true; } template void* VarArray::operator new(size_t) { return NULL; } template void VarArray::operator delete(void*,size_t) { } template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const VarArray& y) { typename ArrayTraits >::ArgsType r(x.size()+y.size()); for (int i=x.size(); i--;) r[i] = x[i]; for (int i=y.size(); i--;) r[x.size()+i] = y[i]; return r; } template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const VarArgArray& y) { typename ArrayTraits >::ArgsType r(x.size()+y.size()); for (int i=x.size(); i--;) r[i] = x[i]; for (int i=y.size(); i--;) r[x.size()+i] = y[i]; return r; } template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const VarArray& y) { typename ArrayTraits >::ArgsType r(x.size()+y.size()); for (int i=x.size(); i--;) r[i] = x[i]; for (int i=y.size(); i--;) r[x.size()+i] = y[i]; return r; } template typename ArrayTraits >::ArgsType operator +(const VarArray& x, const Var& y) { typename ArrayTraits >::ArgsType r(x.size()+1); for (int i=x.size(); i--;) r[i] = x[i]; r[x.size()] = y; return r; } template typename ArrayTraits >::ArgsType operator +(const Var& x, const VarArray& y) { typename ArrayTraits >::ArgsType r(y.size()+1); r[0] = x; for (int i=y.size(); i--;) r[1+i] = y[i]; return r; } /* * View arrays * */ template forceinline ViewArray::ViewArray(void) : n(0), x(NULL) {} template forceinline ViewArray::ViewArray(Space& home, int n0) : n(n0) { x = (n>0) ? home.alloc(n) : NULL; } template forceinline ViewArray::ViewArray(Region& r, int n0) : n(n0) { x = (n>0) ? r.alloc(n) : NULL; } template ViewArray::ViewArray(Space& home, const ViewArray& a) : n(a.size()) { if (n>0) { x = home.alloc(n); for (int i = n; i--; ) x[i] = a[i]; } else { x = NULL; } } template ViewArray::ViewArray(Region& r, const ViewArray& a) : n(a.size()) { if (n>0) { x = r.alloc(n); for (int i = n; i--; ) x[i] = a[i]; } else { x = NULL; } } template forceinline ViewArray::ViewArray(const ViewArray& a) : n(a.n), x(a.x) {} template forceinline const ViewArray& ViewArray::operator =(const ViewArray& a) { n = a.n; x = a.x; return *this; } template forceinline int ViewArray::size(void) const { return n; } template forceinline void ViewArray::size(int n0) { n = n0; } template forceinline View& ViewArray::operator [](int i) { assert((i >= 0) && (i < size())); return x[i]; } template forceinline const View& ViewArray::operator [](int i) const { assert((i >= 0) && (i < size())); return x[i]; } template forceinline typename ViewArray::iterator ViewArray::begin(void) { return x; } template forceinline typename ViewArray::const_iterator ViewArray::begin(void) const { return x; } template forceinline typename ViewArray::iterator ViewArray::end(void) { return x+n; } template forceinline typename ViewArray::const_iterator ViewArray::end(void) const { return x+n; } template forceinline typename ViewArray::reverse_iterator ViewArray::rbegin(void) { return reverse_iterator(x+n); } template forceinline typename ViewArray::const_reverse_iterator ViewArray::rbegin(void) const { return const_reverse_iterator(x+n); } template forceinline typename ViewArray::reverse_iterator ViewArray::rend(void) { return reverse_iterator(x); } template forceinline typename ViewArray::const_reverse_iterator ViewArray::rend(void) const { return const_reverse_iterator(x); } template forceinline void ViewArray::move_fst(int i) { x[i]=x[0]; x++; n--; } template forceinline void ViewArray::move_lst(int i) { n--; x[i]=x[n]; } template forceinline void ViewArray::drop_fst(int i) { assert(i>=0); x += i; n -= i; } template forceinline void ViewArray::drop_lst(int i) { assert(i forceinline void ViewArray::move_fst(int i, Space& home, Propagator& p, PropCond pc) { // Move x[0] to x[i] x[i].cancel(home,p,pc); x[i]=x[0]; x++; n--; } template forceinline void ViewArray::move_lst(int i, Space& home, Propagator& p, PropCond pc) { // Move x[n-1] to x[i] x[i].cancel(home,p,pc); n--; x[i]=x[n]; } template void ViewArray::drop_fst(int i, Space& home, Propagator& p, PropCond pc) { // Drop elements from 0..i-1 assert(i>=0); for (int j=i; j--; ) x[j].cancel(home,p,pc); x += i; n -= i; } template void ViewArray::drop_lst(int i, Space& home, Propagator& p, PropCond pc) { // Drop elements from i+1..n-1 assert(i forceinline void ViewArray::move_fst(int i, Space& home, Advisor& a) { // Move x[0] to x[i] x[i].cancel(home,a); x[i]=x[0]; x++; n--; } template forceinline void ViewArray::move_lst(int i, Space& home, Advisor& a) { // Move x[n-1] to x[i] x[i].cancel(home,a); n--; x[i]=x[n]; } template void ViewArray::drop_fst(int i, Space& home, Advisor& a) { // Drop elements from 0..i-1 assert(i>=0); for (int j=i; j--; ) x[j].cancel(home,a); x += i; n -= i; } template void ViewArray::drop_lst(int i, Space& home, Advisor& a) { // Drop elements from i+1..n-1 assert(i void ViewArray::update(Space& home, bool share, ViewArray& y) { n = y.n; if (n > 0) { x = home.alloc(n); for (int i = n; i--; ) x[i].update(home, share, y.x[i]); } else { x = NULL; } } template void ViewArray::subscribe(Space& home, Propagator& p, PropCond pc, bool process) { for (int i = n; i--; ) x[i].subscribe(home,p,pc,process); } template void ViewArray::cancel(Space& home, Propagator& p, PropCond pc) { for (int i = n; i--; ) x[i].cancel(home,p,pc); } template void ViewArray::subscribe(Space& home, Advisor& a) { for (int i = n; i--; ) x[i].subscribe(home,a); } template void ViewArray::cancel(Space& home, Advisor& a) { for (int i = n; i--; ) x[i].cancel(home,a); } template forceinline bool ViewArray::assigned(void) const { for (int i = n; i--;) if (!x[i].assigned()) return false; return true; } template forceinline bool __before(const View& x, const View& y) { return before(x,y); } template template forceinline bool ViewArray::ViewLess::operator ()(const X& a, const X& b) { return __before(a,b); } template void ViewArray::sort(View* y, int m) { ViewLess vl; Support::quicksort >(y,m,vl); } template forceinline bool __same(const X& x, const Y& y) { return same(x,y); } template forceinline bool __shared(const X& x, const Y& y) { return shared(x,y); } template bool ViewArray::same(const Space& home) const { if (n < 2) return false; Region r(home); View* y = r.alloc(n); for (int i = n; i--; ) y[i] = x[i]; sort(y,n); for (int i = n-1; i--; ) if (!y[i].assigned() && __same(y[i+1],y[i])) { r.free(y,n); return true; } r.free(y,n); return false; } template bool ViewArray::same(const Space&, const View& y) const { if (y.assigned()) return false; for (int i = n; i--; ) if (__same(x[i],y)) return true; return false; } template void ViewArray::unique(const Space&) { if (n < 2) return; sort(x,n); int j = 0; for (int i = 1; i bool ViewArray::shared(const Space& home) const { if (n < 2) return false; Region r(home); View* y = r.alloc(n); for (int i = n; i--; ) y[i] = x[i]; sort(y,n); for (int i = n-1; i--; ) if (!y[i].assigned() && __shared(y[i+1],y[i])) { r.free(y,n); return true; } r.free(y,n); return false; } template template bool ViewArray::shared(const Space&, const ViewY& y) const { if (y.assigned()) return false; for (int i = n; i--; ) if (!x[i].assigned() && __shared(x[i],y)) return true; return false; } template template bool ViewArray::shared(const Space& home, const ViewArray& y) const { if ((size() < 1) || (y.size() < 1)) return false; Region r(home); View* xs = r.alloc(size()); for (int i=size(); i--; ) xs[i] = x[i]; ViewLess xvl; Support::quicksort >(xs,size(),xvl); ViewY* ys = r.alloc(y.size()); for (int j=y.size(); j--; ) ys[j] = y[j]; ViewLess yvl; Support::quicksort >(ys,y.size(),yvl); { int i=0, j=0; while ((i < size()) && (j < y.size())) if (!x[i].assigned() && __shared(x[i],y[j])) { r.free(xs,size()); r.free(ys,y.size()); return true; } else if (before(x[i],y[j])) { i++; } else { j++; } } r.free(xs,size()); r.free(ys,y.size()); return false; } template void* ViewArray::operator new(size_t) { return NULL; } template void ViewArray::operator delete(void*,size_t) { } /* * Argument arrays: base class * */ template forceinline T* ArgArrayBase::allocate(int n) { return (n > onstack_size) ? heap.alloc(static_cast(n)) : &onstack[0]; } template forceinline void ArgArrayBase::resize(int i) { if (n+i >= capacity) { assert(n+i >= onstack_size); int newCapacity = (3*capacity)/2; if (newCapacity <= n+i) newCapacity = n+i; T* newA = allocate(newCapacity); heap.copy(newA,a,n); if (capacity > onstack_size) heap.free(a,capacity); capacity = newCapacity; a = newA; } } template forceinline ArgArrayBase::ArgArrayBase(void) : n(0), capacity(onstack_size), a(allocate(0)) {} template forceinline ArgArrayBase::ArgArrayBase(int n0) : n(n0), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) {} template inline ArgArrayBase::ArgArrayBase(const ArgArrayBase& aa) : n(aa.n), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) { heap.copy(a,aa.a,n); } template forceinline ArgArrayBase::~ArgArrayBase(void) { if (capacity > onstack_size) heap.free(a,capacity); } template forceinline const ArgArrayBase& ArgArrayBase::operator =(const ArgArrayBase& aa) { if (&aa != this) { if (capacity > onstack_size) heap.free(a,capacity); n = aa.n; capacity = (n < onstack_size ? onstack_size : n); a = allocate(aa.n); heap.copy(a,aa.a,n); } return *this; } template forceinline int ArgArrayBase::size(void) const { return n; } template forceinline T& ArgArrayBase::operator [](int i) { assert((i>=0) && (i < n)); return a[i]; } template forceinline const T& ArgArrayBase::operator [](int i) const { assert((i>=0) && (i < n)); return a[i]; } template forceinline typename ArgArrayBase::iterator ArgArrayBase::begin(void) { return a; } template forceinline typename ArgArrayBase::const_iterator ArgArrayBase::begin(void) const { return a; } template forceinline typename ArgArrayBase::iterator ArgArrayBase::end(void) { return a+n; } template forceinline typename ArgArrayBase::const_iterator ArgArrayBase::end(void) const { return a+n; } template forceinline typename ArgArrayBase::reverse_iterator ArgArrayBase::rbegin(void) { return reverse_iterator(a+n); } template forceinline typename ArgArrayBase::const_reverse_iterator ArgArrayBase::rbegin(void) const { return const_reverse_iterator(a+n); } template forceinline typename ArgArrayBase::reverse_iterator ArgArrayBase::rend(void) { return reverse_iterator(a); } template forceinline typename ArgArrayBase::const_reverse_iterator ArgArrayBase::rend(void) const { return const_reverse_iterator(a); } template template A ArgArrayBase::slice(int start, int inc, int maxN) { assert(n==0 || start < n); if (n==0 || maxN<0) maxN = n; int s; if (inc == 0) s = n-start; else if (inc > 0) s = (n-start)/inc + ((n-start) % inc == 0 ? 0 : 1); else s = (start+1)/-inc + ((start+1) % -inc == 0 ? 0 : 1); A r(std::min(maxN,s)); for (int i=0; i template inline A& ArgArrayBase::append(const T& x) { resize(1); new (&a[n++]) T(x); return static_cast(*this); } template template inline A& ArgArrayBase::append(const ArgArrayBase& x) { resize(x.size()); for (int i=0; i(*this); } template template inline A ArgArrayBase::concat(const ArgArrayBase& x) const { A r(n+x.n); for (int i=n; i--;) new (&r[i]) T(a[i]); for (int i=x.n; i--;) new (&r[n+i]) T(x.a[i]); return r; } template template inline A ArgArrayBase::concat(const T& x) const { A r(n+1); for (int i=n; i--;) new (&r[i]) T(a[i]); new (&r[n]) T(x); return r; } /* * Argument arrays for primitive types * */ template forceinline PrimArgArray::PrimArgArray(void) {} template forceinline PrimArgArray::PrimArgArray(int n) : ArgArrayBase(n) {} template PrimArgArray::PrimArgArray(int n, T a0, ...) : ArgArrayBase(n) { va_list args; va_start(args, a0); a[0] = a0; for (int i = 1; i < n; i++) a[i] = va_arg(args,T); va_end(args); } template PrimArgArray::PrimArgArray(int n, const T* a0) : ArgArrayBase(n) { for (int i=n; i--; ) a[i] = a0[i]; } template forceinline PrimArgArray::PrimArgArray(const PrimArgArray& aa) : ArgArrayBase(aa) {} template forceinline typename ArrayTraits >::ArgsType PrimArgArray::slice(int start, int inc, int maxN) { return ArgArrayBase::template slice >::ArgsType> (start,inc,maxN); } template forceinline typename ArrayTraits >::ArgsType& PrimArgArray::operator <<(const T& x) { return ArgArrayBase::template append >::ArgsType>(x); } template forceinline typename ArrayTraits >::ArgsType& PrimArgArray::operator <<(const PrimArgArray& x) { return ArgArrayBase::template append >::ArgsType>(x); } template typename ArrayTraits >::ArgsType operator +(const PrimArgArray& x, const PrimArgArray& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const PrimArgArray& x, const T& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const T& x, const PrimArgArray& y) { return PrimArgArray(1,x).template concat >::ArgsType>(y); } /* * Argument arrays for non-primitive types * */ template forceinline ArgArray::ArgArray(void) {} template forceinline ArgArray::ArgArray(int n) : ArgArrayBase(n) {} template ArgArray::ArgArray(int n, const T* a0) : ArgArrayBase(n) { for (int i=n; i--; ) a[i] = a0[i]; } template forceinline ArgArray::ArgArray(const ArgArray& aa) : ArgArrayBase(aa) {} template forceinline typename ArrayTraits >::ArgsType ArgArray::slice(int start, int inc, int maxN) { return ArgArrayBase::template slice >::ArgsType> (start,inc,maxN); } template forceinline typename ArrayTraits >::ArgsType& ArgArray::operator <<(const T& x) { return ArgArrayBase::template append >::ArgsType>(x); } template forceinline typename ArrayTraits >::ArgsType& ArgArray::operator <<(const ArgArray& x) { return ArgArrayBase::template append >::ArgsType>(x); } template typename ArrayTraits >::ArgsType operator +(const ArgArray& x, const ArgArray& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const ArgArray& x, const T& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const T& x, const ArgArray& y) { ArgArray xa(1); xa[0] = x; return xa.template concat >::ArgsType>(y); } /* * Argument arrays for variables * */ template forceinline VarArgArray::VarArgArray(void) {} template forceinline VarArgArray::VarArgArray(int n) : ArgArrayBase(n) {} template forceinline VarArgArray::VarArgArray(const VarArgArray& aa) : ArgArrayBase(aa) {} template inline VarArgArray::VarArgArray(const VarArray& x) : ArgArrayBase(x.size()) { for (int i=x.size(); i--; ) a[i]=x[i]; } template forceinline typename ArrayTraits >::ArgsType VarArgArray::slice(int start, int inc, int maxN) { return ArgArrayBase::template slice >::ArgsType> (start,inc,maxN); } template forceinline typename ArrayTraits >::ArgsType& VarArgArray::operator <<(const Var& x) { return ArgArrayBase::template append >::ArgsType>(x); } template forceinline typename ArrayTraits >::ArgsType& VarArgArray::operator <<(const VarArgArray& x) { return ArgArrayBase::template append >::ArgsType>(x); } template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const VarArgArray& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const VarArgArray& x, const Var& y) { return x.template concat >::ArgsType>(y); } template typename ArrayTraits >::ArgsType operator +(const Var& x, const VarArgArray& y) { VarArgArray xa(1); xa[0] = x; return xa.template concat >::ArgsType>(y); } template forceinline bool VarArgArray::VarLess::operator ()(const Var& a, const Var& b) { return a.varimp() < b.varimp(); } template forceinline bool VarArgArray::assigned(void) const { for (int i = n; i--;) if (!a[i].assigned()) return false; return true; } template bool VarArgArray::same(const Space& home) const { if (n < 2) return false; Region r(home); Var* y = r.alloc(n); for (int i = n; i--; ) y[i] = a[i]; VarLess vl; Support::quicksort(y,n,vl); for (int i = n-1; i--; ) if (!y[i].assigned() && (y[i+1].varimp() == y[i].varimp())) { r.free(y,n); return true; } r.free(y,n); return false; } template bool VarArgArray::same(const Space& home, const VarArgArray& y) const { int m = n + y.n; if (m < 2) return false; Region r(home); Var* z = r.alloc(m); for (int i = n; i--; ) z[i] = a[i]; for (int i = y.n; i--; ) z[i+n] = y.a[i]; VarLess vl; Support::quicksort(z,m,vl); for (int i = m-1; i--; ) if (!z[i].assigned() && (z[i+1].varimp() == z[i].varimp())) { r.free(z,m); return true; } r.free(z,m); return false; } template bool VarArgArray::same(const Space&, const Var& y) const { if (y.assigned()) return false; for (int i = n; i--; ) if (a[i].varimp() == y.varimp()) return true; return false; } /* * Interdependent code * */ template inline VarArray::VarArray(Space& home, const VarArgArray& a) : n(a.size()) { if (n>0) { x = home.alloc(n); for (int i=n; i--;) x[i] = a[i]; } else { x = NULL; } } /* * Printing of arrays * */ template std::basic_ostream& operator <<(std::basic_ostream& os, const VarArray& x) { std::basic_ostringstream s; s.copyfmt(os); s.width(0); s << '{'; if (x.size() > 0) { s << x[0]; for (int i=1; i std::basic_ostream& operator <<(std::basic_ostream& os, const ViewArray& x) { std::basic_ostringstream s; s.copyfmt(os); s.width(0); s << '{'; if (x.size() > 0) { s << x[0]; for (int i=1; i std::basic_ostream& operator <<(std::basic_ostream& os, const ArgArrayBase& x) { std::basic_ostringstream s; s.copyfmt(os); s.width(0); s << '{'; if (x.size() > 0) { s << x[0]; for (int i=1; i