multi_array/test/dimtest.cpp

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;
}