index_range.hpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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_MULTI_ARRAY_INDEX_RANGE_HPP
  11. #define BOOST_MULTI_ARRAY_INDEX_RANGE_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. size_type size(index idx) const
  86. {
  87. return (start_ == from_start() || finish_ == to_end())
  88. ? idx : ((finish_ - start_) / stride_);
  89. }
  90. void set_index_range(index start, index finish, index stride=1)
  91. {
  92. start_ = start;
  93. finish_ = finish;
  94. stride_ = stride;
  95. }
  96. static index_range all()
  97. { return index_range(from_start(), to_end(), 1); }
  98. bool is_degenerate() const { return degenerate_; }
  99. index_range operator-(index shift) const
  100. {
  101. return index_range(start_ - shift, finish_ - shift, stride_);
  102. }
  103. index_range operator+(index shift) const
  104. {
  105. return index_range(start_ + shift, finish_ + shift, stride_);
  106. }
  107. index operator[](unsigned i) const
  108. {
  109. return start_ + i * stride_;
  110. }
  111. index operator()(unsigned i) const
  112. {
  113. return start_ + i * stride_;
  114. }
  115. // add conversion to std::slice?
  116. public:
  117. index start_, finish_, stride_;
  118. bool degenerate_;
  119. };
  120. // Express open and closed interval end-points using the comparison
  121. // operators.
  122. // left closed
  123. template <typename Index, typename SizeType>
  124. inline index_range<Index,SizeType>
  125. operator<=(Index s, const index_range<Index,SizeType>& r)
  126. {
  127. return index_range<Index,SizeType>(s, r.finish(), r.stride());
  128. }
  129. // left open
  130. template <typename Index, typename SizeType>
  131. inline index_range<Index,SizeType>
  132. operator<(Index s, const index_range<Index,SizeType>& r)
  133. {
  134. return index_range<Index,SizeType>(s + 1, r.finish(), r.stride());
  135. }
  136. // right open
  137. template <typename Index, typename SizeType>
  138. inline index_range<Index,SizeType>
  139. operator<(const index_range<Index,SizeType>& r, Index f)
  140. {
  141. return index_range<Index,SizeType>(r.start(), f, r.stride());
  142. }
  143. // right closed
  144. template <typename Index, typename SizeType>
  145. inline index_range<Index,SizeType>
  146. operator<=(const index_range<Index,SizeType>& r, Index f)
  147. {
  148. return index_range<Index,SizeType>(r.start(), f + 1, r.stride());
  149. }
  150. } // namespace multi_array
  151. } // namespace detail
  152. } // namespace boost
  153. #endif