This forum has been archived. All content is frozen. Please use KDE Discuss instead.

How to sort values in a matrix row?

Tags: None
(comma "," separated)
inverse
Registered Member
Posts
2
Karma
0

How to sort values in a matrix row?

Fri Mar 11, 2011 2:07 am
What the best way to sort values in a dense matrix row? For columns, I have been using the data() member to get a pointer to sort with, as in:

Code: Select all
MatrixXd m(10,10);
...
std::sort(m.col(3).data(), m.col(3).data() + m.rows());


But this fails for sorting rows because the data() pointer is in column order. I was hoping there would be standard iterators for rows or columns blocks, but I couldn't find any in the docs.

So what's the best solution?
inverse
Registered Member
Posts
2
Karma
0
Well I ended up writing a generic iterator that works with Eigen containers (pasted below). This allows you to iterate over any type that has size() and operator[](int) member functions.

It allows you to use it like:

Code: Select all
Eigen::MatrixXd m(100, 20);

auto row_2 = m.row(2);
auto begin = index_begin<double>(row_2);
auto end   = index_end  <double>(row_2);

// sort a row:
std::sort(begin, end);

// copy row to standard library container:
std::vector<double> std_v(begin, end);

// find a value in a row:
std::find(begin, end, 3.14);


Or any other algorithm in the c++ standard library. Here's the iterator code:

Code: Select all
template<typename Value_t, typename Container_t>
class index_iterator : public std::iterator<std::random_access_iterator_tag, Value_t>
{
protected:
   Container_t* container_;
   int          index_;

public:
   index_iterator() : container_(0), index_(0) { }
   index_iterator(Container_t& container, int index) : container_(&container), index_(index) { }

   bool operator==(const index_iterator& other) { return container_ == other.container_ && index_ == other.index_; }
   bool operator!=(const index_iterator& other) { return !(*this == other); }

   Value_t&       operator*()       { return (*container_)[index_]; }
   Value_t const& operator*() const { return (*container_)[index_]; }
   
   Value_t*       operator->()       { return &((*container_)[index_]); }
   Value_t const* operator->() const { return &((*container_)[index_]); }

   index_iterator& operator++() { ++index_; return *this;}
   index_iterator operator++(int) { index_iterator prev(*this); operator++(); return prev;}

   index_iterator& operator--() { --index_; return *this;}
   index_iterator operator--(int) { index_iterator prev(*this); operator--(); return prev;}
   
   friend index_iterator operator+(const index_iterator& a, int b) { index_iterator ret(a); ret += b; return ret; }
   friend index_iterator operator-(const index_iterator& a, int b) { index_iterator ret(a); ret -= b; return ret; }
   friend index_iterator operator+(int a, const index_iterator& b) { index_iterator ret(b); ret += a; return ret; }
   friend index_iterator operator-(int a, const index_iterator& b) { index_iterator ret(b); ret -= a; return ret; }

   int operator-(const index_iterator& other) const { return index_ - other.index_; }

   bool operator< (const index_iterator& other) { return container_ == other.container_ && index_ <  other.index_; }
   bool operator<=(const index_iterator& other) { return container_ == other.container_ && index_ <= other.index_; }
   bool operator> (const index_iterator& other) { return container_ == other.container_ && index_ >  other.index_; }
   bool operator>=(const index_iterator& other) { return container_ == other.container_ && index_ >= other.index_; }

   index_iterator& operator+=(int b) { index_ += b; }
   index_iterator& operator-=(int b) { index_ -= b; }

   Value_t&       operator[](int i)       { return (*container_)[i]; }
   Value_t const& operator[](int i) const { return (*container_)[i]; }
};
template<typename Value_t, typename Container_t>
inline index_iterator<Value_t, Container_t> index_begin(Container_t& container)
{
   return index_iterator<Value_t, Container_t>(container, 0);
}
template<typename Value_t, typename Container_t>
inline index_iterator<Value_t, Container_t> index_end(Container_t& container)
{
   return index_iterator<Value_t, Container_t>(container, container.size());
}
template<typename Value_t, typename Container_t>
inline index_iterator<const Value_t, const Container_t> index_begin(const Container_t& container)
{
   return index_iterator<const Value_t, const Container_t>(container, 0);
}
template<typename Value_t, typename Container_t>
inline index_iterator<const Value_t, const Container_t> index_end(const Container_t& container)
{
   return index_iterator<const Value_t, const Container_t>(container, container.size());
}
User avatar
ggael
Moderator
Posts
3447
Karma
19
OS
thank you for sharing this code, until we integrate such a feature directly inside Eigen, I'm sure it will be very useful to a couple of users.
anjishnub
Registered Member
Posts
3
Karma
0
I was looking to iterate over rows in Eigen and ended up here. Has this been implemented in Eigen?


Bookmarks



Who is online

Registered users: Bing [Bot], Evergrowing, Google [Bot], rockscient