New user self-registration is disabled due to spam. Please email eigen-core-team @ lists.tuxfamily.org if you need an account.
Before reporting a bug, please make sure that your Eigen version is up-to-date!
Bug 1374 - Sane Iterator for Eigen::SparseMatrix
Summary: Sane Iterator for Eigen::SparseMatrix
Status: NEW
Alias: None
Product: Eigen
Classification: Unclassified
Component: Sparse (show other bugs)
Version: 3.3 (current stable)
Hardware: All All
: Normal Unknown
Assignee: Nobody
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-01-14 23:51 UTC by citibeth
Modified: 2017-01-14 23:52 UTC (History)
2 users (show)



Attachments

Description citibeth 2017-01-14 23:51:49 UTC
I finally wrote a sane, easy-to-use iterator for Eigen::SparseMatrix.  See below...  Although I haven't tried it, I believe this iterator is compatible with Eigen::SparseMatrix::setFromTriplets().



#define ARGS _Scalar,_Options,_StorageIndex
template<class _Scalar, int _Options, class _StorageIndex>
class EigenSparseMatrixIterator :
    public ibmisc::forward_iterator<
        EigenSparseMatrixIterator<ARGS>,
        EigenSparseMatrixIterator<ARGS>>
{
    typedef EigenSparseMatrixIterator<ARGS> IteratorT;
public:
    typedef _StorageIndex index_type;
    typedef _Scalar val_type;
    static const int RANK = 2;

    Eigen::SparseMatrix<ARGS> const &M;
    int k;
    typename Eigen::SparseMatrix<ARGS>::InnerIterator ii;
    
    EigenSparseMatrixIterator(Eigen::SparseMatrix<ARGS> const &_M, int _k)
        : M(_M), k(_k),
        ii(typename Eigen::SparseMatrix<ARGS>::InnerIterator(M,k)) {}

    // ---------------------------------------------------------
    // http://www.cplusplus.com/reference/iterator/

    IteratorT &operator++() {    // Prefix ++
        ++ii;
        if (!ii) {
            ++k;
            ii.~InnerIterator();
            new (&ii) typename Eigen::SparseMatrix<ARGS>::InnerIterator(M,k);
        }
        return *this;
    }

    bool operator==(IteratorT const &other) const
        { return (k == other->k) && (ii == other->ii); }
//    bool operator==(IteratorT const other) const
//        { return (k == other->k) && (ii == other->ii); }

    IteratorT &operator*()
        { return *this; }
    IteratorT const &operator*() const
        { return *this; }
//    IteratorT *operator->()
//        { return this; }

    // ---------- What you get once you dereference

    _Scalar const &value()
        { return ii.value(); }
    _StorageIndex row()
        { return ii.row(); }
    _StorageIndex col()
        { return ii.col(); }
    _StorageIndex index(int ix)
        { return ix == 0 ? row() : col(); }
    std::array<_StorageIndex,2> index()
        { return {row(), col()}; }
};

// -----------------------------------

template<class _Scalar, int _Options, class _StorageIndex>
EigenSparseMatrixIterator<ARGS> begin(Eigen::SparseMatrix<ARGS> const &M)
    { return EigenSparseMatrixIterator<ARGS>(M,0); }

template<class _Scalar, int _Options, class _StorageIndex>
EigenSparseMatrixIterator<ARGS> end(Eigen::SparseMatrix<ARGS> const &M)
    { return EigenSparseMatrixIterator<ARGS>(M,M.outerSize()); }

#undef ARGS
Comment 1 citibeth 2017-01-14 23:52:37 UTC
Here is ibmisc::forward_iterator, used above.


template<class ValueT, class DerivedT>
class forward_iterator : public std::iterator<std::forward_iterator_tag, ValueT>
{
    DerivedT *derived()
        { return static_cast<DerivedT *>(this); }
    DerivedT const *derived() const
        { return static_cast<DerivedT const *>(this); }
public:
    ValueT *operator->()
        { return &derived()->operator*(); }
    ValueT const *operator->() const
        { return &derived()->operator*(); }

    DerivedT operator++(int)
    {
        DerivedT clone(derived());
        derived()->operator+=(1);
        return clone;
    }

    bool operator!=(const DerivedT& rhs) const
        {return !derived()->operator==(rhs); }
};

Note You need to log in before you can comment on or make changes to this bug.