Chris@16: // Copyright 2002 The Trustees of Indiana University. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software Chris@16: // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: // Boost.MultiArray Library Chris@16: // Authors: Ronald Garcia Chris@16: // Jeremy Siek Chris@16: // Andrew Lumsdaine Chris@16: // See http://www.boost.org/libs/multi_array for documentation. Chris@16: Chris@16: #ifndef BOOST_INDEX_RANGE_RG071801_HPP Chris@16: #define BOOST_INDEX_RANGE_RG071801_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: // For representing intervals, also with stride. Chris@16: // A degenerate range is a range with one element. Chris@16: Chris@16: // Thanks to Doug Gregor for the really cool idea of using the Chris@16: // comparison operators to express various interval types! Chris@16: Chris@16: // Internally, we represent the interval as half-open. Chris@16: Chris@16: namespace boost { Chris@16: namespace detail { Chris@16: namespace multi_array { Chris@16: Chris@16: template Chris@16: class index_range { Chris@16: public: Chris@16: typedef Index index; Chris@16: typedef SizeType size_type; Chris@16: Chris@16: private: Chris@16: static index from_start() Chris@16: { return (std::numeric_limits::min)(); } Chris@16: Chris@16: static index to_end() Chris@16: { return (std::numeric_limits::max)(); } Chris@16: Chris@16: public: Chris@16: Chris@16: index_range() Chris@16: { Chris@16: start_ = from_start(); Chris@16: finish_ = to_end(); Chris@16: stride_ = 1; Chris@16: degenerate_ = false; Chris@16: } Chris@16: Chris@16: explicit index_range(index pos) Chris@16: { Chris@16: start_ = pos; Chris@16: finish_ = pos+1; Chris@16: stride_ = 1; Chris@16: degenerate_ = true; Chris@16: } Chris@16: Chris@16: explicit index_range(index start, index finish, index stride=1) Chris@16: : start_(start), finish_(finish), stride_(stride), Chris@16: degenerate_(false) Chris@16: { } Chris@16: Chris@16: Chris@16: // These are for chaining assignments to an index_range Chris@16: index_range& start(index s) { Chris@16: start_ = s; Chris@16: degenerate_ = false; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: index_range& finish(index f) { Chris@16: finish_ = f; Chris@16: degenerate_ = false; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: index_range& stride(index s) { stride_ = s; return *this; } Chris@16: Chris@16: index start() const Chris@16: { Chris@16: return start_; Chris@16: } Chris@16: Chris@16: index get_start(index low_index_range = index_range::from_start()) const Chris@16: { Chris@16: if (start_ == from_start()) Chris@16: return low_index_range; Chris@16: return start_; Chris@16: } Chris@16: Chris@16: index finish() const Chris@16: { Chris@16: return finish_; Chris@16: } Chris@16: Chris@16: index get_finish(index high_index_range = index_range::to_end()) const Chris@16: { Chris@16: if (finish_ == to_end()) Chris@16: return high_index_range; Chris@16: return finish_; Chris@16: } Chris@16: Chris@16: index stride() const { return stride_; } Chris@16: Chris@16: void set_index_range(index start, index finish, index stride=1) Chris@16: { Chris@16: start_ = start; Chris@16: finish_ = finish; Chris@16: stride_ = stride; Chris@16: } Chris@16: Chris@16: static index_range all() Chris@16: { return index_range(from_start(), to_end(), 1); } Chris@16: Chris@16: bool is_degenerate() const { return degenerate_; } Chris@16: Chris@16: index_range operator-(index shift) const Chris@16: { Chris@16: return index_range(start_ - shift, finish_ - shift, stride_); Chris@16: } Chris@16: Chris@16: index_range operator+(index shift) const Chris@16: { Chris@16: return index_range(start_ + shift, finish_ + shift, stride_); Chris@16: } Chris@16: Chris@16: index operator[](unsigned i) const Chris@16: { Chris@16: return start_ + i * stride_; Chris@16: } Chris@16: Chris@16: index operator()(unsigned i) const Chris@16: { Chris@16: return start_ + i * stride_; Chris@16: } Chris@16: Chris@16: // add conversion to std::slice? Chris@16: Chris@16: public: Chris@16: index start_, finish_, stride_; Chris@16: bool degenerate_; Chris@16: }; Chris@16: Chris@16: // Express open and closed interval end-points using the comparison Chris@16: // operators. Chris@16: Chris@16: // left closed Chris@16: template Chris@16: inline index_range Chris@16: operator<=(Index s, const index_range& r) Chris@16: { Chris@16: return index_range(s, r.finish(), r.stride()); Chris@16: } Chris@16: Chris@16: // left open Chris@16: template Chris@16: inline index_range Chris@16: operator<(Index s, const index_range& r) Chris@16: { Chris@16: return index_range(s + 1, r.finish(), r.stride()); Chris@16: } Chris@16: Chris@16: // right open Chris@16: template Chris@16: inline index_range Chris@16: operator<(const index_range& r, Index f) Chris@16: { Chris@16: return index_range(r.start(), f, r.stride()); Chris@16: } Chris@16: Chris@16: // right closed Chris@16: template Chris@16: inline index_range Chris@16: operator<=(const index_range& r, Index f) Chris@16: { Chris@16: return index_range(r.start(), f + 1, r.stride()); Chris@16: } Chris@16: Chris@16: } // namespace multi_array Chris@16: } // namespace detail Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_INDEX_RANGE_RG071801_HPP