1 #ifndef BOOST_INDEX_RANGE_RG071801_HPP
2 #define BOOST_INDEX_RANGE_RG071801_HPP
4 #include <boost/config.hpp>
6 #include <boost/limits.hpp>
8 // For representing intervals, also with stride.
9 // A degenerate range is a range with one element.
11 // Thanks to Doug Gregor for the really cool idea of using the
12 // comparison operators to express various interval types!
14 // Internally, we represent the interval as half-open.
18 namespace multi_array {
20 template <typename Index,typename SizeType>
24 typedef SizeType size_type;
28 start_ = from_start();
34 explicit index_range(index pos)
42 explicit index_range(index start, index finish, index stride=1)
43 : start_(start), finish_(finish), stride_(stride),
44 degenerate_(start_ == finish_)
48 // These are for chaining assignments to an index_range
49 index_range& start(index s) {
51 degenerate_ = (start_ == finish_);
55 index_range& finish(index f) {
57 degenerate_ = (start_ == finish_);
61 index_range& stride(index s) { stride_ = s; return *this; }
68 index get_start(index low_index_range = 0) const
70 if (start_ == from_start())
71 return low_index_range;
80 index get_finish(index high_index_range = 0) const
82 if (finish_ == to_end())
83 return high_index_range;
87 size_type size(index recommended_length = 0) const
89 if ((start_ == from_start()) || (finish_ == to_end()))
90 return recommended_length;
92 return (finish_ - start_) / stride_;
95 index stride() const { return stride_; }
97 bool is_ascending_contiguous() const
99 return (start_ < finish_) && is_unit_stride();
102 void set_index_range(index start, index finish, index stride=1)
109 static index_range all()
110 { return index_range(from_start(), to_end(), 1); }
112 bool is_unit_stride() const
113 { return stride_ == 1; }
115 bool is_degenerate() const { return degenerate_; }
117 index_range operator-(index shift) const
119 return index_range(start_ - shift, finish_ - shift, stride_);
122 index_range operator+(index shift) const
124 return index_range(start_ + shift, finish_ + shift, stride_);
127 index operator[](unsigned i) const
129 return start_ + i * stride_;
132 index operator()(unsigned i) const
134 return start_ + i * stride_;
137 // add conversion to std::slice?
140 static index from_start()
141 { return std::numeric_limits<index>::min(); }
143 static index to_end()
144 { return std::numeric_limits<index>::max(); }
146 index start_, finish_, stride_;
150 // Express open and closed interval end-points using the comparison
154 template <typename Index, typename SizeType>
155 inline index_range<Index,SizeType>
156 operator<=(Index s, const index_range<Index,SizeType>& r)
158 return index_range<Index,SizeType>(s, r.finish(), r.stride());
162 template <typename Index, typename SizeType>
163 inline index_range<Index,SizeType>
164 operator<(Index s, const index_range<Index,SizeType>& r)
166 return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
170 template <typename Index, typename SizeType>
171 inline index_range<Index,SizeType>
172 operator<(const index_range<Index,SizeType>& r, Index f)
174 return index_range<Index,SizeType>(r.start(), f, r.stride());
178 template <typename Index, typename SizeType>
179 inline index_range<Index,SizeType>
180 operator<=(const index_range<Index,SizeType>& r, Index f)
182 return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
185 } // namespace multi_array
186 } // namespace detail
189 #endif // BOOST_INDEX_RANGE_RG071801_HPP