| 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 | |
|---|
| 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 | } |
|---|