source: NonGTP/Boost/boost/multi_array/index_range.hpp @ 857

Revision 857, 5.0 KB checked in by igarcia, 18 years ago (diff)
Line 
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#ifndef BOOST_INDEX_RANGE_RG071801_HPP
14#define BOOST_INDEX_RANGE_RG071801_HPP
15
16#include <boost/config.hpp>
17#include <utility>
18#include <boost/limits.hpp>
19
20// For representing intervals, also with stride.
21// A degenerate range is a range with one element.
22
23// Thanks to Doug Gregor for the really cool idea of using the
24// comparison operators to express various interval types!
25
26// Internally, we represent the interval as half-open.
27
28namespace boost {
29namespace detail {
30namespace multi_array {
31
32  template <typename Index,typename SizeType>
33  class index_range {
34  public:
35    typedef Index index;
36    typedef SizeType size_type;
37
38    index_range()
39    {
40      start_ = from_start();
41      finish_ = to_end();
42      stride_ = 1;
43      degenerate_ = false;
44    }
45
46    explicit index_range(index pos)
47    {
48      start_ = pos;
49      finish_ = pos;
50      stride_ = 1;
51      degenerate_ = true;
52    }
53
54    explicit index_range(index start, index finish, index stride=1)
55      : start_(start), finish_(finish), stride_(stride),
56        degenerate_(false)
57    { }
58
59
60    // These are for chaining assignments to an index_range
61    index_range& start(index s) {
62      start_ = s;
63      degenerate_ = (start_ == finish_);
64      return *this;
65    }
66
67    index_range& finish(index f) {
68      finish_ = f;
69      degenerate_ = (start_ == finish_);
70      return *this;
71    }
72
73    index_range& stride(index s) { stride_ = s; return *this; }
74
75    index start() const
76    {
77      return start_;
78    }
79
80    index get_start(index low_index_range = 0) const
81    {
82      if (start_ == from_start())
83        return low_index_range;
84      return start_;
85    }
86
87    index finish() const
88    {
89      return finish_;
90    }
91
92    index get_finish(index high_index_range = 0) const
93    {
94      if (finish_ == to_end())
95        return high_index_range;
96      return finish_;
97    }
98
99    size_type size(index recommended_length = 0) const
100    {
101      if ((start_ == from_start()) || (finish_ == to_end()))
102        return recommended_length;
103      else
104        return (finish_ - start_) / stride_;
105    }
106
107    index stride() const { return stride_; }
108
109    bool is_ascending_contiguous() const
110    {
111      return (start_ < finish_) && is_unit_stride();
112    }
113
114    void set_index_range(index start, index finish, index stride=1)
115    {
116      start_ = start;
117      finish_ = finish;
118      stride_ = stride;
119    }
120
121    static index_range all()
122    { return index_range(from_start(), to_end(), 1); }
123
124    bool is_unit_stride() const
125    { return stride_ == 1; }
126
127    bool is_degenerate() const { return degenerate_; }
128
129    index_range operator-(index shift) const
130    {
131      return index_range(start_ - shift, finish_ - shift, stride_);
132    }
133
134    index_range operator+(index shift) const
135    {
136      return index_range(start_ + shift, finish_ + shift, stride_);
137    }
138
139    index operator[](unsigned i) const
140    {
141      return start_ + i * stride_;
142    }
143
144    index operator()(unsigned i) const
145    {
146      return start_ + i * stride_;
147    }
148
149    // add conversion to std::slice?
150
151  private:
152    static index from_start()
153      { return (std::numeric_limits<index>::min)(); }
154
155    static index to_end()
156      { return (std::numeric_limits<index>::max)(); }
157  public:
158    index start_, finish_, stride_;
159    bool degenerate_;
160  };
161
162  // Express open and closed interval end-points using the comparison
163  // operators.
164
165  // left closed
166  template <typename Index, typename SizeType>
167  inline index_range<Index,SizeType>
168  operator<=(Index s, const index_range<Index,SizeType>& r)
169  {
170    return index_range<Index,SizeType>(s, r.finish(), r.stride());
171  }
172
173  // left open
174  template <typename Index, typename SizeType>
175  inline index_range<Index,SizeType>
176  operator<(Index s, const index_range<Index,SizeType>& r)
177  {
178    return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
179  }
180
181  // right open
182  template <typename Index, typename SizeType>
183  inline index_range<Index,SizeType>
184  operator<(const index_range<Index,SizeType>& r, Index f)
185  {
186    return index_range<Index,SizeType>(r.start(), f, r.stride());
187  }
188
189  // right closed
190  template <typename Index, typename SizeType>
191  inline index_range<Index,SizeType>
192  operator<=(const index_range<Index,SizeType>& r, Index f)
193  {
194    return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
195  }
196
197} // namespace multi_array
198} // namespace detail 
199} // namespace boost
200
201#endif // BOOST_INDEX_RANGE_RG071801_HPP
Note: See TracBrowser for help on using the repository browser.