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