2010-03-28 16:08:35 +00:00
|
|
|
// Boost.Range library
|
|
|
|
//
|
|
|
|
// Copyright Neil Groves 2007. 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)
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// For more information, see http://www.boost.org/libs/range/
|
|
|
|
//
|
|
|
|
#ifndef BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
|
|
|
|
#define BOOST_RANGE_ADAPTOR_STRIDED_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include <boost/range/adaptor/argument_fwd.hpp>
|
|
|
|
#include <boost/range/iterator_range.hpp>
|
|
|
|
#include <boost/iterator/iterator_adaptor.hpp>
|
|
|
|
#include <iterator>
|
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2010-03-28 16:08:35 +00:00
|
|
|
namespace boost
|
|
|
|
{
|
2010-04-20 17:54:16 +00:00
|
|
|
namespace range_detail
|
|
|
|
{
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class BaseIterator>
|
2010-04-20 17:54:16 +00:00
|
|
|
class strided_iterator
|
|
|
|
: public iterator_adaptor<
|
2010-12-24 15:00:08 +00:00
|
|
|
strided_iterator<BaseIterator>
|
|
|
|
, BaseIterator
|
|
|
|
>
|
2010-04-20 17:54:16 +00:00
|
|
|
{
|
|
|
|
friend class iterator_core_access;
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
typedef iterator_adaptor<strided_iterator<BaseIterator>, BaseIterator> super_t;
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
public:
|
2010-12-24 15:00:08 +00:00
|
|
|
typedef BOOST_DEDUCED_TYPENAME std::iterator_traits<BaseIterator>::difference_type difference_type;
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
strided_iterator()
|
|
|
|
: m_stride(), m_offset(), m_max_offset()
|
|
|
|
{
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
explicit strided_iterator(BaseIterator base_it,
|
|
|
|
difference_type stride,
|
|
|
|
difference_type offset,
|
|
|
|
difference_type max_offset)
|
|
|
|
: super_t(base_it)
|
|
|
|
, m_stride(stride)
|
|
|
|
, m_offset(offset)
|
|
|
|
, m_max_offset(max_offset)
|
|
|
|
{
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class OtherIterator>
|
|
|
|
strided_iterator(const strided_iterator<OtherIterator>& other,
|
|
|
|
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0)
|
|
|
|
: super_t(other)
|
|
|
|
, m_stride(other.m_stride)
|
|
|
|
, m_offset(other.m_offset)
|
|
|
|
, m_max_offset(other.m_max_offset)
|
|
|
|
{
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
strided_iterator&
|
|
|
|
operator=(const strided_iterator& other)
|
|
|
|
{
|
|
|
|
super_t::operator=(other);
|
|
|
|
m_stride = other.m_stride;
|
2010-12-24 15:00:08 +00:00
|
|
|
m_offset = other.m_offset;
|
|
|
|
m_max_offset = other.m_max_offset;
|
2010-04-20 17:54:16 +00:00
|
|
|
return *this;
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
void increment()
|
|
|
|
{
|
|
|
|
m_offset += m_stride;
|
|
|
|
if (m_offset <= m_max_offset)
|
|
|
|
std::advance(this->base_reference(), m_stride);
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
void decrement()
|
|
|
|
{
|
|
|
|
m_offset -= m_stride;
|
|
|
|
if (m_offset >= 0)
|
|
|
|
std::advance(this->base_reference(), -m_stride);
|
|
|
|
}
|
|
|
|
|
|
|
|
void advance(difference_type n)
|
|
|
|
{
|
|
|
|
n *= m_stride;
|
|
|
|
m_offset += n;
|
|
|
|
|
|
|
|
if (m_offset >= 0 && m_offset <= m_max_offset)
|
|
|
|
std::advance(this->base_reference(), n);
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class OtherIterator>
|
|
|
|
bool equal(const strided_iterator<OtherIterator>& other,
|
|
|
|
BOOST_DEDUCED_TYPENAME enable_if_convertible<OtherIterator, BaseIterator>::type* = 0) const
|
|
|
|
{
|
|
|
|
return m_offset == other.m_offset;
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
difference_type
|
|
|
|
distance_to(const strided_iterator& other) const
|
|
|
|
{
|
2010-12-24 15:00:08 +00:00
|
|
|
return (other.m_offset - m_offset) / m_stride;
|
2010-04-20 17:54:16 +00:00
|
|
|
}
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
private:
|
|
|
|
difference_type m_stride;
|
2010-12-24 15:00:08 +00:00
|
|
|
difference_type m_offset;
|
|
|
|
difference_type m_max_offset;
|
2010-04-20 17:54:16 +00:00
|
|
|
};
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class BaseIterator, class Difference> inline
|
2010-04-20 17:54:16 +00:00
|
|
|
strided_iterator<BaseIterator>
|
|
|
|
make_strided_iterator(
|
|
|
|
const BaseIterator& first,
|
2010-12-24 15:00:08 +00:00
|
|
|
Difference stride,
|
|
|
|
typename std::iterator_traits<BaseIterator>::difference_type offset,
|
|
|
|
typename std::iterator_traits<BaseIterator>::difference_type max_offset
|
|
|
|
)
|
2010-04-20 17:54:16 +00:00
|
|
|
{
|
2010-12-24 15:00:08 +00:00
|
|
|
BOOST_ASSERT( stride >= 0 );
|
|
|
|
BOOST_ASSERT( (stride == 0) || (offset % stride == 0) );
|
|
|
|
BOOST_ASSERT( (stride == 0) || (max_offset % stride == 0) );
|
|
|
|
BOOST_ASSERT( offset <= max_offset );
|
|
|
|
return strided_iterator<BaseIterator>(first, stride, offset, max_offset);
|
2010-04-20 17:54:16 +00:00
|
|
|
}
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template< class Rng >
|
|
|
|
class strided_range
|
|
|
|
: public iterator_range<range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> >
|
|
|
|
{
|
|
|
|
typedef range_detail::strided_iterator<BOOST_DEDUCED_TYPENAME range_iterator<Rng>::type> iter_type;
|
|
|
|
typedef iterator_range<iter_type> super_t;
|
|
|
|
public:
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class Difference>
|
2010-04-20 17:54:16 +00:00
|
|
|
strided_range(Difference stride, Rng& rng)
|
2010-12-24 15:00:08 +00:00
|
|
|
: super_t(make_super(stride, rng))
|
2010-04-20 17:54:16 +00:00
|
|
|
{
|
2010-12-22 22:36:43 +00:00
|
|
|
BOOST_ASSERT( stride >= 0 );
|
|
|
|
}
|
2010-12-24 15:00:08 +00:00
|
|
|
|
2010-12-22 22:36:43 +00:00
|
|
|
private:
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class Difference>
|
|
|
|
static super_t make_super(const Difference stride, Rng& rng)
|
2010-12-22 22:36:43 +00:00
|
|
|
{
|
2010-12-24 15:00:08 +00:00
|
|
|
const Difference count = boost::size(rng);
|
|
|
|
const Difference max_count = max_offset(count, stride);
|
|
|
|
return super_t(make_strided_iterator(boost::begin(rng), stride, 0, max_count),
|
|
|
|
make_strided_iterator(boost::end(rng), stride, max_count, max_count));
|
2010-12-22 22:36:43 +00:00
|
|
|
}
|
|
|
|
|
2010-12-24 15:00:08 +00:00
|
|
|
template<class Difference, class Stride>
|
|
|
|
static Difference max_offset(Difference sz, const Stride stride)
|
2010-12-22 22:36:43 +00:00
|
|
|
{
|
|
|
|
if (stride > 0)
|
|
|
|
{
|
2010-12-24 15:00:08 +00:00
|
|
|
sz += stride - 1;
|
|
|
|
sz /= stride;
|
|
|
|
sz *= stride;
|
2010-12-22 22:36:43 +00:00
|
|
|
}
|
2010-12-24 15:00:08 +00:00
|
|
|
return sz;
|
2010-04-20 17:54:16 +00:00
|
|
|
}
|
|
|
|
};
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template<class Difference>
|
|
|
|
class strided_holder : public holder<Difference>
|
|
|
|
{
|
|
|
|
public:
|
2010-12-22 22:36:43 +00:00
|
|
|
explicit strided_holder(Difference value) : holder<Difference>(value) {}
|
2010-04-20 17:54:16 +00:00
|
|
|
};
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template<class Rng, class Difference>
|
|
|
|
inline strided_range<Rng>
|
|
|
|
operator|(Rng& rng, const strided_holder<Difference>& stride)
|
|
|
|
{
|
|
|
|
return strided_range<Rng>(stride.val, rng);
|
|
|
|
}
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template<class Rng, class Difference>
|
|
|
|
inline strided_range<const Rng>
|
|
|
|
operator|(const Rng& rng, const strided_holder<Difference>& stride)
|
|
|
|
{
|
|
|
|
return strided_range<const Rng>(stride.val, rng);
|
|
|
|
}
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
} // namespace range_detail
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
using range_detail::strided_range;
|
2010-03-28 16:08:35 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
namespace adaptors
|
|
|
|
{
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
namespace
|
|
|
|
{
|
|
|
|
const range_detail::forwarder<range_detail::strided_holder>
|
|
|
|
strided = range_detail::forwarder<range_detail::strided_holder>();
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template<class Range, class Difference>
|
|
|
|
inline strided_range<Range>
|
|
|
|
stride(Range& rng, Difference step)
|
|
|
|
{
|
|
|
|
return strided_range<Range>(step, rng);
|
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
template<class Range, class Difference>
|
|
|
|
inline strided_range<const Range>
|
|
|
|
stride(const Range& rng, Difference step)
|
|
|
|
{
|
|
|
|
return strided_range<const Range>(step, rng);
|
2010-03-28 16:08:35 +00:00
|
|
|
}
|
2010-12-22 22:36:43 +00:00
|
|
|
|
2010-04-20 17:54:16 +00:00
|
|
|
} // namespace 'adaptors'
|
2010-03-28 16:08:35 +00:00
|
|
|
} // namespace 'boost'
|
|
|
|
|
|
|
|
#endif
|