sort.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  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 "parallel_for.h"
  14. #include <cassert>
  15. #include <algorithm>
  16. #include <iostream>
  17. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  18. IGL_INLINE void igl::sort(
  19. const Eigen::PlainObjectBase<DerivedX>& X,
  20. const int dim,
  21. const bool ascending,
  22. Eigen::PlainObjectBase<DerivedY>& Y,
  23. Eigen::PlainObjectBase<DerivedIX>& IX)
  24. {
  25. // get number of rows (or columns)
  26. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  27. // Special case for swapping
  28. switch(num_inner)
  29. {
  30. default:
  31. break;
  32. case 2:
  33. return igl::sort2(X,dim,ascending,Y,IX);
  34. case 3:
  35. return igl::sort3(X,dim,ascending,Y,IX);
  36. }
  37. using namespace Eigen;
  38. // get number of columns (or rows)
  39. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  40. // dim must be 2 or 1
  41. assert(dim == 1 || dim == 2);
  42. // Resize output
  43. Y.resize(X.rows(),X.cols());
  44. IX.resize(X.rows(),X.cols());
  45. // idea is to process each column (or row) as a std vector
  46. // loop over columns (or rows)
  47. for(int i = 0; i<num_outer;i++)
  48. {
  49. // Unsorted index map for this column (or row)
  50. std::vector<size_t> index_map(num_inner);
  51. std::vector<double> data(num_inner);
  52. for(int j = 0;j<num_inner;j++)
  53. {
  54. if(dim == 1)
  55. {
  56. data[j] = (double) X(j,i);
  57. }else
  58. {
  59. data[j] = (double) X(i,j);
  60. }
  61. }
  62. // sort this column (or row)
  63. igl::sort( data, ascending, data, index_map);
  64. // Copy into Y and IX
  65. for(int j = 0;j<num_inner;j++)
  66. {
  67. if(dim == 1)
  68. {
  69. Y(j,i) = data[j];
  70. IX(j,i) = index_map[j];
  71. }else
  72. {
  73. Y(i,j) = data[j];
  74. IX(i,j) = index_map[j];
  75. }
  76. }
  77. }
  78. }
  79. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  80. IGL_INLINE void igl::sort_new(
  81. const Eigen::PlainObjectBase<DerivedX>& X,
  82. const int dim,
  83. const bool ascending,
  84. Eigen::PlainObjectBase<DerivedY>& Y,
  85. Eigen::PlainObjectBase<DerivedIX>& IX)
  86. {
  87. // get number of rows (or columns)
  88. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  89. // Special case for swapping
  90. switch(num_inner)
  91. {
  92. default:
  93. break;
  94. case 2:
  95. return igl::sort2(X,dim,ascending,Y,IX);
  96. case 3:
  97. return igl::sort3(X,dim,ascending,Y,IX);
  98. }
  99. using namespace Eigen;
  100. // get number of columns (or rows)
  101. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  102. // dim must be 2 or 1
  103. assert(dim == 1 || dim == 2);
  104. // Resize output
  105. Y.resize(X.rows(),X.cols());
  106. IX.resize(X.rows(),X.cols());
  107. // idea is to process each column (or row) as a std vector
  108. // loop over columns (or rows)
  109. for(int i = 0; i<num_outer;i++)
  110. {
  111. Eigen::VectorXi ix;
  112. colon(0,num_inner-1,ix);
  113. // Sort the index map, using unsorted for comparison
  114. if(dim == 1)
  115. {
  116. std::sort(
  117. ix.data(),
  118. ix.data()+ix.size(),
  119. igl::IndexVectorLessThan<const typename DerivedX::ConstColXpr >(X.col(i)));
  120. }else
  121. {
  122. std::sort(
  123. ix.data(),
  124. ix.data()+ix.size(),
  125. igl::IndexVectorLessThan<const typename DerivedX::ConstRowXpr >(X.row(i)));
  126. }
  127. // if not ascending then reverse
  128. if(!ascending)
  129. {
  130. std::reverse(ix.data(),ix.data()+ix.size());
  131. }
  132. for(int j = 0;j<num_inner;j++)
  133. {
  134. if(dim == 1)
  135. {
  136. Y(j,i) = X(ix[j],i);
  137. IX(j,i) = ix[j];
  138. }else
  139. {
  140. Y(i,j) = X(i,ix[j]);
  141. IX(i,j) = ix[j];
  142. }
  143. }
  144. }
  145. }
  146. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  147. IGL_INLINE void igl::sort2(
  148. const Eigen::PlainObjectBase<DerivedX>& X,
  149. const int dim,
  150. const bool ascending,
  151. Eigen::PlainObjectBase<DerivedY>& Y,
  152. Eigen::PlainObjectBase<DerivedIX>& IX)
  153. {
  154. using namespace Eigen;
  155. using namespace std;
  156. typedef typename Eigen::PlainObjectBase<DerivedY>::Scalar YScalar;
  157. Y = X.template cast<YScalar>();
  158. // get number of columns (or rows)
  159. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  160. // get number of rows (or columns)
  161. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  162. assert(num_inner == 2);(void)num_inner;
  163. typedef typename Eigen::PlainObjectBase<DerivedIX>::Scalar Index;
  164. IX.resize(X.rows(),X.cols());
  165. if(dim==1)
  166. {
  167. IX.row(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(1,IX.cols());
  168. IX.row(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
  169. }else
  170. {
  171. IX.col(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(IX.rows(),1);
  172. IX.col(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
  173. }
  174. // loop over columns (or rows)
  175. for(int i = 0;i<num_outer;i++)
  176. {
  177. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  178. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  179. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  180. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  181. if((ascending && a>b) || (!ascending && a<b))
  182. {
  183. std::swap(a,b);
  184. std::swap(ai,bi);
  185. }
  186. }
  187. }
  188. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  189. IGL_INLINE void igl::sort3(
  190. const Eigen::PlainObjectBase<DerivedX>& X,
  191. const int dim,
  192. const bool ascending,
  193. Eigen::PlainObjectBase<DerivedY>& Y,
  194. Eigen::PlainObjectBase<DerivedIX>& IX)
  195. {
  196. using namespace Eigen;
  197. using namespace std;
  198. typedef typename Eigen::PlainObjectBase<DerivedY>::Scalar YScalar;
  199. Y = X.template cast<YScalar>();
  200. // get number of columns (or rows)
  201. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  202. // get number of rows (or columns)
  203. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  204. assert(num_inner == 3);(void)num_inner;
  205. typedef typename Eigen::PlainObjectBase<DerivedIX>::Scalar Index;
  206. IX.resize(X.rows(),X.cols());
  207. if(dim==1)
  208. {
  209. IX.row(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(1,IX.cols());
  210. IX.row(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
  211. IX.row(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (1,IX.cols());
  212. }else
  213. {
  214. IX.col(0).setConstant(0);// = Eigen::PlainObjectBase<DerivedIX>::Zero(IX.rows(),1);
  215. IX.col(1).setConstant(1);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
  216. IX.col(2).setConstant(2);// = Eigen::PlainObjectBase<DerivedIX>::Ones (IX.rows(),1);
  217. }
  218. const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
  219. {
  220. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  221. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  222. YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
  223. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  224. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  225. Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
  226. if(ascending)
  227. {
  228. // 123 132 213 231 312 321
  229. if(a > b)
  230. {
  231. std::swap(a,b);
  232. std::swap(ai,bi);
  233. }
  234. // 123 132 123 231 132 231
  235. if(b > c)
  236. {
  237. std::swap(b,c);
  238. std::swap(bi,ci);
  239. // 123 123 123 213 123 213
  240. if(a > b)
  241. {
  242. std::swap(a,b);
  243. std::swap(ai,bi);
  244. }
  245. // 123 123 123 123 123 123
  246. }
  247. }else
  248. {
  249. // 123 132 213 231 312 321
  250. if(a < b)
  251. {
  252. std::swap(a,b);
  253. std::swap(ai,bi);
  254. }
  255. // 213 312 213 321 312 321
  256. if(b < c)
  257. {
  258. std::swap(b,c);
  259. std::swap(bi,ci);
  260. // 231 321 231 321 321 321
  261. if(a < b)
  262. {
  263. std::swap(a,b);
  264. std::swap(ai,bi);
  265. }
  266. // 321 321 321 321 321 321
  267. }
  268. }
  269. };
  270. parallel_for(num_outer,inner,16000);
  271. }
  272. template <class T>
  273. IGL_INLINE void igl::sort(
  274. const std::vector<T> & unsorted,
  275. const bool ascending,
  276. std::vector<T> & sorted,
  277. std::vector<size_t> & index_map)
  278. {
  279. // Original unsorted index map
  280. index_map.resize(unsorted.size());
  281. for(size_t i=0;i<unsorted.size();i++)
  282. {
  283. index_map[i] = i;
  284. }
  285. // Sort the index map, using unsorted for comparison
  286. std::sort(
  287. index_map.begin(),
  288. index_map.end(),
  289. igl::IndexLessThan<const std::vector<T>& >(unsorted));
  290. // if not ascending then reverse
  291. if(!ascending)
  292. {
  293. std::reverse(index_map.begin(),index_map.end());
  294. }
  295. // make space for output without clobbering
  296. sorted.resize(unsorted.size());
  297. // reorder unsorted into sorted using index map
  298. igl::reorder(unsorted,index_map,sorted);
  299. }
  300. #ifdef IGL_STATIC_LIBRARY
  301. // Explicit template specialization
  302. // generated by autoexplicit.sh
  303. 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> >&);
  304. // generated by autoexplicit.sh
  305. 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> >&);
  306. // generated by autoexplicit.sh
  307. template void igl::sort<int>(std::vector<int, std::allocator<int> > const&, bool, std::vector<int, std::allocator<int> >&, std::vector<size_t,class std::allocator<size_t> > &);
  308. // generated by autoexplicit.sh
  309. 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> >&);
  310. // generated by autoexplicit.sh
  311. 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> >&);
  312. 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> >&);
  313. 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> >&);
  314. 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> >&);
  315. 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> >&);
  316. 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> >&);
  317. 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> >&);
  318. 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> >&);
  319. 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> >&);
  320. 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> >&);
  321. 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> >&);
  322. 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> >&);
  323. 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> >&);
  324. 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> >&);
  325. 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> >&);
  326. template void igl::sort<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> > const&, int, bool, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  327. 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> >&);
  328. #endif