#ifndef IGL_SORT_H #define IGL_SORT_H #include #include namespace igl { // Sort the elements of a matrix X along a given dimension like matlabs sort // function // // Templates: // T should be a eigen matrix primitive type like int or double // Inputs: // X m by n matrix whose entries are to be sorted // dim dimensional along which to sort: // 1 sort each column (matlab default) // 2 sort each row // ascending sort ascending (true, matlab default) or descending (false) // Outputs: // Y m by n matrix whose entries are sorted // IX m by n matrix of indices so that if dim = 1, then in matlab notation // for j = 1:n, Y(:,j) = X(I(:,j),j); end template inline void sort( const Eigen::Matrix & X, const int dim, const bool ascending, Eigen::Matrix & Y, Eigen::MatrixXi & IX); // Act like matlab's [Y,I] = SORT(X) for std library vectors // Templates: // T should be a class that implements the '<' comparator operator // Input: // unsorted unsorted vector // ascending sort ascending (true, matlab default) or descending (false) // Output: // sorted sorted vector, allowed to be same as unsorted // index_map an index map such that sorted[i] = unsorted[index_map[i]] template inline void sort( const std::vector &unsorted, const bool ascending, std::vector &sorted, std::vector &index_map); } // Implementation #include #include "reorder.h" template inline void igl::sort( const Eigen::Matrix & X, const int dim, const bool ascending, Eigen::Matrix & Y, Eigen::MatrixXi & IX) { // dim must be 2 or 1 assert(dim == 1 || dim == 2); // Resize output Y.resize(X.rows(),X.cols()); IX.resize(X.rows(),X.cols()); // idea is to process each column (or row) as a std vector // get number of columns (or rows) int num_outer = (dim == 1 ? X.cols() : X.rows() ); // get number of rows (or columns) int num_inner = (dim == 1 ? X.rows() : X.cols() ); // loop over columns (or rows) for(int i = 0; i index_map(num_inner); std::vector data(num_inner); for(int j = 0;j( data, ascending, data, index_map); // Copy into Y and IX for(int j = 0;j struct index_cmp { index_cmp(const T arr) : arr(arr) {} bool operator()(const size_t a, const size_t b) const { return arr[a] < arr[b]; } const T arr; }; } template inline void igl::sort( const std::vector & unsorted, const bool ascending, std::vector & sorted, std::vector & index_map) { // Original unsorted index map index_map.resize(unsorted.size()); for(size_t i=0;i& >(unsorted)); // if not ascending then reverse if(!ascending) { std::reverse(index_map.begin(),index_map.end()); } // make space for output without clobbering sorted.resize(unsorted.size()); // reorder unsorted into sorted using index map igl::reorder(unsorted,index_map,sorted); } #endif