189 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			189 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // Copyright 2002 The Trustees of Indiana University. | ||
|  | 
 | ||
|  | // Use, modification and distribution is subject to the Boost Software  | ||
|  | // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | ||
|  | // http://www.boost.org/LICENSE_1_0.txt) | ||
|  | 
 | ||
|  | //  Boost.MultiArray Library | ||
|  | //  Authors: Ronald Garcia | ||
|  | //           Jeremy Siek | ||
|  | //           Andrew Lumsdaine | ||
|  | //  See http://www.boost.org/libs/multi_array for documentation. | ||
|  | 
 | ||
|  | #ifndef BOOST_INDEX_RANGE_RG071801_HPP | ||
|  | #define BOOST_INDEX_RANGE_RG071801_HPP | ||
|  | 
 | ||
|  | #include <boost/config.hpp> | ||
|  | #include <utility> | ||
|  | #include <boost/limits.hpp> | ||
|  | 
 | ||
|  | // For representing intervals, also with stride. | ||
|  | // A degenerate range is a range with one element. | ||
|  | 
 | ||
|  | // Thanks to Doug Gregor for the really cool idea of using the | ||
|  | // comparison operators to express various interval types! | ||
|  | 
 | ||
|  | // Internally, we represent the interval as half-open. | ||
|  | 
 | ||
|  | namespace boost { | ||
|  | namespace detail { | ||
|  | namespace multi_array { | ||
|  | 
 | ||
|  |   template <typename Index,typename SizeType> | ||
|  |   class index_range { | ||
|  |   public: | ||
|  |     typedef Index index; | ||
|  |     typedef SizeType size_type; | ||
|  | 
 | ||
|  |   private: | ||
|  |     static index from_start() | ||
|  |       { return (std::numeric_limits<index>::min)(); } | ||
|  | 
 | ||
|  |     static index to_end() | ||
|  |       { return (std::numeric_limits<index>::max)(); } | ||
|  | 
 | ||
|  |   public: | ||
|  | 
 | ||
|  |     index_range() | ||
|  |     { | ||
|  |       start_ = from_start(); | ||
|  |       finish_ = to_end(); | ||
|  |       stride_ = 1; | ||
|  |       degenerate_ = false; | ||
|  |     } | ||
|  | 
 | ||
|  |     explicit index_range(index pos) | ||
|  |     { | ||
|  |       start_ = pos; | ||
|  |       finish_ = pos+1; | ||
|  |       stride_ = 1; | ||
|  |       degenerate_ = true; | ||
|  |     } | ||
|  | 
 | ||
|  |     explicit index_range(index start, index finish, index stride=1) | ||
|  |       : start_(start), finish_(finish), stride_(stride), | ||
|  |         degenerate_(false) | ||
|  |     { } | ||
|  | 
 | ||
|  | 
 | ||
|  |     // These are for chaining assignments to an index_range | ||
|  |     index_range& start(index s) { | ||
|  |       start_ = s; | ||
|  |       degenerate_ = false; | ||
|  |       return *this; | ||
|  |     } | ||
|  | 
 | ||
|  |     index_range& finish(index f) { | ||
|  |       finish_ = f; | ||
|  |       degenerate_ = false; | ||
|  |       return *this; | ||
|  |     } | ||
|  | 
 | ||
|  |     index_range& stride(index s) { stride_ = s; return *this; } | ||
|  | 
 | ||
|  |     index start() const | ||
|  |     {  | ||
|  |       return start_;  | ||
|  |     } | ||
|  | 
 | ||
|  |     index get_start(index low_index_range = index_range::from_start()) const | ||
|  |     {  | ||
|  |       if (start_ == from_start()) | ||
|  |         return low_index_range; | ||
|  |       return start_;  | ||
|  |     } | ||
|  | 
 | ||
|  |     index finish() const | ||
|  |     { | ||
|  |       return finish_; | ||
|  |     } | ||
|  | 
 | ||
|  |     index get_finish(index high_index_range = index_range::to_end()) const | ||
|  |     { | ||
|  |       if (finish_ == to_end()) | ||
|  |         return high_index_range; | ||
|  |       return finish_; | ||
|  |     } | ||
|  | 
 | ||
|  |     index stride() const { return stride_; } | ||
|  | 
 | ||
|  |     void set_index_range(index start, index finish, index stride=1) | ||
|  |     { | ||
|  |       start_ = start; | ||
|  |       finish_ = finish; | ||
|  |       stride_ = stride; | ||
|  |     } | ||
|  | 
 | ||
|  |     static index_range all()  | ||
|  |     { return index_range(from_start(), to_end(), 1); } | ||
|  | 
 | ||
|  |     bool is_degenerate() const { return degenerate_; } | ||
|  | 
 | ||
|  |     index_range operator-(index shift) const | ||
|  |     {  | ||
|  |       return index_range(start_ - shift, finish_ - shift, stride_);  | ||
|  |     } | ||
|  | 
 | ||
|  |     index_range operator+(index shift) const | ||
|  |     {  | ||
|  |       return index_range(start_ + shift, finish_ + shift, stride_);  | ||
|  |     } | ||
|  | 
 | ||
|  |     index operator[](unsigned i) const | ||
|  |     { | ||
|  |       return start_ + i * stride_; | ||
|  |     } | ||
|  | 
 | ||
|  |     index operator()(unsigned i) const | ||
|  |     { | ||
|  |       return start_ + i * stride_; | ||
|  |     } | ||
|  | 
 | ||
|  |     // add conversion to std::slice? | ||
|  | 
 | ||
|  |   public: | ||
|  |     index start_, finish_, stride_; | ||
|  |     bool degenerate_; | ||
|  |   }; | ||
|  | 
 | ||
|  |   // Express open and closed interval end-points using the comparison | ||
|  |   // operators. | ||
|  | 
 | ||
|  |   // left closed | ||
|  |   template <typename Index, typename SizeType> | ||
|  |   inline index_range<Index,SizeType> | ||
|  |   operator<=(Index s, const index_range<Index,SizeType>& r) | ||
|  |   { | ||
|  |     return index_range<Index,SizeType>(s, r.finish(), r.stride()); | ||
|  |   } | ||
|  | 
 | ||
|  |   // left open | ||
|  |   template <typename Index, typename SizeType> | ||
|  |   inline index_range<Index,SizeType> | ||
|  |   operator<(Index s, const index_range<Index,SizeType>& r) | ||
|  |   { | ||
|  |     return index_range<Index,SizeType>(s + 1, r.finish(), r.stride()); | ||
|  |   } | ||
|  | 
 | ||
|  |   // right open | ||
|  |   template <typename Index, typename SizeType> | ||
|  |   inline index_range<Index,SizeType> | ||
|  |   operator<(const index_range<Index,SizeType>& r, Index f) | ||
|  |   { | ||
|  |     return index_range<Index,SizeType>(r.start(), f, r.stride()); | ||
|  |   } | ||
|  | 
 | ||
|  |   // right closed | ||
|  |   template <typename Index, typename SizeType> | ||
|  |   inline index_range<Index,SizeType> | ||
|  |   operator<=(const index_range<Index,SizeType>& r, Index f) | ||
|  |   { | ||
|  |     return index_range<Index,SizeType>(r.start(), f + 1, r.stride()); | ||
|  |   } | ||
|  | 
 | ||
|  | } // namespace multi_array | ||
|  | } // namespace detail   | ||
|  | } // namespace boost | ||
|  | 
 | ||
|  | #endif // BOOST_INDEX_RANGE_RG071801_HPP |