| // 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. |
| |
| #ifndef BOOST_INDEX_RANGE_RG071801_HPP |
| #define BOOST_INDEX_RANGE_RG071801_HPP |
| |
| #include <boost/config.hpp> |
| #include <utility> |
| #include <boost/limits.hpp> |
| |
| // For representing intervals, also with stride. |
| // A degenerate range is a range with one element. |
| |
| // Thanks to Doug Gregor for the really cool idea of using the |
| // comparison operators to express various interval types! |
| |
| // Internally, we represent the interval as half-open. |
| |
| namespace boost { |
| namespace detail { |
| namespace multi_array { |
| |
| template <typename Index,typename SizeType> |
| class index_range { |
| public: |
| typedef Index index; |
| typedef SizeType size_type; |
| |
| private: |
| static index from_start() |
| { return (std::numeric_limits<index>::min)(); } |
| |
| static index to_end() |
| { return (std::numeric_limits<index>::max)(); } |
| |
| public: |
| |
| index_range() |
| { |
| start_ = from_start(); |
| finish_ = to_end(); |
| stride_ = 1; |
| degenerate_ = false; |
| } |
| |
| explicit index_range(index pos) |
| { |
| start_ = pos; |
| finish_ = pos+1; |
| stride_ = 1; |
| degenerate_ = true; |
| } |
| |
| explicit index_range(index start, index finish, index stride=1) |
| : start_(start), finish_(finish), stride_(stride), |
| degenerate_(false) |
| { } |
| |
| |
| // These are for chaining assignments to an index_range |
| index_range& start(index s) { |
| start_ = s; |
| degenerate_ = false; |
| return *this; |
| } |
| |
| index_range& finish(index f) { |
| finish_ = f; |
| degenerate_ = false; |
| return *this; |
| } |
| |
| index_range& stride(index s) { stride_ = s; return *this; } |
| |
| index start() const |
| { |
| return start_; |
| } |
| |
| index get_start(index low_index_range = index_range::from_start()) const |
| { |
| if (start_ == from_start()) |
| return low_index_range; |
| return start_; |
| } |
| |
| index finish() const |
| { |
| return finish_; |
| } |
| |
| index get_finish(index high_index_range = index_range::to_end()) const |
| { |
| if (finish_ == to_end()) |
| return high_index_range; |
| return finish_; |
| } |
| |
| index stride() const { return 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_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? |
| |
| 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()); |
| } |
| |
| } // namespace multi_array |
| } // namespace detail |
| } // namespace boost |
| |
| #endif // BOOST_INDEX_RANGE_RG071801_HPP |