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