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 28 namespace boost { 29 namespace detail { 30 namespace 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 index_range()38 index_range() 39 { 40 start_ = from_start(); 41 finish_ = to_end(); 42 stride_ = 1; 43 degenerate_ = false; 44 } 45 index_range(index pos)46 explicit index_range(index pos) 47 { 48 start_ = pos; 49 finish_ = pos; 50 stride_ = 1; 51 degenerate_ = true; 52 } 53 index_range(index start,index finish,index stride=1)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 start(index s)61 index_range& start(index s) { 62 start_ = s; 63 degenerate_ = (start_ == finish_); 64 return *this; 65 } 66 finish(index f)67 index_range& finish(index f) { 68 finish_ = f; 69 degenerate_ = (start_ == finish_); 70 return *this; 71 } 72 stride(index s)73 index_range& stride(index s) { stride_ = s; return *this; } 74 start() const75 index start() const 76 { 77 return start_; 78 } 79 get_start(index low_index_range=0) const80 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 finish() const87 index finish() const 88 { 89 return finish_; 90 } 91 get_finish(index high_index_range=0) const92 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 size(index recommended_length=0) const99 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 stride() const107 index stride() const { return stride_; } 108 is_ascending_contiguous() const109 bool is_ascending_contiguous() const 110 { 111 return (start_ < finish_) && is_unit_stride(); 112 } 113 set_index_range(index start,index finish,index stride=1)114 void set_index_range(index start, index finish, index stride=1) 115 { 116 start_ = start; 117 finish_ = finish; 118 stride_ = stride; 119 } 120 all()121 static index_range all() 122 { return index_range(from_start(), to_end(), 1); } 123 is_unit_stride() const124 bool is_unit_stride() const 125 { return stride_ == 1; } 126 is_degenerate() const127 bool is_degenerate() const { return degenerate_; } 128 operator -(index shift) const129 index_range operator-(index shift) const 130 { 131 return index_range(start_ - shift, finish_ - shift, stride_); 132 } 133 operator +(index shift) const134 index_range operator+(index shift) const 135 { 136 return index_range(start_ + shift, finish_ + shift, stride_); 137 } 138 operator [](unsigned i) const139 index operator[](unsigned i) const 140 { 141 return start_ + i * stride_; 142 } 143 operator ()(unsigned i) const144 index operator()(unsigned i) const 145 { 146 return start_ + i * stride_; 147 } 148 149 // add conversion to std::slice? 150 151 private: from_start()152 static index from_start() 153 { return (std::numeric_limits<index>::min)(); } 154 to_end()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> operator <=(Index s,const index_range<Index,SizeType> & r)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> operator <(Index s,const index_range<Index,SizeType> & r)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> operator <(const index_range<Index,SizeType> & r,Index f)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> operator <=(const index_range<Index,SizeType> & r,Index f)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 202