sparse_iterator.h

Back to Iterator

pastel/sys/iterator/

// Description: SparseIterator class
// Detail: An iterator adapter for a larger step size.
// Documentation: iterator.txt

#ifndef PASTELSYS_SPARSE_ITERATOR_H
#define PASTELSYS_SPARSE_ITERATOR_H

#include "pastel/sys/mytypes.h"
#include "pastel/sys/ensure.h"
#include "pastel/sys/range.h"

#include <boost/operators.hpp>

#include <type_traits>
#include <iterator>

namespace Pastel
{

    namespace SparseIterator_
    {

        template <typename Derived, typename Iterator>
        class SparseIteratorHelperBase
            : public boost::random_access_iterator_helper<
            Derived, 
            typename std::iterator_traits<Iterator>::value_type,
            typename std::iterator_traits<Iterator>::difference_type,
            typename std::iterator_traits<Iterator>::pointer,
            typename std::iterator_traits<Iterator>::reference>
        {
        };

        template <typename Derived, typename Iterator>
        class SparseIteratorBase
            : public SparseIterator_::SparseIteratorHelperBase<Derived, Iterator>
        {
        private:
            typedef SparseIterator_::SparseIteratorHelperBase<Derived, Iterator>
                Base;

        public:
            // Using default copy constructor.
            // Using default assignment.
            // Using default destructor.

            SparseIteratorBase()
                : iter_()
                , delta_(0)
            {
            }

            explicit SparseIteratorBase(
                const Iterator& iter,
                typename Base::difference_type delta = 1)
                : iter_(iter)
                , delta_(delta)
            {
            }

            Derived& operator++()
            {
                iter_ += delta_;
                return (Derived&)*this;
            }

            Derived& operator--()
            {
                iter_ -= delta_;
                return (Derived&)*this;
            }

            Derived& operator+=(
                typename Base::difference_type that)
            {
                iter_ += delta_ * that;
                return (Derived&)*this;
            }

            Derived& operator-=(
                typename Base::difference_type that)
            {
                iter_ -= delta_ * that;
                return (Derived&)*this;
            }

            friend typename Base::difference_type operator-(
                const Derived& left, const Derived& right)
            {
                PENSURE_OP(left.delta_, ==, right.delta_);

                return (left.iter_ - right.iter_) / left.delta_;
            }

            typename Base::reference operator*() const
            {
                return *iter_;
            }

            friend bool operator==(
                const Derived& left, const Derived& right)
            {
                return left.iter_ == right.iter_;
            }

            friend bool operator<(
                const Derived& left, const Derived& right)
            {
                return left.iter_ < right.iter_;
            }

        protected:
            Iterator iter_;
            typename Base::difference_type delta_;
        };

    }

    template <typename ConstIterator>
    class ConstSparseIterator;

    template <typename Iterator>
    class SparseIterator
        : public SparseIterator_::SparseIteratorBase<SparseIterator<Iterator>, Iterator>
    {
    private:
        typedef SparseIterator_::SparseIteratorBase<SparseIterator<Iterator>, Iterator>
            Base;

        template <typename ConstIterator>
        friend class ConstSparseIterator;

    public:
        SparseIterator()
            : Base()
        {
        }

        explicit SparseIterator(
            const Iterator& iter,
            typename Base::difference_type delta = 1)
            : Base(iter, delta)
        {
        }
    };

    template <typename ConstIterator>
    class ConstSparseIterator
        : public SparseIterator_::SparseIteratorBase<ConstSparseIterator<ConstIterator>, ConstIterator>
    {
    private:
        typedef SparseIterator_::SparseIteratorBase<ConstSparseIterator<ConstIterator>, ConstIterator>
            Base;

    public:
        ConstSparseIterator()
            : Base()
        {
        }

        template <typename Iterator>
        ConstSparseIterator(
            const SparseIterator<Iterator>& that)
            : Base(that.iter_, that.delta_)
        {
        }

        explicit ConstSparseIterator(
            const ConstIterator& iter,
            integer delta = 1)
            : Base(iter, delta)
        {
        }
    };

    template <typename Iterator>
    SparseIterator<Iterator> sparseIterator(
        const Iterator& that, 
        typename std::iterator_traits<Iterator>::difference_type delta)
    {
        PENSURE_OP(delta, >=, 1);

        return SparseIterator<Iterator>(that, delta);
    }

    template <typename ConstIterator>
    ConstSparseIterator<ConstIterator> constSparseIterator(
        const ConstIterator& that, 
        typename std::iterator_traits<ConstIterator>::difference_type delta)
    {
        PENSURE_OP(delta, >=, 1);

        return ConstSparseIterator<ConstIterator>(that, delta);
    }

    template <typename Iterator>
    SparseIterator<Iterator> sparseEnd(
        const Iterator& begin, const Iterator& end,
        typename std::iterator_traits<Iterator>::difference_type delta)
    {
        PENSURE_OP(delta, >= , 1);

        integer elements = end - begin;
        integer remainder = elements % delta;

        Iterator result = end;
        if (remainder > 0)
        {
            result += delta - remainder;
        }

        return SparseIterator<Iterator>(result, delta);
    }

    template <typename ConstIterator>
    ConstSparseIterator<ConstIterator> constSparseEnd(
        const ConstIterator& begin, const ConstIterator& end,
        typename std::iterator_traits<ConstIterator>::difference_type delta)
    {
        PENSURE_OP(delta, >=, 1);

        return sparseEnd(begin, end, delta);
    }

    template <typename Iterator>
    boost::iterator_range<SparseIterator<Iterator> > sparseRange(
        const Iterator& begin, const Iterator& end,
        typename std::iterator_traits<Iterator>::difference_type delta)
    {
        PENSURE_OP(delta, >=, 1);

        return Pastel::range(
            sparseIterator(begin, delta),
            sparseEnd(begin, end, delta));
    }

    template <typename ConstIterator>
    boost::iterator_range<ConstSparseIterator<ConstIterator> > constSparseRange(
        const ConstIterator& begin, const ConstIterator& end,
        typename std::iterator_traits<ConstIterator>::difference_type delta)
    {
        PENSURE_OP(delta, >=, 1);

        return Pastel::range(
            constSparseIterator(begin, delta),
            constSparseEnd(begin, end, delta));
    }

}

#endif