index_range.hpp 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2002 The Trustees of Indiana University.
  2. // Use, modification and distribution is subject to the Boost Software
  3. // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  4. // http://www.boost.org/LICENSE_1_0.txt)
  5. // Boost.MultiArray Library
  6. // Authors: Ronald Garcia
  7. // Jeremy Siek
  8. // Andrew Lumsdaine
  9. // See http://www.boost.org/libs/multi_array for documentation.
  10. #ifndef BOOST_INDEX_RANGE_RG071801_HPP
  11. #define BOOST_INDEX_RANGE_RG071801_HPP
  12. #include <boost/config.hpp>
  13. #include <utility>
  14. #include <boost/limits.hpp>
  15. // For representing intervals, also with stride.
  16. // A degenerate range is a range with one element.
  17. // Thanks to Doug Gregor for the really cool idea of using the
  18. // comparison operators to express various interval types!
  19. // Internally, we represent the interval as half-open.
  20. namespace boost {
  21. namespace detail {
  22. namespace multi_array {
  23. template <typename Index,typename SizeType>
  24. class index_range {
  25. public:
  26. typedef Index index;
  27. typedef SizeType size_type;
  28. private:
  29. static index from_start()
  30. { return (std::numeric_limits<index>::min)(); }
  31. static index to_end()
  32. { return (std::numeric_limits<index>::max)(); }
  33. public:
  34. index_range()
  35. {
  36. start_ = from_start();
  37. finish_ = to_end();
  38. stride_ = 1;
  39. degenerate_ = false;
  40. }
  41. explicit index_range(index pos)
  42. {
  43. start_ = pos;
  44. finish_ = pos+1;
  45. stride_ = 1;
  46. degenerate_ = true;
  47. }
  48. explicit index_range(index start, index finish, index stride=1)
  49. : start_(start), finish_(finish), stride_(stride),
  50. degenerate_(false)
  51. { }
  52. // These are for chaining assignments to an index_range
  53. index_range& start(index s) {
  54. start_ = s;
  55. degenerate_ = false;
  56. return *this;
  57. }
  58. index_range& finish(index f) {
  59. finish_ = f;
  60. degenerate_ = false;
  61. return *this;
  62. }
  63. index_range& stride(index s) { stride_ = s; return *this; }
  64. index start() const
  65. {
  66. return start_;
  67. }
  68. index get_start(index low_index_range = index_range::from_start()) const
  69. {
  70. if (start_ == from_start())
  71. return low_index_range;
  72. return start_;
  73. }
  74. index finish() const
  75. {
  76. return finish_;
  77. }
  78. index get_finish(index high_index_range = index_range::to_end()) const
  79. {
  80. if (finish_ == to_end())
  81. return high_index_range;
  82. return finish_;
  83. }
  84. index stride() const { return stride_; }
  85. void set_index_range(index start, index finish, index stride=1)
  86. {
  87. start_ = start;
  88. finish_ = finish;
  89. stride_ = stride;
  90. }
  91. static index_range all()
  92. { return index_range(from_start(), to_end(), 1); }
  93. bool is_degenerate() const { return degenerate_; }
  94. index_range operator-(index shift) const
  95. {
  96. return index_range(start_ - shift, finish_ - shift, stride_);
  97. }
  98. index_range operator+(index shift) const
  99. {
  100. return index_range(start_ + shift, finish_ + shift, stride_);
  101. }
  102. index operator[](unsigned i) const
  103. {
  104. return start_ + i * stride_;
  105. }
  106. index operator()(unsigned i) const
  107. {
  108. return start_ + i * stride_;
  109. }
  110. // add conversion to std::slice?
  111. public:
  112. index start_, finish_, stride_;
  113. bool degenerate_;
  114. };
  115. // Express open and closed interval end-points using the comparison
  116. // operators.
  117. // left closed
  118. template <typename Index, typename SizeType>
  119. inline index_range<Index,SizeType>
  120. operator<=(Index s, const index_range<Index,SizeType>& r)
  121. {
  122. return index_range<Index,SizeType>(s, r.finish(), r.stride());
  123. }
  124. // left open
  125. template <typename Index, typename SizeType>
  126. inline index_range<Index,SizeType>
  127. operator<(Index s, const index_range<Index,SizeType>& r)
  128. {
  129. return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
  130. }
  131. // right open
  132. template <typename Index, typename SizeType>
  133. inline index_range<Index,SizeType>
  134. operator<(const index_range<Index,SizeType>& r, Index f)
  135. {
  136. return index_range<Index,SizeType>(r.start(), f, r.stride());
  137. }
  138. // right closed
  139. template <typename Index, typename SizeType>
  140. inline index_range<Index,SizeType>
  141. operator<=(const index_range<Index,SizeType>& r, Index f)
  142. {
  143. return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
  144. }
  145. } // namespace multi_array
  146. } // namespace detail
  147. } // namespace boost
  148. #endif // BOOST_INDEX_RANGE_RG071801_HPP