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