/* -*- 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 * * 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 #include namespace Gecode { namespace Kernel { /// Occurence information for a view template class ViewOcc { public: /// The view View x; /// The original index in the array int i; /// Sorting order bool operator <(const ViewOcc& y) const; }; template forceinline bool ViewOcc::operator <(const ViewOcc& y) const { return x < y.x; } /// Check whether \a p has duplicates among its \a n elements (changes \a p) GECODE_KERNEL_EXPORT bool duplicates(void** p, int n); /// Check whether \a p has common elements with \a q GECODE_KERNEL_EXPORT bool duplicates(void** p, int n, void** q, int m); }} 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 //@{ /// Update array to be a clone of array \a a void update(Space& home, VarArray& a); //@} /// Allocate memory from heap (disabled) static void* operator new(size_t s) = delete; /// Free memory allocated from heap (disabled) static void operator delete(void* p) = delete; }; /** 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; 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=0; i 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=0; i& 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(void) const; /** * \brief Test whether array contains a view being the same as \a y * * Note that assigned views are ignored. */ bool same(const View& y) const; /// Remove all duplicate views from array (changes element order) void unique(void); //@} /// Allocate memory from heap (disabled) static void* operator new(size_t s) = delete; /// Free memory allocated from heap (disabled) static void operator delete(void* p) = delete; }; /** * \brief Test whether array \a x together with array \a y contains shared views * * Note that assigned views are ignored. * \relates ViewArray */ template bool shared(ViewArray x, ViewArray y); /** * \brief Test whether array \a x contains a view shared with \a y * * Note that assigned views are ignored. * \relates ViewArray */ template bool shared(ViewArray x, ViewY y); /** * \brief Test whether array \a y contains a view shared with \a x * * Note that assigned views are ignored. * \relates ViewArray */ template bool shared(ViewX x, ViewArray y); /** * \brief Test whether array \a x contains shared views * * Note that assigned views are ignored. * \relates ViewArray */ template bool shared(ViewArray x); /** * \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. * * \ingroup TaskVar */ 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); /// Initialize from vector \a a ArgArrayBase(const std::vector& a); /// Initialize from initializer list \a a ArgArrayBase(std::initializer_list a); /// Initialize from InputIterator \a begin and \a end template ArgArrayBase(InputIterator first, InputIterator last); //@} /// \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); //@} }; 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 argument array \a a (copy elements) ArgArray(const ArgArray& a); /// Initialize from vector \a a ArgArray(const std::vector& a); /// Initialize from initializer list \a a ArgArray(std::initializer_list a); /// Initialize from InputIterator \a first and \a last template ArgArray(InputIterator first, InputIterator last); //@} /// \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; 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); /// Initialize from vector \a a VarArgArray(const std::vector& a); /// Initialize from initializer list \a a VarArgArray(std::initializer_list a); /// Initialize from InputIterator \a first and \a last template VarArgArray(InputIterator first, InputIterator last); //@} /// \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); }; /** * \brief Test whether array \a x together with array \a y contains at least one variable being the same * * Note that assigned variables are ignored. * \relates VarArgArray */ template bool same(VarArgArray x, VarArgArray y); /** * \brief Test whether array \a x contains variable \a y * * Note that assigned variables are ignored. * \relates VarArgArray */ template bool same(VarArgArray x, Var y); /** * \brief Test whether array \a y contains variable \a x * * Note that assigned variables are ignored. * \relates VarArgArray */ template bool same(Var x, VarArgArray y); /** * \brief Test whether array \a x contains a variable multiply * * Note that assigned variables are ignored. * \relates VarArgArray */ template bool same(VarArgArray x); /** * \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 allocated in the space. * */ template forceinline VarArray::VarArray(void) : n(0), x(nullptr) {} template forceinline VarArray::VarArray(Space& home, int n0) : n(n0) { // Allocate from space x = (n>0) ? home.alloc(n) : nullptr; } 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, VarArray& a) { n = a.n; if (n > 0) { x = home.alloc(n); for (int i=0; i forceinline bool VarArray::assigned(void) const { for (int i=0; i typename ArrayTraits>::ArgsType operator +(const VarArray& x, const VarArray& y) { typename ArrayTraits>::ArgsType r(x.size()+y.size()); for (int i=0; i typename ArrayTraits>::ArgsType operator +(const VarArray& x, const VarArgArray& y) { typename ArrayTraits>::ArgsType r(x.size()+y.size()); for (int i=0; i typename ArrayTraits>::ArgsType operator +(const VarArgArray& x, const VarArray& y) { typename ArrayTraits>::ArgsType r(x.size()+y.size()); for (int i=0; i typename ArrayTraits>::ArgsType operator +(const VarArray& x, const Var& y) { typename ArrayTraits>::ArgsType r(x.size()+1); for (int i=0; i typename ArrayTraits>::ArgsType operator +(const Var& x, const VarArray& y) { typename ArrayTraits>::ArgsType r(y.size()+1); r[0] = x; for (int i=0; i forceinline ViewArray::ViewArray(void) : n(0), x(nullptr) {} template forceinline ViewArray::ViewArray(Space& home, int n0) : n(n0) { x = (n>0) ? home.alloc(n) : nullptr; } template forceinline ViewArray::ViewArray(Region& r, int n0) : n(n0) { x = (n>0) ? r.alloc(n) : nullptr; } template ViewArray::ViewArray(Space& home, const ViewArray& a) : n(a.size()) { if (n>0) { x = home.alloc(n); for (int i=0; i ViewArray::ViewArray(Region& r, const ViewArray& a) : n(a.size()) { if (n>0) { x = r.alloc(n); for (int i=0; i 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=0; j 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=0; j void ViewArray::drop_lst(int i, Space& home, Advisor& a) { // Drop elements from i+1..n-1 assert(i void ViewArray::update(Space& home, ViewArray& y) { n = y.n; if (n > 0) { x = home.alloc(n); for (int i=0; i void ViewArray::subscribe(Space& home, Propagator& p, PropCond pc, bool schedule) { for (int i=0; i void ViewArray::cancel(Space& home, Propagator& p, PropCond pc) { for (int i=0; i void ViewArray::subscribe(Space& home, Advisor& a) { for (int i=0; i void ViewArray::cancel(Space& home, Advisor& a) { for (int i=0; i void ViewArray::reschedule(Space& home, Propagator& p, PropCond pc) { for (int i=0; i forceinline bool ViewArray::assigned(void) const { for (int i=0; i bool ViewArray::same(void) const { if (n < 2) return false; Region r; View* y = r.alloc(n); int j=0; for (int i=0; i(y,j); for (int i=1; i bool ViewArray::same(const View& y) const { if (y.assigned()) return false; for (int i=0; i void ViewArray::unique(void) { if (n < 2) return; Region r; Kernel::ViewOcc* o = r.alloc>(n); for (int i=0; i>(o,n); // Assign bucket numbers int* bkt = r.alloc(n); int b = 0; bkt[o[0].i] = b; for (int i=1; i seen(r,static_cast(b+1)); int j=0; for (int i=0; i(bkt[i]))) { x[j++]=x[i]; seen.set(static_cast(bkt[i])); } else { x[j]=x[i]; } assert(j == b+1); n = j; } /* * Sharing for view arrays * */ template bool shared(ViewArray x, ViewArray y) { if ((x.size() == 0) || (y.size() == 0)) return false; Region r; void** px = r.alloc(x.size()); int j=0; for (int i=0; i(y.size()); int k=0; for (int i=0; i bool shared(ViewArray x, ViewY y) { if (y.assigned() || !y.varimp()) return false; for (int i=0; i forceinline bool shared(ViewX x, ViewArray y) { return shared(y,x); } template bool shared(ViewArray x) { if (x.size() < 2) return false; Region r; void** px = r.alloc(x.size()); int j=0; for (int i=0; i 2) && Kernel::duplicates(px,j); } /* * 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 inline ArgArrayBase::ArgArrayBase(const std::vector& aa) : n(static_cast(aa.size())), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) { heap.copy(a,&aa[0],n); } template inline ArgArrayBase::ArgArrayBase(std::initializer_list aa) : n(static_cast(aa.size())), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) { int i=0; for (const T& x : aa) a[i++]=x; } 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 ArgArrayBase::ArgArrayBase(InputIterator first, InputIterator last) : n(0), capacity(onstack_size), a(allocate(0)) { while (first != last) { (void) append>(*first); ++first; } } 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=0; i template inline A ArgArrayBase::concat(const T& x) const { A r(n+1); for (int i=0; i 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=0; i forceinline ArgArray::ArgArray(const ArgArray& aa) : ArgArrayBase(aa) {} template forceinline ArgArray::ArgArray(const std::vector& aa) : ArgArrayBase(aa) {} template forceinline ArgArray::ArgArray(std::initializer_list aa) : ArgArrayBase(aa) {} template template forceinline ArgArray::ArgArray(InputIterator first, InputIterator last) : ArgArrayBase(first,last) {} 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 forceinline VarArgArray::VarArgArray(const std::vector& aa) : ArgArrayBase(aa) {} template forceinline VarArgArray::VarArgArray(std::initializer_list aa) : ArgArrayBase(aa) {} template template forceinline VarArgArray::VarArgArray(InputIterator first, InputIterator last) : ArgArrayBase(first,last) {} template inline VarArgArray::VarArgArray(const VarArray& x) : ArgArrayBase(x.size()) { for (int i=0; i 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::assigned(void) const { for (int i=0; i bool same(VarArgArray x, VarArgArray y) { if ((x.size() == 0) || (y.size() == 0)) return false; Region r; void** px = r.alloc(x.size()); int j=0; for (int i=0; i(y.size()); int k=0; for (int i=0; i bool same(VarArgArray x, Var y) { if (y.assigned()) return false; for (int i=0; i forceinline bool same(Var x, VarArgArray y) { return same(y,x); } template bool same(VarArgArray x) { if (x.size() < 2) return false; Region r; void** px = r.alloc(x.size()); int j=0; for (int i=0; i 1) && Kernel::duplicates(px,j); } /* * Interdependent code * */ template inline VarArray::VarArray(Space& home, const VarArgArray& a) : n(a.size()) { if (n>0) { x = home.alloc(n); for (int i=0; i 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