sort.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // This file is part of libigl, a simple c++ geometry processing library.
  2. //
  3. // Copyright (C) 2013 Alec Jacobson <alecjacobson@gmail.com>
  4. //
  5. // This Source Code Form is subject to the terms of the Mozilla Public License
  6. // v. 2.0. If a copy of the MPL was not distributed with this file, You can
  7. // obtain one at http://mozilla.org/MPL/2.0/.
  8. #include "sort.h"
  9. #include "SortableRow.h"
  10. #include "reorder.h"
  11. #include "IndexComparison.h"
  12. #include "colon.h"
  13. #include <cassert>
  14. #include <algorithm>
  15. #include <iostream>
  16. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  17. IGL_INLINE void igl::sort(
  18. const Eigen::PlainObjectBase<DerivedX>& X,
  19. const int dim,
  20. const bool ascending,
  21. Eigen::PlainObjectBase<DerivedY>& Y,
  22. Eigen::PlainObjectBase<DerivedIX>& IX)
  23. {
  24. // get number of rows (or columns)
  25. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  26. // Special case for swapping
  27. if(num_inner == 2)
  28. {
  29. return igl::sort2(X,dim,ascending,Y,IX);
  30. }
  31. using namespace Eigen;
  32. // get number of columns (or rows)
  33. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  34. // dim must be 2 or 1
  35. assert(dim == 1 || dim == 2);
  36. // Resize output
  37. Y.resize(X.rows(),X.cols());
  38. IX.resize(X.rows(),X.cols());
  39. // idea is to process each column (or row) as a std vector
  40. // loop over columns (or rows)
  41. for(int i = 0; i<num_outer;i++)
  42. {
  43. // Unsorted index map for this column (or row)
  44. std::vector<size_t> index_map(num_inner);
  45. std::vector<double> data(num_inner);
  46. for(int j = 0;j<num_inner;j++)
  47. {
  48. if(dim == 1)
  49. {
  50. data[j] = (double) X(j,i);
  51. }else
  52. {
  53. data[j] = (double) X(i,j);
  54. }
  55. }
  56. // sort this column (or row)
  57. igl::sort( data, ascending, data, index_map);
  58. // Copy into Y and IX
  59. for(int j = 0;j<num_inner;j++)
  60. {
  61. if(dim == 1)
  62. {
  63. Y(j,i) = data[j];
  64. IX(j,i) = index_map[j];
  65. }else
  66. {
  67. Y(i,j) = data[j];
  68. IX(i,j) = index_map[j];
  69. }
  70. }
  71. }
  72. }
  73. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  74. IGL_INLINE void igl::sort_new(
  75. const Eigen::PlainObjectBase<DerivedX>& X,
  76. const int dim,
  77. const bool ascending,
  78. Eigen::PlainObjectBase<DerivedY>& Y,
  79. Eigen::PlainObjectBase<DerivedIX>& IX)
  80. {
  81. // get number of rows (or columns)
  82. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  83. // Special case for swapping
  84. if(num_inner == 2)
  85. {
  86. return igl::sort2(X,dim,ascending,Y,IX);
  87. }
  88. using namespace Eigen;
  89. // get number of columns (or rows)
  90. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  91. // dim must be 2 or 1
  92. assert(dim == 1 || dim == 2);
  93. // Resize output
  94. Y.resize(X.rows(),X.cols());
  95. IX.resize(X.rows(),X.cols());
  96. // idea is to process each column (or row) as a std vector
  97. // loop over columns (or rows)
  98. for(int i = 0; i<num_outer;i++)
  99. {
  100. Eigen::VectorXi ix;
  101. colon(0,num_inner-1,ix);
  102. // Sort the index map, using unsorted for comparison
  103. if(dim == 1)
  104. {
  105. std::sort(
  106. ix.data(),
  107. ix.data()+ix.size(),
  108. igl::IndexVectorLessThan<const typename DerivedX::ConstColXpr >(X.col(i)));
  109. }else
  110. {
  111. std::sort(
  112. ix.data(),
  113. ix.data()+ix.size(),
  114. igl::IndexVectorLessThan<const typename DerivedX::ConstRowXpr >(X.row(i)));
  115. }
  116. // if not ascending then reverse
  117. if(!ascending)
  118. {
  119. std::reverse(ix.data(),ix.data()+ix.size());
  120. }
  121. for(int j = 0;j<num_inner;j++)
  122. {
  123. if(dim == 1)
  124. {
  125. Y(j,i) = X(ix[j],i);
  126. IX(j,i) = ix[j];
  127. }else
  128. {
  129. Y(i,j) = X(i,ix[j]);
  130. IX(i,j) = ix[j];
  131. }
  132. }
  133. }
  134. }
  135. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  136. IGL_INLINE void igl::sort2(
  137. const Eigen::PlainObjectBase<DerivedX>& X,
  138. const int dim,
  139. const bool ascending,
  140. Eigen::PlainObjectBase<DerivedY>& Y,
  141. Eigen::PlainObjectBase<DerivedIX>& IX)
  142. {
  143. using namespace Eigen;
  144. using namespace std;
  145. typedef typename Eigen::PlainObjectBase<DerivedY>::Scalar YScalar;
  146. Y = X.template cast<YScalar>();
  147. // get number of columns (or rows)
  148. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  149. // get number of rows (or columns)
  150. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  151. assert(num_inner == 2);(void)num_inner;
  152. typedef typename Eigen::PlainObjectBase<DerivedIX>::Scalar Index;
  153. IX.resize(X.rows(),X.cols());
  154. if(dim==1)
  155. {
  156. IX.row(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(1,IX.cols());
  157. IX.row(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
  158. }else
  159. {
  160. IX.col(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(IX.rows(),1);
  161. IX.col(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
  162. }
  163. // loop over columns (or rows)
  164. for(int i = 0;i<num_outer;i++)
  165. {
  166. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  167. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  168. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  169. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  170. if((ascending && a>b) || (!ascending && a<b))
  171. {
  172. std::swap(a,b);
  173. std::swap(ai,bi);
  174. }
  175. }
  176. }
  177. template <class T>
  178. IGL_INLINE void igl::sort(
  179. const std::vector<T> & unsorted,
  180. const bool ascending,
  181. std::vector<T> & sorted,
  182. std::vector<size_t> & index_map)
  183. {
  184. // Original unsorted index map
  185. index_map.resize(unsorted.size());
  186. for(size_t i=0;i<unsorted.size();i++)
  187. {
  188. index_map[i] = i;
  189. }
  190. // Sort the index map, using unsorted for comparison
  191. std::sort(
  192. index_map.begin(),
  193. index_map.end(),
  194. igl::IndexLessThan<const std::vector<T>& >(unsorted));
  195. // if not ascending then reverse
  196. if(!ascending)
  197. {
  198. std::reverse(index_map.begin(),index_map.end());
  199. }
  200. // make space for output without clobbering
  201. sorted.resize(unsorted.size());
  202. // reorder unsorted into sorted using index map
  203. igl::reorder(unsorted,index_map,sorted);
  204. }
  205. #ifdef IGL_STATIC_LIBRARY
  206. // Explicit template specialization
  207. // generated by autoexplicit.sh
  208. template void igl::sort<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  209. // generated by autoexplicit.sh
  210. template void igl::sort<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  211. // generated by autoexplicit.sh
  212. template void igl::sort<int>(std::vector<int, std::allocator<int> > const&, bool, std::vector<int, std::allocator<int> >&, std::vector<unsigned long, std::allocator<unsigned long> >&);
  213. // generated by autoexplicit.sh
  214. template void igl::sort<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  215. // generated by autoexplicit.sh
  216. template void igl::sort<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  217. template void igl::sort<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  218. template void igl::sort<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  219. template void igl::sort<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  220. template void igl::sort<Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
  221. template void igl::sort_new<Eigen::Matrix<int, 1, 6, 1, 1, 6>, Eigen::Matrix<int, 1, 6, 1, 1, 6>, Eigen::Matrix<int, 1, 6, 1, 1, 6> >(Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 6, 1, 1, 6> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 6, 1, 1, 6> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, 1, 6, 1, 1, 6> >&);
  222. template void igl::sort<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> >&);
  223. template void igl::sort<Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 4, 0, -1, 4>, Eigen::Matrix<int, -1, 4, 0, -1, 4> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> >&);
  224. template void igl::sort<Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  225. template void igl::sort<long>(std::vector<long, std::allocator<long> > const&, bool, std::vector<long, std::allocator<long> >&, std::vector<unsigned long, std::allocator<unsigned long> >&);
  226. template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  227. template void igl::sort<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  228. template void igl::sort<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  229. template void igl::sort<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  230. template void igl::sort<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  231. #endif
  232. #ifdef _WIN32
  233. template void igl::sort<int>(std::vector<int,std::allocator<int> > const &,bool,std::vector<int,std::allocator<int> > &,std::vector<unsigned long long int,class std::allocator<unsigned long long int> > &);
  234. #endif