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 3e72b0e857 Squashed 'software/gecode_on_record/' content from commit 37ed9bda4
git-subtree-dir: software/gecode_on_record
git-subtree-split: 37ed9bda495ea87e63217c19a374b5a93bb0078e
2021-06-16 14:03:52 +10:00

2048 lines
56 KiB
C++

/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
/*
* Main authors:
* Christian Schulte <schulte@gecode.org>
* Guido Tack <tack@gecode.org>
*
* Contributing authors:
* Gregory Crosswhite <gcross@phys.washington.edu>
*
* 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 <iostream>
#include <iterator>
#include <vector>
#include <sstream>
#include <initializer_list>
namespace Gecode { namespace Kernel {
/// Occurence information for a view
template<class View>
class ViewOcc {
public:
/// The view
View x;
/// The original index in the array
int i;
/// Sorting order
bool operator <(const ViewOcc& y) const;
};
template<class View>
forceinline bool
ViewOcc<View>::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 Var> class VarArray;
template<class Var> class VarArgArray;
/** \brief Traits of arrays in %Gecode
*
* This class collects the traits of an array in Gecode.
* The traits used are the following.
* - <code>typedef Type StorageType</code> where \c Type is the type
* of an appropriate storage type for this array.
* - <code>typedef Type ValueType</code> where \c Type is the type
* of the elements of this array.
* - <code>typedef Type ArgsType</code> where \c Type is the type
* of the appropriate Args-array type (e.g., \c BoolVarArgs if \c A is
* \c BoolVarArray).
*/
template<class A>
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 Var>
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<Var*> reverse_iterator;
/// Type of the iterator used to iterate backwards and read-only through this array's elements
typedef std::reverse_iterator<const Var*> 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<Var>&);
/// Initialize from variable array \a a (share elements)
VarArray(const VarArray<Var>& a);
/// Initialize from variable array \a a (share elements)
const VarArray<Var>& operator =(const VarArray<Var>& 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<n\f$, \f$y_i=x_{\text{start}+i\cdot\text{inc}}\f$
*
* If \a n is -1, then all possible elements starting from \a start
* with increment \a inc are returned.
*/
typename ArrayTraits<VarArgArray<Var>>::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<Var>& 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<class T>
typename ArrayTraits<VarArray<T>>::ArgsType
operator +(const VarArray<T>& x, const VarArgArray<T>& y);
/** Concatenate \a x and \a y and return result
* \relates VarArray
*/
template<class T>
typename ArrayTraits<VarArray<T>>::ArgsType
operator +(const VarArray<T>& x, const VarArray<T>& y);
/** Concatenate \a x and \a y and return result
* \relates VarArray
*/
template<class T>
typename ArrayTraits<VarArray<T>>::ArgsType
operator +(const VarArgArray<T>& x, const VarArray<T>& y);
/** Concatenate \a x and \a y and return result
* \relates VarArray
*/
template<class T>
typename ArrayTraits<VarArray<T>>::ArgsType
operator +(const VarArray<T>& x, const T& y);
/** Concatenate \a x and \a y and return result
* \relates VarArray
*/
template<class T>
typename ArrayTraits<VarArray<T>>::ArgsType
operator +(const T& x, const VarArray<T>& 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 View>
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<View*> reverse_iterator;
/// Type of the iterator used to iterate backwards and read-only through this array's elements
typedef std::reverse_iterator<const View*> 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<View>& a);
/// Initialize from view array \a a (copy elements)
ViewArray(Space& home, const ViewArray<View>& a);
/// Initialize from view array \a a (copy elements)
ViewArray(Region& r, const ViewArray<View>& a);
/// Initialize from view array \a a (share elements)
const ViewArray<View>& operator =(const ViewArray<View>& 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<class Var>
ViewArray(Space& home, const VarArgArray<Var>& a)
: n(a.size()) {
// This may not be in the hpp file (to satisfy the MS compiler)
if (n>0) {
x = home.alloc<View>(n);
for (int i=0; i<n; i++)
x[i]=a[i];
} else {
x = nullptr;
}
}
/**
* \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<class Var>
ViewArray(Region& r, const VarArgArray<Var>& a)
: n(a.size()) {
// This may not be in the hpp file (to satisfy the MS compiler)
if (n>0) {
x = r.alloc<View>(n);
for (int i=0; i<n; i++)
x[i]=a[i];
} else {
x = nullptr;
}
}
//@}
/// \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 scheduled for execution (this must be used when creating
* subscriptions during propagation).
*/
void subscribe(Space& home, Propagator& p, PropCond pc,
bool schedule=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);
/// Re-schedule propagator \a p with propagation condition \a pc
void reschedule(Space& home, Propagator& p, PropCond pc);
//@}
/// \name Cloning
//@{
/// Update array to be a clone of array \a a
void update(Space& home, ViewArray<View>& 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<class ViewX, class ViewY>
bool shared(ViewArray<ViewX> x, ViewArray<ViewY> y);
/**
* \brief Test whether array \a x contains a view shared with \a y
*
* Note that assigned views are ignored.
* \relates ViewArray
*/
template<class ViewX, class ViewY>
bool shared(ViewArray<ViewX> 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<class ViewX, class ViewY>
bool shared(ViewX x, ViewArray<ViewY> y);
/**
* \brief Test whether array \a x contains shared views
*
* Note that assigned views are ignored.
* \relates ViewArray
*/
template<class View>
bool shared(ViewArray<View> 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 T>
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<class A>
A concat(const ArgArrayBase<T>& x) const;
/// Return this array concatenated with \a x
template<class A>
A concat(const T& x) const;
/// Insert a new element \a x at the end of the array (increase size by 1)
template<class A>
A& append(const T& x);
/// Append \a x to the end of the array
template<class A>
A& append(const ArgArrayBase<T>& x);
/** Return slice \f$y\f$ of length at most \a n such that forall \f$0\leq i<n\f$, \f$y_i=x_{\text{start}+i\cdot\text{inc}}\f$
*
* If \a n is -1, then all possible elements starting from \a start
* with increment \a inc are returned.
*/
template<class A>
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<T*> reverse_iterator;
/// Type of the iterator used to iterate backwards and read-only through this array's elements
typedef std::reverse_iterator<const T*> 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<T>& a);
/// Initialize from view array \a a (copy elements)
const ArgArrayBase<T>& operator =(const ArgArrayBase<T>& a);
/// Initialize from vector \a a
ArgArrayBase(const std::vector<T>& a);
/// Initialize from initializer list \a a
ArgArrayBase(std::initializer_list<T> a);
/// Initialize from InputIterator \a begin and \a end
template<class InputIterator>
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> class ArgArray;
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const ArgArray<T>& x, const ArgArray<T>& y);
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const ArgArray<T>& x, const T& y);
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const T& x, const ArgArray<T>& 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 T>
class ArgArray : public ArgArrayBase<T> {
protected:
using ArgArrayBase<T>::a;
public:
using ArgArrayBase<T>::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<T>& a);
/// Initialize from vector \a a
ArgArray(const std::vector<T>& a);
/// Initialize from initializer list \a a
ArgArray(std::initializer_list<T> a);
/// Initialize from InputIterator \a first and \a last
template<class InputIterator>
ArgArray(InputIterator first, InputIterator last);
//@}
/// \name Array elements
//@{
/// Return slice \f$y\f$ of length \a n such that forall \f$0\leq i<n\f$, \f$y_i=x_{\text{start}+i\cdot\text{inc}}\f$
typename ArrayTraits<ArgArray<T>>::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<ArgArray<T>>::ArgsType&
operator <<(const T& x);
/// Append \a x to the end of the array
typename ArrayTraits<ArgArray<T>>::ArgsType&
operator <<(const ArgArray<T>& x);
//@}
friend typename ArrayTraits<ArgArray<T>>::ArgsType
operator + <>(const ArgArray<T>& x, const ArgArray<T>& y);
friend typename ArrayTraits<ArgArray<T>>::ArgsType
operator + <>(const ArgArray<T>& x, const T& y);
friend
typename ArrayTraits<ArgArray<T>>::ArgsType
operator + <>(const T& x, const ArgArray<T>& y);
};
template<class> class VarArgArray;
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const VarArgArray<Var>& x, const VarArgArray<Var>& y);
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const VarArgArray<Var>& x, const Var& y);
/** Concatenate \a x and \a y and return result
* \relates ArgArray
*/
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const Var& x, const VarArgArray<Var>& 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 Var>
class VarArgArray : public ArgArrayBase<Var> {
protected:
using ArgArrayBase<Var>::a;
using ArgArrayBase<Var>::n;
public:
using ArgArrayBase<Var>::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<Var>& a);
/// Initialize from variable array \a a (copy elements)
VarArgArray(const VarArray<Var>& a);
/// Initialize from vector \a a
VarArgArray(const std::vector<Var>& a);
/// Initialize from initializer list \a a
VarArgArray(std::initializer_list<Var> a);
/// Initialize from InputIterator \a first and \a last
template<class InputIterator>
VarArgArray(InputIterator first, InputIterator last);
//@}
/// \name Array elements
//@{
/// Return slice \f$y\f$ of length \a n such that forall \f$0\leq i<n\f$, \f$y_i=x_{\text{start}+i\cdot\text{inc}}\f$
typename ArrayTraits<VarArgArray<Var>>::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<VarArgArray<Var>>::ArgsType&
operator <<(const Var& x);
/// Append \a x to the end of the array
typename ArrayTraits<VarArgArray<Var>>::ArgsType&
operator <<(const VarArgArray<Var>& x);
//@}
/// Test if all variables are assigned
bool assigned(void) const;
friend typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator + <>(const VarArgArray<Var>& x, const VarArgArray<Var>& y);
friend typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator + <>(const VarArgArray<Var>& x, const Var& y);
friend
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator + <>(const Var& x, const VarArgArray<Var>& 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<class Var>
bool same(VarArgArray<Var> x, VarArgArray<Var> y);
/**
* \brief Test whether array \a x contains variable \a y
*
* Note that assigned variables are ignored.
* \relates VarArgArray
*/
template<class Var>
bool same(VarArgArray<Var> x, Var y);
/**
* \brief Test whether array \a y contains variable \a x
*
* Note that assigned variables are ignored.
* \relates VarArgArray
*/
template<class Var>
bool same(Var x, VarArgArray<Var> y);
/**
* \brief Test whether array \a x contains a variable multiply
*
* Note that assigned variables are ignored.
* \relates VarArgArray
*/
template<class Var>
bool same(VarArgArray<Var> x);
/**
* \brief Print array elements enclosed in curly brackets
* \relates VarArray
*/
template<class Char, class Traits, class Var>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os,
const VarArray<Var>& x);
/**
* \brief Print array elements enclosed in curly brackets
* \relates ViewArray
*/
template<class Char, class Traits, class View>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os, const ViewArray<View>& x);
/**
* \brief Print array elements enclosed in curly brackets
* \relates ArgArrayBase
*/
template<class Char, class Traits, class T>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os, const ArgArrayBase<T>& x);
/*
* Implementation
*
*/
/*
* Variable arrays
*
* These arrays are allocated in the space.
*
*/
template<class Var>
forceinline
VarArray<Var>::VarArray(void) : n(0), x(nullptr) {}
template<class Var>
forceinline
VarArray<Var>::VarArray(Space& home, int n0)
: n(n0) {
// Allocate from space
x = (n>0) ? home.alloc<Var>(n) : nullptr;
}
template<class Var>
forceinline
VarArray<Var>::VarArray(const VarArray<Var>& a) {
n = a.n; x = a.x;
}
template<class Var>
inline const VarArray<Var>&
VarArray<Var>::operator =(const VarArray<Var>& a) {
n = a.n; x = a.x;
return *this;
}
template<class Var>
forceinline int
VarArray<Var>::size(void) const {
return n;
}
template<class Var>
forceinline Var&
VarArray<Var>::operator [](int i) {
assert((i >= 0) && (i < size()));
return x[i];
}
template<class Var>
forceinline const Var&
VarArray<Var>::operator [](int i) const {
assert((i >= 0) && (i < size()));
return x[i];
}
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
VarArray<Var>::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<VarArgArray<Var>>::ArgsType r(std::min(maxN,s));
for (int i=0; i<r.size(); i++, start+=inc)
r[i] = x[start];
return r;
}
template<class Var>
forceinline typename VarArray<Var>::iterator
VarArray<Var>::begin(void) {
return x;
}
template<class Var>
forceinline typename VarArray<Var>::const_iterator
VarArray<Var>::begin(void) const {
return x;
}
template<class Var>
forceinline typename VarArray<Var>::iterator
VarArray<Var>::end(void) {
return x+n;
}
template<class Var>
forceinline typename VarArray<Var>::const_iterator
VarArray<Var>::end(void) const {
return x+n;
}
template<class Var>
forceinline typename VarArray<Var>::reverse_iterator
VarArray<Var>::rbegin(void) {
return reverse_iterator(x+n);
}
template<class Var>
forceinline typename VarArray<Var>::const_reverse_iterator
VarArray<Var>::rbegin(void) const {
return const_reverse_iterator(x+n);
}
template<class Var>
forceinline typename VarArray<Var>::reverse_iterator
VarArray<Var>::rend(void) {
return reverse_iterator(x);
}
template<class Var>
forceinline typename VarArray<Var>::const_reverse_iterator
VarArray<Var>::rend(void) const {
return const_reverse_iterator(x);
}
template<class Var>
forceinline void
VarArray<Var>::update(Space& home, VarArray<Var>& a) {
n = a.n;
if (n > 0) {
x = home.alloc<Var>(n);
for (int i=0; i<n; i++)
x[i].update(home, a.x[i]);
} else {
x = nullptr;
}
}
template<class Var>
forceinline bool
VarArray<Var>::assigned(void) const {
for (int i=0; i<n; i++)
if (!x[i].assigned())
return false;
return true;
}
template<class Var>
typename ArrayTraits<VarArray<Var>>::ArgsType
operator +(const VarArray<Var>& x, const VarArray<Var>& y) {
typename ArrayTraits<VarArray<Var>>::ArgsType r(x.size()+y.size());
for (int i=0; i<x.size(); i++)
r[i] = x[i];
for (int i=0; i<y.size(); i++)
r[x.size()+i] = y[i];
return r;
}
template<class Var>
typename ArrayTraits<VarArray<Var>>::ArgsType
operator +(const VarArray<Var>& x, const VarArgArray<Var>& y) {
typename ArrayTraits<VarArray<Var>>::ArgsType r(x.size()+y.size());
for (int i=0; i<x.size(); i++)
r[i] = x[i];
for (int i=0; i<y.size(); i++)
r[x.size()+i] = y[i];
return r;
}
template<class Var>
typename ArrayTraits<VarArray<Var>>::ArgsType
operator +(const VarArgArray<Var>& x, const VarArray<Var>& y) {
typename ArrayTraits<VarArray<Var>>::ArgsType r(x.size()+y.size());
for (int i=0; i<x.size(); i++)
r[i] = x[i];
for (int i=0; i<y.size(); i++)
r[x.size()+i] = y[i];
return r;
}
template<class Var>
typename ArrayTraits<VarArray<Var>>::ArgsType
operator +(const VarArray<Var>& x, const Var& y) {
typename ArrayTraits<VarArray<Var>>::ArgsType r(x.size()+1);
for (int i=0; i<x.size(); i++)
r[i] = x[i];
r[x.size()] = y;
return r;
}
template<class Var>
typename ArrayTraits<VarArray<Var>>::ArgsType
operator +(const Var& x, const VarArray<Var>& y) {
typename ArrayTraits<VarArray<Var>>::ArgsType r(y.size()+1);
r[0] = x;
for (int i=0; i<y.size(); i++)
r[1+i] = y[i];
return r;
}
/*
* View arrays
*
*/
template<class View>
forceinline
ViewArray<View>::ViewArray(void) : n(0), x(nullptr) {}
template<class View>
forceinline
ViewArray<View>::ViewArray(Space& home, int n0)
: n(n0) {
x = (n>0) ? home.alloc<View>(n) : nullptr;
}
template<class View>
forceinline
ViewArray<View>::ViewArray(Region& r, int n0)
: n(n0) {
x = (n>0) ? r.alloc<View>(n) : nullptr;
}
template<class View>
ViewArray<View>::ViewArray(Space& home, const ViewArray<View>& a)
: n(a.size()) {
if (n>0) {
x = home.alloc<View>(n);
for (int i=0; i<n; i++)
x[i] = a[i];
} else {
x = nullptr;
}
}
template<class View>
ViewArray<View>::ViewArray(Region& r, const ViewArray<View>& a)
: n(a.size()) {
if (n>0) {
x = r.alloc<View>(n);
for (int i=0; i<n; i++)
x[i] = a[i];
} else {
x = nullptr;
}
}
template<class View>
forceinline
ViewArray<View>::ViewArray(const ViewArray<View>& a)
: n(a.n), x(a.x) {}
template<class View>
forceinline const ViewArray<View>&
ViewArray<View>::operator =(const ViewArray<View>& a) {
n = a.n; x = a.x;
return *this;
}
template<class View>
forceinline int
ViewArray<View>::size(void) const {
return n;
}
template<class View>
forceinline void
ViewArray<View>::size(int n0) {
n = n0;
}
template<class View>
forceinline View&
ViewArray<View>::operator [](int i) {
assert((i >= 0) && (i < size()));
return x[i];
}
template<class View>
forceinline const View&
ViewArray<View>::operator [](int i) const {
assert((i >= 0) && (i < size()));
return x[i];
}
template<class View>
forceinline typename ViewArray<View>::iterator
ViewArray<View>::begin(void) {
return x;
}
template<class View>
forceinline typename ViewArray<View>::const_iterator
ViewArray<View>::begin(void) const {
return x;
}
template<class View>
forceinline typename ViewArray<View>::iterator
ViewArray<View>::end(void) {
return x+n;
}
template<class View>
forceinline typename ViewArray<View>::const_iterator
ViewArray<View>::end(void) const {
return x+n;
}
template<class View>
forceinline typename ViewArray<View>::reverse_iterator
ViewArray<View>::rbegin(void) {
return reverse_iterator(x+n);
}
template<class View>
forceinline typename ViewArray<View>::const_reverse_iterator
ViewArray<View>::rbegin(void) const {
return const_reverse_iterator(x+n);
}
template<class View>
forceinline typename ViewArray<View>::reverse_iterator
ViewArray<View>::rend(void) {
return reverse_iterator(x);
}
template<class View>
forceinline typename ViewArray<View>::const_reverse_iterator
ViewArray<View>::rend(void) const {
return const_reverse_iterator(x);
}
template<class View>
forceinline void
ViewArray<View>::move_fst(int i) {
x[i]=x[0]; x++; n--;
}
template<class View>
forceinline void
ViewArray<View>::move_lst(int i) {
n--; x[i]=x[n];
}
template<class View>
forceinline void
ViewArray<View>::drop_fst(int i) {
assert(i>=0);
x += i; n -= i;
}
template<class View>
forceinline void
ViewArray<View>::drop_lst(int i) {
assert(i<n);
n = i+1;
}
template<class View>
forceinline void
ViewArray<View>::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<class View>
forceinline void
ViewArray<View>::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<class View>
void
ViewArray<View>::drop_fst(int i, Space& home, Propagator& p, PropCond pc) {
// Drop elements from 0..i-1
assert(i>=0);
for (int j=0; j<i; j++)
x[j].cancel(home,p,pc);
x += i; n -= i;
}
template<class View>
void
ViewArray<View>::drop_lst(int i, Space& home, Propagator& p, PropCond pc) {
// Drop elements from i+1..n-1
assert(i<n);
for (int j=i+1; j<n; j++)
x[j].cancel(home,p,pc);
n = i+1;
}
template<class View>
forceinline void
ViewArray<View>::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<class View>
forceinline void
ViewArray<View>::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<class View>
void
ViewArray<View>::drop_fst(int i, Space& home, Advisor& a) {
// Drop elements from 0..i-1
assert(i>=0);
for (int j=0; j<i; j++)
x[j].cancel(home,a);
x += i; n -= i;
}
template<class View>
void
ViewArray<View>::drop_lst(int i, Space& home, Advisor& a) {
// Drop elements from i+1..n-1
assert(i<n);
for (int j=i+1; j<n; j++)
x[j].cancel(home,a);
n = i+1;
}
template<class View>
void
ViewArray<View>::update(Space& home, ViewArray<View>& y) {
n = y.n;
if (n > 0) {
x = home.alloc<View>(n);
for (int i=0; i<n; i++)
x[i].update(home, y.x[i]);
} else {
x = nullptr;
}
}
template<class View>
void
ViewArray<View>::subscribe(Space& home, Propagator& p, PropCond pc,
bool schedule) {
for (int i=0; i<n; i++)
x[i].subscribe(home,p,pc,schedule);
}
template<class View>
void
ViewArray<View>::cancel(Space& home, Propagator& p, PropCond pc) {
for (int i=0; i<n; i++)
x[i].cancel(home,p,pc);
}
template<class View>
void
ViewArray<View>::subscribe(Space& home, Advisor& a) {
for (int i=0; i<n; i++)
x[i].subscribe(home,a);
}
template<class View>
void
ViewArray<View>::cancel(Space& home, Advisor& a) {
for (int i=0; i<n; i++)
x[i].cancel(home,a);
}
template<class View>
void
ViewArray<View>::reschedule(Space& home, Propagator& p, PropCond pc) {
for (int i=0; i<n; i++)
x[i].reschedule(home,p,pc);
}
template<class View>
forceinline bool
ViewArray<View>::assigned(void) const {
for (int i=0; i<n; i++)
if (!x[i].assigned())
return false;
return true;
}
template<class View>
bool
ViewArray<View>::same(void) const {
if (n < 2)
return false;
Region r;
View* y = r.alloc<View>(n);
int j=0;
for (int i=0; i<n; i++)
if (!x[i].assigned())
y[j++] = x[i];
if (j < 2)
return false;
Support::quicksort<View>(y,j);
for (int i=1; i<j; i++)
if (y[i-1] == y[i])
return true;
return false;
}
template<class View>
bool
ViewArray<View>::same(const View& y) const {
if (y.assigned())
return false;
for (int i=0; i<n; i++)
if (x[i] == y)
return true;
return false;
}
template<class View>
void
ViewArray<View>::unique(void) {
if (n < 2)
return;
Region r;
Kernel::ViewOcc<View>* o = r.alloc<Kernel::ViewOcc<View>>(n);
for (int i=0; i<n; i++) {
o[i].x = x[i]; o[i].i = i;
}
Support::quicksort<Kernel::ViewOcc<View>>(o,n);
// Assign bucket numbers
int* bkt = r.alloc<int>(n);
int b = 0;
bkt[o[0].i] = b;
for (int i=1; i<n; i++) {
if (o[i-1].x != o[i].x)
b++;
bkt[o[i].i] = b;
}
// Eliminate duplicate elements
Support::BitSet<Region> seen(r,static_cast<unsigned int>(b+1));
int j=0;
for (int i=0; i<n; i++)
if (!seen.get(static_cast<unsigned int>(bkt[i]))) {
x[j++]=x[i]; seen.set(static_cast<unsigned int>(bkt[i]));
} else {
x[j]=x[i];
}
assert(j == b+1);
n = j;
}
/*
* Sharing for view arrays
*
*/
template<class ViewX, class ViewY>
bool
shared(ViewArray<ViewX> x, ViewArray<ViewY> y) {
if ((x.size() == 0) || (y.size() == 0))
return false;
Region r;
void** px = r.alloc<void*>(x.size());
int j=0;
for (int i=0; i<x.size(); i++)
if (!x[i].assigned() && x[i].varimp())
px[j++] = x[i].varimp();
if (j == 0)
return false;
void** py = r.alloc<void*>(y.size());
int k=0;
for (int i=0; i<y.size(); i++)
if (!y[i].assigned() && y[i].varimp())
py[k++] = y[i].varimp();
if (k == 0)
return false;
return Kernel::duplicates(px,j,py,k);
}
template<class ViewX, class ViewY>
bool
shared(ViewArray<ViewX> x, ViewY y) {
if (y.assigned() || !y.varimp())
return false;
for (int i=0; i<x.size(); i++)
if (!x[i].assigned() && x[i].varimp() && (x[i].varimp() == y.varimp()))
return true;
return false;
}
template<class ViewX, class ViewY>
forceinline bool
shared(ViewX x, ViewArray<ViewY> y) {
return shared(y,x);
}
template<class View>
bool
shared(ViewArray<View> x) {
if (x.size() < 2)
return false;
Region r;
void** px = r.alloc<void*>(x.size());
int j=0;
for (int i=0; i<x.size(); i++)
if (!x[i].assigned() && x[i].varimp())
px[j++] = x[i].varimp();
return (j > 2) && Kernel::duplicates(px,j);
}
/*
* Argument arrays: base class
*
*/
template<class T>
forceinline T*
ArgArrayBase<T>::allocate(int n) {
return (n > onstack_size) ?
heap.alloc<T>(static_cast<unsigned int>(n)) : &onstack[0];
}
template<class T>
forceinline void
ArgArrayBase<T>::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<T>(newA,a,n);
if (capacity > onstack_size)
heap.free(a,capacity);
capacity = newCapacity;
a = newA;
}
}
template<class T>
forceinline
ArgArrayBase<T>::ArgArrayBase(void)
: n(0), capacity(onstack_size), a(allocate(0)) {}
template<class T>
forceinline
ArgArrayBase<T>::ArgArrayBase(int n0)
: n(n0), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) {}
template<class T>
inline
ArgArrayBase<T>::ArgArrayBase(const ArgArrayBase<T>& aa)
: n(aa.n), capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) {
heap.copy<T>(a,aa.a,n);
}
template<class T>
inline
ArgArrayBase<T>::ArgArrayBase(const std::vector<T>& aa)
: n(static_cast<int>(aa.size())),
capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) {
heap.copy<T>(a,&aa[0],n);
}
template<class T>
inline
ArgArrayBase<T>::ArgArrayBase(std::initializer_list<T> aa)
: n(static_cast<int>(aa.size())),
capacity(n < onstack_size ? onstack_size : n), a(allocate(n)) {
int i=0;
for (const T& x : aa)
a[i++]=x;
}
template<class T>
forceinline
ArgArrayBase<T>::~ArgArrayBase(void) {
if (capacity > onstack_size)
heap.free(a,capacity);
}
template<class T>
forceinline const ArgArrayBase<T>&
ArgArrayBase<T>::operator =(const ArgArrayBase<T>& 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<T>(a,aa.a,n);
}
return *this;
}
template<class T>
forceinline int
ArgArrayBase<T>::size(void) const {
return n;
}
template<class T>
forceinline T&
ArgArrayBase<T>::operator [](int i) {
assert((i>=0) && (i < n));
return a[i];
}
template<class T>
forceinline const T&
ArgArrayBase<T>::operator [](int i) const {
assert((i>=0) && (i < n));
return a[i];
}
template<class T>
forceinline typename ArgArrayBase<T>::iterator
ArgArrayBase<T>::begin(void) {
return a;
}
template<class T>
forceinline typename ArgArrayBase<T>::const_iterator
ArgArrayBase<T>::begin(void) const {
return a;
}
template<class T>
forceinline typename ArgArrayBase<T>::iterator
ArgArrayBase<T>::end(void) {
return a+n;
}
template<class T>
forceinline typename ArgArrayBase<T>::const_iterator
ArgArrayBase<T>::end(void) const {
return a+n;
}
template<class T>
forceinline typename ArgArrayBase<T>::reverse_iterator
ArgArrayBase<T>::rbegin(void) {
return reverse_iterator(a+n);
}
template<class T>
forceinline typename ArgArrayBase<T>::const_reverse_iterator
ArgArrayBase<T>::rbegin(void) const {
return const_reverse_iterator(a+n);
}
template<class T>
forceinline typename ArgArrayBase<T>::reverse_iterator
ArgArrayBase<T>::rend(void) {
return reverse_iterator(a);
}
template<class T>
forceinline typename ArgArrayBase<T>::const_reverse_iterator
ArgArrayBase<T>::rend(void) const {
return const_reverse_iterator(a);
}
template<class T> template<class A>
A
ArgArrayBase<T>::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<r.size(); i++, start+=inc)
new (&r[i]) T(a[start]);
return r;
}
template<class T> template<class A>
inline A&
ArgArrayBase<T>::append(const T& x) {
resize(1);
new (&a[n++]) T(x);
return static_cast<A&>(*this);
}
template<class T>
template<class InputIterator>
inline
ArgArrayBase<T>::ArgArrayBase(InputIterator first, InputIterator last)
: n(0), capacity(onstack_size), a(allocate(0)) {
while (first != last) {
(void) append<ArgArrayBase<T>>(*first);
++first;
}
}
template<class T> template<class A>
inline A&
ArgArrayBase<T>::append(const ArgArrayBase<T>& x) {
resize(x.size());
for (int i=0; i<x.size(); i++)
new (&a[n++]) T(x[i]);
return static_cast<A&>(*this);
}
template<class T> template<class A>
inline A
ArgArrayBase<T>::concat(const ArgArrayBase<T>& x) const {
A r(n+x.n);
for (int i=0; i<n; i++)
new (&r[i]) T(a[i]);
for (int i=0; i<x.n; i++)
new (&r[n+i]) T(x.a[i]);
return r;
}
template<class T> template<class A>
inline A
ArgArrayBase<T>::concat(const T& x) const {
A r(n+1);
for (int i=0; i<n; i++)
new (&r[i]) T(a[i]);
new (&r[n]) T(x);
return r;
}
/*
* Argument arrays
*
*/
template<class T>
forceinline
ArgArray<T>::ArgArray(void) {}
template<class T>
forceinline
ArgArray<T>::ArgArray(int n)
: ArgArrayBase<T>(n) {}
template<class T>
ArgArray<T>::ArgArray(int n, const T* a0)
: ArgArrayBase<T>(n) {
for (int i=0; i<n; i++)
a[i] = a0[i];
}
template<class T>
forceinline
ArgArray<T>::ArgArray(const ArgArray<T>& aa)
: ArgArrayBase<T>(aa) {}
template<class T>
forceinline
ArgArray<T>::ArgArray(const std::vector<T>& aa)
: ArgArrayBase<T>(aa) {}
template<class T>
forceinline
ArgArray<T>::ArgArray(std::initializer_list<T> aa)
: ArgArrayBase<T>(aa) {}
template<class T>
template<class InputIterator>
forceinline
ArgArray<T>::ArgArray(InputIterator first, InputIterator last)
: ArgArrayBase<T>(first,last) {}
template<class T>
forceinline typename ArrayTraits<ArgArray<T>>::ArgsType
ArgArray<T>::slice(int start, int inc, int maxN) {
return ArgArrayBase<T>::template slice
<typename ArrayTraits<ArgArray<T>>::ArgsType>
(start,inc,maxN);
}
template<class T>
forceinline typename ArrayTraits<ArgArray<T>>::ArgsType&
ArgArray<T>::operator <<(const T& x) {
return
ArgArrayBase<T>::template append
<typename ArrayTraits<ArgArray<T>>::ArgsType>(x);
}
template<class T>
forceinline typename ArrayTraits<ArgArray<T>>::ArgsType&
ArgArray<T>::operator <<(const ArgArray<T>& x) {
return
ArgArrayBase<T>::template append
<typename ArrayTraits<ArgArray<T>>::ArgsType>(x);
}
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const ArgArray<T>& x, const ArgArray<T>& y) {
return x.template concat
<typename ArrayTraits<ArgArray<T>>::ArgsType>(y);
}
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const ArgArray<T>& x, const T& y) {
return x.template concat
<typename ArrayTraits<ArgArray<T>>::ArgsType>(y);
}
template<class T>
typename ArrayTraits<ArgArray<T>>::ArgsType
operator +(const T& x, const ArgArray<T>& y) {
ArgArray<T> xa(1);
xa[0] = x;
return xa.template concat
<typename ArrayTraits<ArgArray<T>>::ArgsType>(y);
}
/*
* Argument arrays for variables
*
*/
template<class Var>
forceinline
VarArgArray<Var>::VarArgArray(void) {}
template<class Var>
forceinline
VarArgArray<Var>::VarArgArray(int n) : ArgArrayBase<Var>(n) {}
template<class Var>
forceinline
VarArgArray<Var>::VarArgArray(const VarArgArray<Var>& aa)
: ArgArrayBase<Var>(aa) {}
template<class Var>
forceinline
VarArgArray<Var>::VarArgArray(const std::vector<Var>& aa)
: ArgArrayBase<Var>(aa) {}
template<class Var>
forceinline
VarArgArray<Var>::VarArgArray(std::initializer_list<Var> aa)
: ArgArrayBase<Var>(aa) {}
template<class Var>
template<class InputIterator>
forceinline
VarArgArray<Var>::VarArgArray(InputIterator first, InputIterator last)
: ArgArrayBase<Var>(first,last) {}
template<class Var>
inline
VarArgArray<Var>::VarArgArray(const VarArray<Var>& x)
: ArgArrayBase<Var>(x.size()) {
for (int i=0; i<x.size(); i++)
a[i]=x[i];
}
template<class Var>
forceinline typename ArrayTraits<VarArgArray<Var>>::ArgsType
VarArgArray<Var>::slice(int start, int inc, int maxN) {
return ArgArrayBase<Var>::template slice
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>
(start,inc,maxN);
}
template<class Var>
forceinline typename ArrayTraits<VarArgArray<Var>>::ArgsType&
VarArgArray<Var>::operator <<(const Var& x) {
return
ArgArrayBase<Var>::template append
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>(x);
}
template<class Var>
forceinline typename ArrayTraits<VarArgArray<Var>>::ArgsType&
VarArgArray<Var>::operator <<(const VarArgArray<Var>& x) {
return
ArgArrayBase<Var>::template append
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>(x);
}
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const VarArgArray<Var>& x, const VarArgArray<Var>& y) {
return x.template concat
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>(y);
}
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const VarArgArray<Var>& x, const Var& y) {
return x.template concat
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>(y);
}
template<class Var>
typename ArrayTraits<VarArgArray<Var>>::ArgsType
operator +(const Var& x, const VarArgArray<Var>& y) {
VarArgArray<Var> xa(1);
xa[0] = x;
return xa.template concat
<typename ArrayTraits<VarArgArray<Var>>::ArgsType>(y);
}
template<class Var>
forceinline bool
VarArgArray<Var>::assigned(void) const {
for (int i=0; i<n; i++)
if (!a[i].assigned())
return false;
return true;
}
/*
* Checking for multiple occurences of the same variable
*
*/
template<class Var>
bool
same(VarArgArray<Var> x, VarArgArray<Var> y) {
if ((x.size() == 0) || (y.size() == 0))
return false;
Region r;
void** px = r.alloc<void*>(x.size());
int j=0;
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
px[j++] = x[i].varimp();
if (j == 0)
return false;
void** py = r.alloc<void*>(y.size());
int k=0;
for (int i=0; i<y.size(); i++)
if (!y[i].assigned())
py[k++] = y[i].varimp();
if (k == 0)
return false;
return Kernel::duplicates(px,j,py,k);
}
template<class Var>
bool
same(VarArgArray<Var> x, Var y) {
if (y.assigned())
return false;
for (int i=0; i<x.size(); i++)
if (x[i].varimp() == y.varimp())
return true;
return false;
}
template<class Var>
forceinline bool
same(Var x, VarArgArray<Var> y) {
return same(y,x);
}
template<class Var>
bool
same(VarArgArray<Var> x) {
if (x.size() < 2)
return false;
Region r;
void** px = r.alloc<void*>(x.size());
int j=0;
for (int i=0; i<x.size(); i++)
if (!x[i].assigned())
px[j++] = x[i].varimp();
return (j > 1) && Kernel::duplicates(px,j);
}
/*
* Interdependent code
*
*/
template<class Var>
inline
VarArray<Var>::VarArray(Space& home, const VarArgArray<Var>& a)
: n(a.size()) {
if (n>0) {
x = home.alloc<Var>(n);
for (int i=0; i<n; i++)
x[i] = a[i];
} else {
x = nullptr;
}
}
/*
* Printing of arrays
*
*/
template<class Char, class Traits, class Var>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os,
const VarArray<Var>& x) {
std::basic_ostringstream<Char,Traits> s;
s.copyfmt(os); s.width(0);
s << '{';
if (x.size() > 0) {
s << x[0];
for (int i=1; i<x.size(); i++)
s << ", " << x[i];
}
s << '}';
return os << s.str();
}
template<class Char, class Traits, class View>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os,
const ViewArray<View>& x) {
std::basic_ostringstream<Char,Traits> s;
s.copyfmt(os); s.width(0);
s << '{';
if (x.size() > 0) {
s << x[0];
for (int i=1; i<x.size(); i++)
s << ", " << x[i];
}
s << '}';
return os << s.str();
}
template<class Char, class Traits, class T>
std::basic_ostream<Char,Traits>&
operator <<(std::basic_ostream<Char,Traits>& os,
const ArgArrayBase<T>& x) {
std::basic_ostringstream<Char,Traits> s;
s.copyfmt(os); s.width(0);
s << '{';
if (x.size() > 0) {
s << x[0];
for (int i=1; i<x.size(); i++)
s << ", " << x[i];
}
s << '}';
return os << s.str();
}
}
// STATISTICS: kernel-other