]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright 2002 The Trustees of Indiana University. |
2 | ||
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) | |
6 | ||
7 | // Boost.MultiArray Library | |
8 | // Authors: Ronald Garcia | |
9 | // Jeremy Siek | |
10 | // Andrew Lumsdaine | |
11 | // See http://www.boost.org/libs/multi_array for documentation. | |
12 | ||
13 | // | |
14 | // Trying to diagnose problems under visual | |
15 | ||
92f5a8d4 TL |
16 | #include <boost/config.hpp> |
17 | #include <boost/array.hpp> | |
18 | #include <boost/limits.hpp> | |
7c673cae FG |
19 | #include <algorithm> |
20 | #include <utility> | |
21 | ||
22 | typedef int index; | |
23 | typedef std::size_t size_type; | |
24 | ||
25 | template <typename Index,typename SizeType> | |
26 | class index_range { | |
27 | public: | |
28 | ||
29 | index_range() | |
30 | { | |
31 | start_ = from_start(); | |
32 | finish_ = to_end(); | |
33 | stride_ = 1; | |
34 | degenerate_ = false; | |
35 | } | |
36 | ||
37 | explicit index_range(Index pos) | |
38 | { | |
39 | start_ = pos; | |
40 | finish_ = pos; | |
41 | stride_ = 1; | |
42 | degenerate_ = true; | |
43 | } | |
44 | ||
45 | explicit index_range(Index start, Index finish, Index stride=1) | |
46 | : start_(start), finish_(finish), stride_(stride), | |
47 | degenerate_(start_ == finish_) | |
48 | { } | |
49 | ||
50 | ||
51 | // These are for chaining assignments to an index_range | |
52 | index_range& start(Index s) { | |
53 | start_ = s; | |
54 | degenerate_ = (start_ == finish_); | |
55 | return *this; | |
56 | } | |
57 | ||
58 | index_range& finish(Index f) { | |
59 | finish_ = f; | |
60 | degenerate_ = (start_ == finish_); | |
61 | return *this; | |
62 | } | |
63 | ||
64 | index_range& stride(Index s) { stride_ = s; return *this; } | |
65 | ||
66 | Index start() const | |
67 | { | |
68 | return start_; | |
69 | } | |
70 | ||
71 | Index get_start(Index low_index_range = 0) const | |
72 | { | |
73 | if (start_ == from_start()) | |
74 | return low_index_range; | |
75 | return start_; | |
76 | } | |
77 | ||
78 | Index finish() const | |
79 | { | |
80 | return finish_; | |
81 | } | |
82 | ||
83 | Index get_finish(Index high_index_range = 0) const | |
84 | { | |
85 | if (finish_ == to_end()) | |
86 | return high_index_range; | |
87 | return finish_; | |
88 | } | |
89 | ||
90 | unsigned int size(Index recommended_length = 0) const | |
91 | { | |
92 | if ((start_ == from_start()) || (finish_ == to_end())) | |
93 | return recommended_length; | |
94 | else | |
95 | return (finish_ - start_) / stride_; | |
96 | } | |
97 | ||
98 | Index stride() const { return stride_; } | |
99 | ||
100 | bool is_ascending_contiguous() const | |
101 | { | |
102 | return (start_ < finish_) && is_unit_stride(); | |
103 | } | |
104 | ||
105 | void set_index_range(Index start, Index finish, Index stride=1) | |
106 | { | |
107 | start_ = start; | |
108 | finish_ = finish; | |
109 | stride_ = stride; | |
110 | } | |
111 | ||
112 | static index_range all() | |
113 | { return index_range(from_start(), to_end(), 1); } | |
114 | ||
115 | bool is_unit_stride() const | |
116 | { return stride_ == 1; } | |
117 | ||
118 | bool is_degenerate() const { return degenerate_; } | |
119 | ||
120 | index_range operator-(Index shift) const | |
121 | { | |
122 | return index_range(start_ - shift, finish_ - shift, stride_); | |
123 | } | |
124 | ||
125 | index_range operator+(Index shift) const | |
126 | { | |
127 | return index_range(start_ + shift, finish_ + shift, stride_); | |
128 | } | |
129 | ||
130 | Index operator[](unsigned i) const | |
131 | { | |
132 | return start_ + i * stride_; | |
133 | } | |
134 | ||
135 | Index operator()(unsigned i) const | |
136 | { | |
137 | return start_ + i * stride_; | |
138 | } | |
139 | ||
140 | // add conversion to std::slice? | |
141 | ||
142 | private: | |
143 | static Index from_start() | |
144 | { return (std::numeric_limits<Index>::min)(); } | |
145 | ||
146 | static Index to_end() | |
147 | { return (std::numeric_limits<Index>::max)(); } | |
148 | public: | |
149 | Index start_, finish_, stride_; | |
150 | bool degenerate_; | |
151 | }; | |
152 | ||
153 | // Express open and closed interval end-points using the comparison | |
154 | // operators. | |
155 | ||
156 | // left closed | |
157 | template <typename Index, typename SizeType> | |
158 | inline index_range<Index,SizeType> | |
159 | operator<=(Index s, const index_range<Index,SizeType>& r) | |
160 | { | |
161 | return index_range<Index,SizeType>(s, r.finish(), r.stride()); | |
162 | } | |
163 | ||
164 | // left open | |
165 | template <typename Index, typename SizeType> | |
166 | inline index_range<Index,SizeType> | |
167 | operator<(Index s, const index_range<Index,SizeType>& r) | |
168 | { | |
169 | return index_range<Index,SizeType>(s + 1, r.finish(), r.stride()); | |
170 | } | |
171 | ||
172 | // right open | |
173 | template <typename Index, typename SizeType> | |
174 | inline index_range<Index,SizeType> | |
175 | operator<(const index_range<Index,SizeType>& r, Index f) | |
176 | { | |
177 | return index_range<Index,SizeType>(r.start(), f, r.stride()); | |
178 | } | |
179 | ||
180 | // right closed | |
181 | template <typename Index, typename SizeType> | |
182 | inline index_range<Index,SizeType> | |
183 | operator<=(const index_range<Index,SizeType>& r, Index f) | |
184 | { | |
185 | return index_range<Index,SizeType>(r.start(), f + 1, r.stride()); | |
186 | } | |
187 | ||
188 | // | |
189 | // range_list.hpp - helper to build boost::arrays for *_set types | |
190 | // | |
191 | ||
192 | ///////////////////////////////////////////////////////////////////////// | |
193 | // choose range list begins | |
194 | // | |
195 | ||
196 | struct choose_range_list_n { | |
197 | template <typename T, std::size_t NumRanges> | |
198 | struct bind { | |
199 | typedef boost::array<T,NumRanges> type; | |
200 | }; | |
201 | }; | |
202 | ||
203 | struct choose_range_list_zero { | |
204 | template <typename T, std::size_t NumRanges> | |
205 | struct bind { | |
206 | typedef boost::array<T,1> type; | |
207 | }; | |
208 | }; | |
209 | ||
210 | ||
211 | template <std::size_t NumRanges> | |
212 | struct range_list_gen_helper { | |
213 | typedef choose_range_list_n choice; | |
214 | }; | |
215 | ||
216 | template <> | |
217 | struct range_list_gen_helper<0> { | |
218 | typedef choose_range_list_zero choice; | |
219 | }; | |
220 | ||
221 | template <typename T, std::size_t NumRanges> | |
222 | struct range_list_generator { | |
223 | private: | |
224 | typedef typename range_list_gen_helper<NumRanges>::choice Choice; | |
225 | public: | |
226 | typedef typename Choice::template bind<T,NumRanges>::type type; | |
227 | }; | |
228 | ||
229 | // | |
230 | // choose range list ends | |
231 | ///////////////////////////////////////////////////////////////////////// | |
232 | ||
233 | // | |
234 | // Index_gen.hpp stuff | |
235 | // | |
236 | ||
237 | template <int NumRanges, int NumDims> | |
238 | struct index_gen { | |
239 | private: | |
240 | typedef index Index; | |
241 | typedef size_type SizeType; | |
242 | typedef index_range<Index,SizeType> range; | |
243 | public: | |
244 | typedef typename range_list_generator<range,NumRanges>::type range_list; | |
245 | range_list ranges_; | |
246 | ||
247 | index_gen() { } | |
248 | ||
249 | template <int ND> | |
250 | explicit index_gen(const index_gen<NumRanges-1,ND>& rhs, | |
251 | const index_range<Index,SizeType>& range) | |
252 | { | |
253 | std::copy(rhs.ranges_.begin(),rhs.ranges_.end(),ranges_.begin()); | |
254 | *ranges_.rbegin() = range; | |
255 | } | |
256 | ||
257 | index_gen<NumRanges+1,NumDims+1> | |
258 | operator[](const index_range<Index,SizeType>& range) const | |
259 | { | |
260 | index_gen<NumRanges+1,NumDims+1> tmp; | |
261 | std::copy(ranges_.begin(),ranges_.end(),tmp.ranges_.begin()); | |
262 | *tmp.ranges_.rbegin() = range; | |
263 | return tmp; | |
264 | } | |
265 | ||
266 | index_gen<NumRanges+1,NumDims> | |
267 | operator[](Index idx) const | |
268 | { | |
269 | index_gen<NumRanges+1,NumDims> tmp; | |
270 | std::copy(ranges_.begin(),ranges_.end(),tmp.ranges_.begin()); | |
271 | *tmp.ranges_.rbegin() = index_range<Index,SizeType>(idx); | |
272 | return tmp; | |
273 | } | |
274 | }; | |
275 | ||
276 | ||
277 | template <int NDims, int NRanges> | |
278 | void accept_gen(index_gen<NRanges,NDims>& indices) { | |
279 | // do nothing | |
280 | } | |
281 | ||
282 | template <typename X, typename Y, int A, int B> | |
283 | class foo { }; | |
284 | ||
285 | class boo { | |
286 | ||
287 | template <int NDims, int NRanges> | |
288 | void operator[](index_gen<NRanges,NDims>& indices) { | |
289 | ||
290 | } | |
291 | }; | |
292 | ||
293 | template <typename X, typename Y, int A1, int A2> | |
294 | void take_foo(foo<X,Y,A1,A2>& f) { } | |
295 | ||
296 | int main() { | |
297 | ||
298 | index_gen<0,0> indices; | |
299 | typedef index_range<index,size_type> range; | |
300 | ||
301 | take_foo(foo<int,std::size_t,1,2>()); | |
302 | ||
303 | indices[range()][range()][range()]; | |
304 | accept_gen(indices); | |
305 | accept_gen(index_gen<0,0>()); | |
306 | accept_gen(indices[range()][range()][range()]); | |
307 | ||
308 | boo b; | |
309 | b[indices[range()][range()][range()]]; | |
310 | ||
311 | return 0; | |
312 | } |