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
16#include <boost/config.hpp>
17#include <boost/array.hpp>
18#include <boost/limits.hpp>
19#include <algorithm>
20#include <utility>
21
22typedef int index;
23typedef 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
196struct 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
203struct 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
211template <std::size_t NumRanges>
212struct range_list_gen_helper {
213 typedef choose_range_list_n choice;
214};
215
216template <>
217struct range_list_gen_helper<0> {
218 typedef choose_range_list_zero choice;
219};
220
221template <typename T, std::size_t NumRanges>
222struct range_list_generator {
223private:
224 typedef typename range_list_gen_helper<NumRanges>::choice Choice;
225public:
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
237template <int NumRanges, int NumDims>
238struct index_gen {
239private:
240 typedef index Index;
241 typedef size_type SizeType;
242 typedef index_range<Index,SizeType> range;
243public:
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
277template <int NDims, int NRanges>
278void accept_gen(index_gen<NRanges,NDims>& indices) {
279 // do nothing
280}
281
282template <typename X, typename Y, int A, int B>
283class foo { };
284
285class boo {
286
287 template <int NDims, int NRanges>
288 void operator[](index_gen<NRanges,NDims>& indices) {
289
290 }
291};
292
293template <typename X, typename Y, int A1, int A2>
294void take_foo(foo<X,Y,A1,A2>& f) { }
295
296int 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}
313

source code of boost/libs/multi_array/test/dimtest.cpp