// Boost.Range library
//
//  Copyright Neil Groves 2010. 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_IRANGE_HPP_INCLUDED
#define BOOST_RANGE_IRANGE_HPP_INCLUDED

#include <boost/assert.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/range/iterator_range.hpp>

namespace boost
{
    namespace range_detail
    {
        // integer_iterator is an iterator over an integer sequence that
        // is bounded only by the limits of the underlying integer
        // representation.
        //
        // This is useful for implementing the irange(first, last)
        // function.
        //
        // Note:
        // This use of this iterator and irange is appreciably less
        // performant than the corresponding hand-written integer
        // loop on many compilers.
        template<typename Integer>
        class integer_iterator
            : public boost::iterator_facade<
                        integer_iterator<Integer>,
                        Integer,
                        boost::random_access_traversal_tag,
                        Integer,
                        std::ptrdiff_t
                    >
        {
            typedef boost::iterator_facade<
                        integer_iterator<Integer>,
                        Integer,
                        boost::random_access_traversal_tag,
                        Integer,
                        std::ptrdiff_t
                    > base_t;
        public:
            typedef typename base_t::value_type value_type;
            typedef typename base_t::difference_type difference_type;
            typedef typename base_t::reference reference;

            integer_iterator() : m_value() {}
            explicit integer_iterator(value_type x) : m_value(x) {}

        private:
            void increment()
            {
                ++m_value;
            }

            void decrement()
            {
                --m_value;
            }

            void advance(difference_type offset)
            {
                m_value += offset;
            }

            difference_type distance_to(const integer_iterator& other) const
            {
                return other.m_value - m_value;
            }

            bool equal(const integer_iterator& other) const
            {
                return m_value == other.m_value;
            }

            reference dereference() const
            {
                return m_value;
            }

            friend class ::boost::iterator_core_access;
            value_type m_value;
        };

        // integer_iterator_with_step is similar in nature to the
        // integer_iterator but provides the ability to 'move' in
        // a number of steps specified at construction time.
        //
        // The three variable implementation provides the best guarantees
        // of loop termination upon various combinations of input.
        //
        // While this design is less performant than some less
        // safe alternatives, the use of ranges and iterators to
        // perform counting will never be optimal anyhow, hence
        // if optimal performance is desired a handcoded loop
        // is the solution.
        template<typename Integer>
        class integer_iterator_with_step
            : public boost::iterator_facade<
                        integer_iterator_with_step<Integer>,
                        Integer,
                        boost::random_access_traversal_tag,
                        Integer,
                        std::ptrdiff_t
                    >
        {
            typedef boost::iterator_facade<
                        integer_iterator_with_step<Integer>,
                        Integer,
                        boost::random_access_traversal_tag,
                        Integer,
                        std::ptrdiff_t
                    > base_t;
        public:
            typedef typename base_t::value_type value_type;
            typedef typename base_t::difference_type difference_type;
            typedef typename base_t::reference reference;

            integer_iterator_with_step(value_type first, value_type step, difference_type step_size)
                : m_first(first)
                , m_step(step)
                , m_step_size(step_size)
            {
                BOOST_ASSERT( step >= 0 );
                BOOST_ASSERT( step_size != 0 );
            }

        private:
            void increment()
            {
                ++m_step;
            }

            void decrement()
            {
                --m_step;
            }

            void advance(difference_type offset)
            {
                m_step += offset;
            }

            difference_type distance_to(const integer_iterator_with_step& other) const
            {
                return other.m_step - m_step;
            }

            bool equal(const integer_iterator_with_step& other) const
            {
                return m_step == other.m_step;
            }

            reference dereference() const
            {
                return m_first + (m_step * m_step_size);
            }

            friend class ::boost::iterator_core_access;
            value_type m_first;
            value_type m_step;
            difference_type m_step_size;
        };

    } // namespace range_detail

    template<typename Integer>
    class integer_range
        : public iterator_range< range_detail::integer_iterator<Integer> >
    {
        typedef range_detail::integer_iterator<Integer> iterator_t;
        typedef iterator_range<iterator_t> base_t;
    public:
        integer_range(Integer first, Integer last)
            : base_t(iterator_t(first), iterator_t(last))
        {
        }
    };

    template<typename Integer>
    class strided_integer_range
    : public iterator_range< range_detail::integer_iterator_with_step<Integer> >
    {
        typedef range_detail::integer_iterator_with_step<Integer> iterator_t;
        typedef iterator_range<iterator_t> base_t;
    public:
        template<typename Iterator>
        strided_integer_range(Iterator first, Iterator last)
            : base_t(first, last)
        {
        }
    };

    template<typename Integer>
    integer_range<Integer>
    irange(Integer first, Integer last)
    {
        BOOST_ASSERT( first <= last );
        return integer_range<Integer>(first, last);
    }

    template<typename Integer, typename StepSize>
    strided_integer_range<Integer>
        irange(Integer first, Integer last, StepSize step_size)
    {
        BOOST_ASSERT( step_size != 0 );
        BOOST_ASSERT( (step_size > 0) ? (last >= first) : (last <= first) );

        typedef typename range_detail::integer_iterator_with_step<Integer> iterator_t;

        const std::ptrdiff_t last_step
            = (static_cast<std::ptrdiff_t>(last) - static_cast<std::ptrdiff_t>(first))
            / (static_cast<std::ptrdiff_t>(step_size));

        return strided_integer_range<Integer>(
            iterator_t(first, 0, step_size),
            iterator_t(first, last_step, step_size));
    }

} // namespace boost

#endif // include guard
