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