Using std::nth_element to sort rows of an arma::mat

  armadillo, c++, nth-element, overloading, swap

As the title mentions my goal is to use std::nth_element on a Armadillo-Matrix which contains a set of N points in d dimensions, i.e. a Nxd matrix. The rows represent a d-dimensional point.
The comparison of two rows should be done along a fixed dimension, i.e.

row(i) < row(j) iff A(i, s) < A(j,s)
(comparing the s-entry of each row).

My idea was now to use the column-iterators provided by Armadillo and overload the std::swap function to be used with two column-iterators and my desired swap:

void swap(arma::mat::col_iterator& lhs, arma::mat::col_iterator& rhs)
{
    lhs->M->swap_rows(lhs->current_row, rhs->current_row);
}

Here I use the swap_rows methods build in arma::mat. The call to std::nth_element looks like this:

// Setting indices to indicate which submatrix should be sorted:
arma::uword first = nodes[currentNodeIndex].indexFirstElem;
arma::uword last  = nodes[currentNodeIndex].indexLastElem + 1;
arma::uword nth = (last - first) / 2;    
// Calling std::nth_element:
std::nth_element(points.begin_col(first), points.begin_col(nth), points.begin_col(last));

Now the problem is that I get compiler-errors when overloading swap in the above manner:

    kd_tree.cpp: In function ‘void swap(double*&, double*&)’:
kd_tree.cpp:25:7: error: request for member ‘M’ in ‘* lhs’, which is of non-class type ‘double’
   25 |  lhs->M->swap_rows(lhs->current_row, rhs->current_row);
      |       ^
kd_tree.cpp:25:25: error: request for member ‘current_row’ in ‘* lhs’, which is of non-class type ‘double’
   25 |  lhs->M->swap_rows(lhs->current_row, rhs->current_row);
      |                         ^~~~~~~~~~~
kd_tree.cpp:25:43: error: request for member ‘current_row’ in ‘* rhs’, which is of non-class type ‘double’
   25 |  lhs->M->swap_rows(lhs->current_row, rhs->current_row);

I guess the errors tell me that the column-iterator is not able to access the matrix M on which it operates? Also it seems like I cannot access the current_row where my iterator is at.
I tried looking at the armadillo-documentation but there was no further information on the actual interface of said iterator apart from its existence and how to initialize it with begin(). Also looking through the actual code of armadillo did not help me as I haven’t found the definition of arma:mat::col_iterator.

So my question is what do the above errors tell me and how can I fix this? Also if you happen to know a better approach to the described problem that would be highly appreciated as well. 🙂

Beforehand I tried writing a custom random-access-operator for the rows of arma::mat but this failed as I could not overload value_type& operator*() { return A.row(i); } as A.row(i) seems to return a temporary arma::vec object or something.

Source: Windows Questions C++

LEAVE A COMMENT