Chris@16
|
1 // Copyright 2002 The Trustees of Indiana University.
|
Chris@16
|
2
|
Chris@16
|
3 // Use, modification and distribution is subject to the Boost Software
|
Chris@16
|
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
5 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
6
|
Chris@16
|
7 // Boost.MultiArray Library
|
Chris@16
|
8 // Authors: Ronald Garcia
|
Chris@16
|
9 // Jeremy Siek
|
Chris@16
|
10 // Andrew Lumsdaine
|
Chris@16
|
11 // See http://www.boost.org/libs/multi_array for documentation.
|
Chris@16
|
12
|
Chris@16
|
13 #ifndef BOOST_INDEX_RANGE_RG071801_HPP
|
Chris@16
|
14 #define BOOST_INDEX_RANGE_RG071801_HPP
|
Chris@16
|
15
|
Chris@16
|
16 #include <boost/config.hpp>
|
Chris@16
|
17 #include <utility>
|
Chris@16
|
18 #include <boost/limits.hpp>
|
Chris@16
|
19
|
Chris@16
|
20 // For representing intervals, also with stride.
|
Chris@16
|
21 // A degenerate range is a range with one element.
|
Chris@16
|
22
|
Chris@16
|
23 // Thanks to Doug Gregor for the really cool idea of using the
|
Chris@16
|
24 // comparison operators to express various interval types!
|
Chris@16
|
25
|
Chris@16
|
26 // Internally, we represent the interval as half-open.
|
Chris@16
|
27
|
Chris@16
|
28 namespace boost {
|
Chris@16
|
29 namespace detail {
|
Chris@16
|
30 namespace multi_array {
|
Chris@16
|
31
|
Chris@16
|
32 template <typename Index,typename SizeType>
|
Chris@16
|
33 class index_range {
|
Chris@16
|
34 public:
|
Chris@16
|
35 typedef Index index;
|
Chris@16
|
36 typedef SizeType size_type;
|
Chris@16
|
37
|
Chris@16
|
38 private:
|
Chris@16
|
39 static index from_start()
|
Chris@16
|
40 { return (std::numeric_limits<index>::min)(); }
|
Chris@16
|
41
|
Chris@16
|
42 static index to_end()
|
Chris@16
|
43 { return (std::numeric_limits<index>::max)(); }
|
Chris@16
|
44
|
Chris@16
|
45 public:
|
Chris@16
|
46
|
Chris@16
|
47 index_range()
|
Chris@16
|
48 {
|
Chris@16
|
49 start_ = from_start();
|
Chris@16
|
50 finish_ = to_end();
|
Chris@16
|
51 stride_ = 1;
|
Chris@16
|
52 degenerate_ = false;
|
Chris@16
|
53 }
|
Chris@16
|
54
|
Chris@16
|
55 explicit index_range(index pos)
|
Chris@16
|
56 {
|
Chris@16
|
57 start_ = pos;
|
Chris@16
|
58 finish_ = pos+1;
|
Chris@16
|
59 stride_ = 1;
|
Chris@16
|
60 degenerate_ = true;
|
Chris@16
|
61 }
|
Chris@16
|
62
|
Chris@16
|
63 explicit index_range(index start, index finish, index stride=1)
|
Chris@16
|
64 : start_(start), finish_(finish), stride_(stride),
|
Chris@16
|
65 degenerate_(false)
|
Chris@16
|
66 { }
|
Chris@16
|
67
|
Chris@16
|
68
|
Chris@16
|
69 // These are for chaining assignments to an index_range
|
Chris@16
|
70 index_range& start(index s) {
|
Chris@16
|
71 start_ = s;
|
Chris@16
|
72 degenerate_ = false;
|
Chris@16
|
73 return *this;
|
Chris@16
|
74 }
|
Chris@16
|
75
|
Chris@16
|
76 index_range& finish(index f) {
|
Chris@16
|
77 finish_ = f;
|
Chris@16
|
78 degenerate_ = false;
|
Chris@16
|
79 return *this;
|
Chris@16
|
80 }
|
Chris@16
|
81
|
Chris@16
|
82 index_range& stride(index s) { stride_ = s; return *this; }
|
Chris@16
|
83
|
Chris@16
|
84 index start() const
|
Chris@16
|
85 {
|
Chris@16
|
86 return start_;
|
Chris@16
|
87 }
|
Chris@16
|
88
|
Chris@16
|
89 index get_start(index low_index_range = index_range::from_start()) const
|
Chris@16
|
90 {
|
Chris@16
|
91 if (start_ == from_start())
|
Chris@16
|
92 return low_index_range;
|
Chris@16
|
93 return start_;
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 index finish() const
|
Chris@16
|
97 {
|
Chris@16
|
98 return finish_;
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 index get_finish(index high_index_range = index_range::to_end()) const
|
Chris@16
|
102 {
|
Chris@16
|
103 if (finish_ == to_end())
|
Chris@16
|
104 return high_index_range;
|
Chris@16
|
105 return finish_;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 index stride() const { return stride_; }
|
Chris@16
|
109
|
Chris@16
|
110 void set_index_range(index start, index finish, index stride=1)
|
Chris@16
|
111 {
|
Chris@16
|
112 start_ = start;
|
Chris@16
|
113 finish_ = finish;
|
Chris@16
|
114 stride_ = stride;
|
Chris@16
|
115 }
|
Chris@16
|
116
|
Chris@16
|
117 static index_range all()
|
Chris@16
|
118 { return index_range(from_start(), to_end(), 1); }
|
Chris@16
|
119
|
Chris@16
|
120 bool is_degenerate() const { return degenerate_; }
|
Chris@16
|
121
|
Chris@16
|
122 index_range operator-(index shift) const
|
Chris@16
|
123 {
|
Chris@16
|
124 return index_range(start_ - shift, finish_ - shift, stride_);
|
Chris@16
|
125 }
|
Chris@16
|
126
|
Chris@16
|
127 index_range operator+(index shift) const
|
Chris@16
|
128 {
|
Chris@16
|
129 return index_range(start_ + shift, finish_ + shift, stride_);
|
Chris@16
|
130 }
|
Chris@16
|
131
|
Chris@16
|
132 index operator[](unsigned i) const
|
Chris@16
|
133 {
|
Chris@16
|
134 return start_ + i * stride_;
|
Chris@16
|
135 }
|
Chris@16
|
136
|
Chris@16
|
137 index operator()(unsigned i) const
|
Chris@16
|
138 {
|
Chris@16
|
139 return start_ + i * stride_;
|
Chris@16
|
140 }
|
Chris@16
|
141
|
Chris@16
|
142 // add conversion to std::slice?
|
Chris@16
|
143
|
Chris@16
|
144 public:
|
Chris@16
|
145 index start_, finish_, stride_;
|
Chris@16
|
146 bool degenerate_;
|
Chris@16
|
147 };
|
Chris@16
|
148
|
Chris@16
|
149 // Express open and closed interval end-points using the comparison
|
Chris@16
|
150 // operators.
|
Chris@16
|
151
|
Chris@16
|
152 // left closed
|
Chris@16
|
153 template <typename Index, typename SizeType>
|
Chris@16
|
154 inline index_range<Index,SizeType>
|
Chris@16
|
155 operator<=(Index s, const index_range<Index,SizeType>& r)
|
Chris@16
|
156 {
|
Chris@16
|
157 return index_range<Index,SizeType>(s, r.finish(), r.stride());
|
Chris@16
|
158 }
|
Chris@16
|
159
|
Chris@16
|
160 // left open
|
Chris@16
|
161 template <typename Index, typename SizeType>
|
Chris@16
|
162 inline index_range<Index,SizeType>
|
Chris@16
|
163 operator<(Index s, const index_range<Index,SizeType>& r)
|
Chris@16
|
164 {
|
Chris@16
|
165 return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
|
Chris@16
|
166 }
|
Chris@16
|
167
|
Chris@16
|
168 // right open
|
Chris@16
|
169 template <typename Index, typename SizeType>
|
Chris@16
|
170 inline index_range<Index,SizeType>
|
Chris@16
|
171 operator<(const index_range<Index,SizeType>& r, Index f)
|
Chris@16
|
172 {
|
Chris@16
|
173 return index_range<Index,SizeType>(r.start(), f, r.stride());
|
Chris@16
|
174 }
|
Chris@16
|
175
|
Chris@16
|
176 // right closed
|
Chris@16
|
177 template <typename Index, typename SizeType>
|
Chris@16
|
178 inline index_range<Index,SizeType>
|
Chris@16
|
179 operator<=(const index_range<Index,SizeType>& r, Index f)
|
Chris@16
|
180 {
|
Chris@16
|
181 return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
|
Chris@16
|
182 }
|
Chris@16
|
183
|
Chris@16
|
184 } // namespace multi_array
|
Chris@16
|
185 } // namespace detail
|
Chris@16
|
186 } // namespace boost
|
Chris@16
|
187
|
Chris@16
|
188 #endif // BOOST_INDEX_RANGE_RG071801_HPP
|