This bugzilla service is closed. All entries have been migrated to https://gitlab.com/libeigen/eigen
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: 2019-12-04 16:42 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); }
};
Comment 2 Nobody 2019-12-04 16:42:44 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to gitlab.com's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.com/libeigen/eigen/issues/1374.

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