313 lines
7.1 KiB
C++
313 lines
7.1 KiB
C++
// Copyright 2002 The Trustees of Indiana University.
|
|
|
|
// Use, modification and distribution is subject to the Boost Software
|
|
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
|
// http://www.boost.org/LICENSE_1_0.txt)
|
|
|
|
// Boost.MultiArray Library
|
|
// Authors: Ronald Garcia
|
|
// Jeremy Siek
|
|
// Andrew Lumsdaine
|
|
// See http://www.boost.org/libs/multi_array for documentation.
|
|
|
|
//
|
|
// Trying to diagnose problems under visual
|
|
|
|
#include <boost/config.hpp>
|
|
#include <boost/array.hpp>
|
|
#include <boost/limits.hpp>
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
typedef int index;
|
|
typedef std::size_t size_type;
|
|
|
|
template <typename Index,typename SizeType>
|
|
class index_range {
|
|
public:
|
|
|
|
index_range()
|
|
{
|
|
start_ = from_start();
|
|
finish_ = to_end();
|
|
stride_ = 1;
|
|
degenerate_ = false;
|
|
}
|
|
|
|
explicit index_range(Index pos)
|
|
{
|
|
start_ = pos;
|
|
finish_ = pos;
|
|
stride_ = 1;
|
|
degenerate_ = true;
|
|
}
|
|
|
|
explicit index_range(Index start, Index finish, Index stride=1)
|
|
: start_(start), finish_(finish), stride_(stride),
|
|
degenerate_(start_ == finish_)
|
|
{ }
|
|
|
|
|
|
// These are for chaining assignments to an index_range
|
|
index_range& start(Index s) {
|
|
start_ = s;
|
|
degenerate_ = (start_ == finish_);
|
|
return *this;
|
|
}
|
|
|
|
index_range& finish(Index f) {
|
|
finish_ = f;
|
|
degenerate_ = (start_ == finish_);
|
|
return *this;
|
|
}
|
|
|
|
index_range& stride(Index s) { stride_ = s; return *this; }
|
|
|
|
Index start() const
|
|
{
|
|
return start_;
|
|
}
|
|
|
|
Index get_start(Index low_index_range = 0) const
|
|
{
|
|
if (start_ == from_start())
|
|
return low_index_range;
|
|
return start_;
|
|
}
|
|
|
|
Index finish() const
|
|
{
|
|
return finish_;
|
|
}
|
|
|
|
Index get_finish(Index high_index_range = 0) const
|
|
{
|
|
if (finish_ == to_end())
|
|
return high_index_range;
|
|
return finish_;
|
|
}
|
|
|
|
unsigned int size(Index recommended_length = 0) const
|
|
{
|
|
if ((start_ == from_start()) || (finish_ == to_end()))
|
|
return recommended_length;
|
|
else
|
|
return (finish_ - start_) / stride_;
|
|
}
|
|
|
|
Index stride() const { return stride_; }
|
|
|
|
bool is_ascending_contiguous() const
|
|
{
|
|
return (start_ < finish_) && is_unit_stride();
|
|
}
|
|
|
|
void set_index_range(Index start, Index finish, Index stride=1)
|
|
{
|
|
start_ = start;
|
|
finish_ = finish;
|
|
stride_ = stride;
|
|
}
|
|
|
|
static index_range all()
|
|
{ return index_range(from_start(), to_end(), 1); }
|
|
|
|
bool is_unit_stride() const
|
|
{ return stride_ == 1; }
|
|
|
|
bool is_degenerate() const { return degenerate_; }
|
|
|
|
index_range operator-(Index shift) const
|
|
{
|
|
return index_range(start_ - shift, finish_ - shift, stride_);
|
|
}
|
|
|
|
index_range operator+(Index shift) const
|
|
{
|
|
return index_range(start_ + shift, finish_ + shift, stride_);
|
|
}
|
|
|
|
Index operator[](unsigned i) const
|
|
{
|
|
return start_ + i * stride_;
|
|
}
|
|
|
|
Index operator()(unsigned i) const
|
|
{
|
|
return start_ + i * stride_;
|
|
}
|
|
|
|
// add conversion to std::slice?
|
|
|
|
private:
|
|
static Index from_start()
|
|
{ return (std::numeric_limits<Index>::min)(); }
|
|
|
|
static Index to_end()
|
|
{ return (std::numeric_limits<Index>::max)(); }
|
|
public:
|
|
Index start_, finish_, stride_;
|
|
bool degenerate_;
|
|
};
|
|
|
|
// Express open and closed interval end-points using the comparison
|
|
// operators.
|
|
|
|
// left closed
|
|
template <typename Index, typename SizeType>
|
|
inline index_range<Index,SizeType>
|
|
operator<=(Index s, const index_range<Index,SizeType>& r)
|
|
{
|
|
return index_range<Index,SizeType>(s, r.finish(), r.stride());
|
|
}
|
|
|
|
// left open
|
|
template <typename Index, typename SizeType>
|
|
inline index_range<Index,SizeType>
|
|
operator<(Index s, const index_range<Index,SizeType>& r)
|
|
{
|
|
return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
|
|
}
|
|
|
|
// right open
|
|
template <typename Index, typename SizeType>
|
|
inline index_range<Index,SizeType>
|
|
operator<(const index_range<Index,SizeType>& r, Index f)
|
|
{
|
|
return index_range<Index,SizeType>(r.start(), f, r.stride());
|
|
}
|
|
|
|
// right closed
|
|
template <typename Index, typename SizeType>
|
|
inline index_range<Index,SizeType>
|
|
operator<=(const index_range<Index,SizeType>& r, Index f)
|
|
{
|
|
return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
|
|
}
|
|
|
|
//
|
|
// range_list.hpp - helper to build boost::arrays for *_set types
|
|
//
|
|
|
|
/////////////////////////////////////////////////////////////////////////
|
|
// choose range list begins
|
|
//
|
|
|
|
struct choose_range_list_n {
|
|
template <typename T, std::size_t NumRanges>
|
|
struct bind {
|
|
typedef boost::array<T,NumRanges> type;
|
|
};
|
|
};
|
|
|
|
struct choose_range_list_zero {
|
|
template <typename T, std::size_t NumRanges>
|
|
struct bind {
|
|
typedef boost::array<T,1> type;
|
|
};
|
|
};
|
|
|
|
|
|
template <std::size_t NumRanges>
|
|
struct range_list_gen_helper {
|
|
typedef choose_range_list_n choice;
|
|
};
|
|
|
|
template <>
|
|
struct range_list_gen_helper<0> {
|
|
typedef choose_range_list_zero choice;
|
|
};
|
|
|
|
template <typename T, std::size_t NumRanges>
|
|
struct range_list_generator {
|
|
private:
|
|
typedef typename range_list_gen_helper<NumRanges>::choice Choice;
|
|
public:
|
|
typedef typename Choice::template bind<T,NumRanges>::type type;
|
|
};
|
|
|
|
//
|
|
// choose range list ends
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
// Index_gen.hpp stuff
|
|
//
|
|
|
|
template <int NumRanges, int NumDims>
|
|
struct index_gen {
|
|
private:
|
|
typedef index Index;
|
|
typedef size_type SizeType;
|
|
typedef index_range<Index,SizeType> range;
|
|
public:
|
|
typedef typename range_list_generator<range,NumRanges>::type range_list;
|
|
range_list ranges_;
|
|
|
|
index_gen() { }
|
|
|
|
template <int ND>
|
|
explicit index_gen(const index_gen<NumRanges-1,ND>& rhs,
|
|
const index_range<Index,SizeType>& range)
|
|
{
|
|
std::copy(rhs.ranges_.begin(),rhs.ranges_.end(),ranges_.begin());
|
|
*ranges_.rbegin() = range;
|
|
}
|
|
|
|
index_gen<NumRanges+1,NumDims+1>
|
|
operator[](const index_range<Index,SizeType>& range) const
|
|
{
|
|
index_gen<NumRanges+1,NumDims+1> tmp;
|
|
std::copy(ranges_.begin(),ranges_.end(),tmp.ranges_.begin());
|
|
*tmp.ranges_.rbegin() = range;
|
|
return tmp;
|
|
}
|
|
|
|
index_gen<NumRanges+1,NumDims>
|
|
operator[](Index idx) const
|
|
{
|
|
index_gen<NumRanges+1,NumDims> tmp;
|
|
std::copy(ranges_.begin(),ranges_.end(),tmp.ranges_.begin());
|
|
*tmp.ranges_.rbegin() = index_range<Index,SizeType>(idx);
|
|
return tmp;
|
|
}
|
|
};
|
|
|
|
|
|
template <int NDims, int NRanges>
|
|
void accept_gen(index_gen<NRanges,NDims>& indices) {
|
|
// do nothing
|
|
}
|
|
|
|
template <typename X, typename Y, int A, int B>
|
|
class foo { };
|
|
|
|
class boo {
|
|
|
|
template <int NDims, int NRanges>
|
|
void operator[](index_gen<NRanges,NDims>& indices) {
|
|
|
|
}
|
|
};
|
|
|
|
template <typename X, typename Y, int A1, int A2>
|
|
void take_foo(foo<X,Y,A1,A2>& f) { }
|
|
|
|
int main() {
|
|
|
|
index_gen<0,0> indices;
|
|
typedef index_range<index,size_type> range;
|
|
|
|
take_foo(foo<int,std::size_t,1,2>());
|
|
|
|
indices[range()][range()][range()];
|
|
accept_gen(indices);
|
|
accept_gen(index_gen<0,0>());
|
|
accept_gen(indices[range()][range()][range()]);
|
|
|
|
boo b;
|
|
b[indices[range()][range()][range()]];
|
|
|
|
return 0;
|
|
}
|