// 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 |