include/utilities/indirect.h
author Christos Mantoulidis <cmad@stanford.edu>
Tue, 04 Aug 2009 13:23:16 -0700
branchdev
changeset 156 f75fb57d2831
parent 137 069596c71902
child 179 d15c6d144645
permissions -rw-r--r--
Changed implementation of WeightedRips to store simplex values (max distance between simplices' vertices) as an invisible layer on top of each simplex object, so that the data() field of WeightedRips has been freed for use by the users again.

#ifndef __INDIRECT_H__
#define __INDIRECT_H__

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <iterator>

// TODO: write documentation


template<class Comparison_>
struct IndirectComparison
{
    typedef         Comparison_                             Comparison;
    
                    IndirectComparison(const Comparison& cmp):
                        cmp_(cmp)
                    {}

    template<class Iterator>
    bool            operator()(Iterator a, Iterator b) const
    { return cmp_(*a, *b); }

    const Comparison&               cmp_;
};
template<class Comparison>
IndirectComparison<Comparison> make_indirect_comparison(const Comparison& cmp)
{ return IndirectComparison<Comparison>(cmp); }


template<class Comparison_>
class FirstComparison
{
    public:
        typedef     Comparison_                             Comparison;

                    FirstComparison(Comparison cmp): 
                        cmp_(cmp)                           {}

        template<class Pair>
        bool        operator()(const Pair& a, const Pair& b) const
        { return cmp_(a.first, b.first); }

    private:
        Comparison  cmp_;
};
template<class Comparison>
FirstComparison<Comparison> make_first_comparison(const Comparison& cmp)
{ return FirstComparison<Comparison>(cmp); }


template<class Comparison>
struct ThreeOutcomeCompare: public Comparison
{
    typedef         typename Comparison::first_argument_type                            first_argument_type;
    typedef         typename Comparison::second_argument_type                           second_argument_type;

                    ThreeOutcomeCompare(const Comparison& cmp = Comparison()): Comparison(cmp)              {}

    int             compare(const first_argument_type& a, const second_argument_type& b) const          
    {   if (operator()(a,b))        return -1;
        else if (operator()(b,a))   return 1;
        else                        return 0;
    }
};

// Iterates over the difference of the two sorted sequences, dereferencing into the first sequence
template<class Iterator1, class Iterator2, class StrictWeakOrdering>
class difference_iterator: public boost::iterator_facade<difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>,
                                                         typename std::iterator_traits<Iterator1>::value_type,
                                                         boost::forward_traversal_tag>
{
    public:
        typedef     typename std::iterator_traits<Iterator1>::reference                 reference;

                    difference_iterator(Iterator1 cur1, Iterator1 end1,
                                        Iterator2 cur2, Iterator2 end2,
                                        const StrictWeakOrdering& cmp = StrictWeakOrdering()):
                        cur1_(cur1), end1_(end1), cur2_(cur2), end2_(end2), cmp_(cmp)   { catchup(); }

    private:
        friend class boost::iterator_core_access;

        void        increment()                                                         { ++cur1_; catchup(); }
        bool        equal(const difference_iterator& other) const                       { return (cur1_ == other.cur1_) && (cur2_ == other.cur2_); }
        reference   dereference() const                                                 { return *cur1_; }

    private:
        Iterator1   cur1_, end1_;
        Iterator2   cur2_, end2_;
        const StrictWeakOrdering&   cmp_;

    private:
        void        catchup()
        {
            while ((cur1_ != end1_) && (cur2_ != end2_))
            {
                if      (cmp_(*cur1_, *cur2_))      break;
                else if (cmp_(*cur2_, *cur1_))      ++cur2_;
                else                                { ++cur1_; ++cur2_; }
            }

            if (cur1_ == end1_)                     cur2_ = end2_;
        }
};

template<class Iterator1, class Iterator2, class StrictWeakOrdering>
difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>
make_difference_iterator(Iterator1 cur1, Iterator1 end1, Iterator2 cur2, Iterator2 end2, const StrictWeakOrdering& cmp)
{ return difference_iterator<Iterator1, Iterator2, StrictWeakOrdering>(cur1, end1, cur2, end2, cmp); }

// Iterates over the intersection of the two sorted sequences, dereferencing into the first sequence
template<class Iterator1, class Iterator2, class StrictWeakOrdering>
class intersection_iterator: public boost::iterator_facade<intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>,
                                                           typename std::iterator_traits<Iterator1>::value_type,
                                                           boost::forward_traversal_tag>
{
    public:
        typedef     typename std::iterator_traits<Iterator1>::reference                 reference;

                    intersection_iterator(Iterator1 cur1, Iterator1 end1,
                                          Iterator2 cur2, Iterator2 end2,
                                          const StrictWeakOrdering& cmp = StrictWeakOrdering()):
                        cur1_(cur1), end1_(end1), cur2_(cur2), end2_(end2), cmp_(cmp)   { catchup(); }

    private:
        friend class boost::iterator_core_access;

        void        increment()                                                         { ++cur1_; ++cur2_; catchup(); }
        bool        equal(const intersection_iterator& other) const                     { return (cur1_ == other.cur1_) && (cur2_ == other.cur2_); }
        reference   dereference() const                                                 { return *cur1_; }

    private:
        Iterator1   cur1_, end1_;
        Iterator2   cur2_, end2_;
        const StrictWeakOrdering&   cmp_;

    private:
        void        catchup()
        {
            while ((cur1_ != end1_) && (cur2_ != end2_))
            {
                if      (cmp_(*cur1_, *cur2_))      ++cur1_;
                else if (cmp_(*cur2_, *cur1_))      ++cur2_;
                else                                break;
            }

            if ((cur1_ == end1_) || (cur2_ == end2_))
            {
                cur1_ = end1_;
                cur2_ = end2_;
            }
        }
};

template<class Iterator1, class Iterator2, class StrictWeakOrdering>
intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>
make_intersection_iterator(Iterator1 cur1, Iterator1 end1, Iterator2 cur2, Iterator2 end2, const StrictWeakOrdering& cmp)
{ return intersection_iterator<Iterator1, Iterator2, StrictWeakOrdering>(cur1, end1, cur2, end2, cmp); }

#endif // __INDIRECT_H__