1 // Copyright 2002 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Boost.MultiArray Library
8 // Authors: Ronald Garcia
11 // See http://www.boost.org/libs/multi_array for documentation.
13 #ifndef BOOST_INDEX_RANGE_RG071801_HPP
14 #define BOOST_INDEX_RANGE_RG071801_HPP
16 #include <boost/config.hpp>
18 #include <boost/limits.hpp>
20 // For representing intervals, also with stride.
21 // A degenerate range is a range with one element.
23 // Thanks to Doug Gregor for the really cool idea of using the
24 // comparison operators to express various interval types!
26 // Internally, we represent the interval as half-open.
30 namespace multi_array {
32 template <typename Index,typename SizeType>
36 typedef SizeType size_type;
40 start_ = from_start();
46 explicit index_range(index pos)
54 explicit index_range(index start, index finish, index stride=1)
55 : start_(start), finish_(finish), stride_(stride),
60 // These are for chaining assignments to an index_range
61 index_range& start(index s) {
63 degenerate_ = (start_ == finish_);
67 index_range& finish(index f) {
69 degenerate_ = (start_ == finish_);
73 index_range& stride(index s) { stride_ = s; return *this; }
80 index get_start(index low_index_range = 0) const
82 if (start_ == from_start())
83 return low_index_range;
92 index get_finish(index high_index_range = 0) const
94 if (finish_ == to_end())
95 return high_index_range;
99 size_type size(index recommended_length = 0) const
101 if ((start_ == from_start()) || (finish_ == to_end()))
102 return recommended_length;
104 return (finish_ - start_) / stride_;
107 index stride() const { return stride_; }
109 bool is_ascending_contiguous() const
111 return (start_ < finish_) && is_unit_stride();
114 void set_index_range(index start, index finish, index stride=1)
121 static index_range all()
122 { return index_range(from_start(), to_end(), 1); }
124 bool is_unit_stride() const
125 { return stride_ == 1; }
127 bool is_degenerate() const { return degenerate_; }
129 index_range operator-(index shift) const
131 return index_range(start_ - shift, finish_ - shift, stride_);
134 index_range operator+(index shift) const
136 return index_range(start_ + shift, finish_ + shift, stride_);
139 index operator[](unsigned i) const
141 return start_ + i * stride_;
144 index operator()(unsigned i) const
146 return start_ + i * stride_;
149 // add conversion to std::slice?
152 static index from_start()
153 { return (std::numeric_limits<index>::min)(); }
155 static index to_end()
156 { return (std::numeric_limits<index>::max)(); }
158 index start_, finish_, stride_;
162 // Express open and closed interval end-points using the comparison
166 template <typename Index, typename SizeType>
167 inline index_range<Index,SizeType>
168 operator<=(Index s, const index_range<Index,SizeType>& r)
170 return index_range<Index,SizeType>(s, r.finish(), r.stride());
174 template <typename Index, typename SizeType>
175 inline index_range<Index,SizeType>
176 operator<(Index s, const index_range<Index,SizeType>& r)
178 return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
182 template <typename Index, typename SizeType>
183 inline index_range<Index,SizeType>
184 operator<(const index_range<Index,SizeType>& r, Index f)
186 return index_range<Index,SizeType>(r.start(), f, r.stride());
190 template <typename Index, typename SizeType>
191 inline index_range<Index,SizeType>
192 operator<=(const index_range<Index,SizeType>& r, Index f)
194 return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
197 } // namespace multi_array
198 } // namespace detail
201 #endif // BOOST_INDEX_RANGE_RG071801_HPP