You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
188 lines
4.4 KiB
188 lines
4.4 KiB
// 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
|
|
|