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