• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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 
index_range()29     index_range()
30     {
31       start_ = from_start();
32       finish_ = to_end();
33       stride_ = 1;
34       degenerate_ = false;
35     }
36 
index_range(Index pos)37     explicit index_range(Index pos)
38     {
39       start_ = pos;
40       finish_ = pos;
41       stride_ = 1;
42       degenerate_ = true;
43     }
44 
index_range(Index start,Index finish,Index stride=1)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
start(Index s)52     index_range& start(Index s) {
53       start_ = s;
54       degenerate_ = (start_ == finish_);
55       return *this;
56     }
57 
finish(Index f)58     index_range& finish(Index f) {
59       finish_ = f;
60       degenerate_ = (start_ == finish_);
61       return *this;
62     }
63 
stride(Index s)64     index_range& stride(Index s) { stride_ = s; return *this; }
65 
start() const66     Index start() const
67     {
68       return start_;
69     }
70 
get_start(Index low_index_range=0) const71     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 
finish() const78     Index finish() const
79     {
80       return finish_;
81     }
82 
get_finish(Index high_index_range=0) const83     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 
size(Index recommended_length=0) const90     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 
stride() const98     Index stride() const { return stride_; }
99 
is_ascending_contiguous() const100     bool is_ascending_contiguous() const
101     {
102       return (start_ < finish_) && is_unit_stride();
103     }
104 
set_index_range(Index start,Index finish,Index stride=1)105     void set_index_range(Index start, Index finish, Index stride=1)
106     {
107       start_ = start;
108       finish_ = finish;
109       stride_ = stride;
110     }
111 
all()112     static index_range all()
113     { return index_range(from_start(), to_end(), 1); }
114 
is_unit_stride() const115     bool is_unit_stride() const
116     { return stride_ == 1; }
117 
is_degenerate() const118     bool is_degenerate() const { return degenerate_; }
119 
operator -(Index shift) const120     index_range operator-(Index shift) const
121     {
122       return index_range(start_ - shift, finish_ - shift, stride_);
123     }
124 
operator +(Index shift) const125     index_range operator+(Index shift) const
126     {
127       return index_range(start_ + shift, finish_ + shift, stride_);
128     }
129 
operator [](unsigned i) const130     Index operator[](unsigned i) const
131     {
132       return start_ + i * stride_;
133     }
134 
operator ()(unsigned i) const135     Index operator()(unsigned i) const
136     {
137       return start_ + i * stride_;
138     }
139 
140     // add conversion to std::slice?
141 
142   private:
from_start()143     static Index from_start()
144       { return (std::numeric_limits<Index>::min)(); }
145 
to_end()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>
operator <=(Index s,const index_range<Index,SizeType> & r)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>
operator <(Index s,const index_range<Index,SizeType> & r)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>
operator <(const index_range<Index,SizeType> & r,Index f)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>
operator <=(const index_range<Index,SizeType> & r,Index f)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 
index_genindex_gen247   index_gen() { }
248 
249   template <int ND>
index_genindex_gen250   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>
operator []index_gen258   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>
operator []index_gen267   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>
accept_gen(index_gen<NRanges,NDims> & indices)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>
operator [](index_gen<NRanges,NDims> & indices)288   void operator[](index_gen<NRanges,NDims>& indices) {
289 
290   }
291 };
292 
293 template <typename X, typename Y, int A1, int A2>
take_foo(foo<X,Y,A1,A2> & f)294 void take_foo(foo<X,Y,A1,A2>& f) { }
295 
main()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 }
313