sort.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  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::DenseBase<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.resizeLike(X);
  44. IX.resizeLike(X);
  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::DenseBase<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.resizeLike(X);
  106. IX.resizeLike(X);
  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::DenseBase<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 DerivedY::Scalar YScalar;
  157. // DenseBase doesn't have a .cast function...
  158. //Y = X.template cast<YScalar>();
  159. Y.resizeLike(X);
  160. for(int j=0;j<X.cols();j++)for(int i=0;i<X.rows();i++)Y(i,j)=(YScalar)X(i,j);
  161. // get number of columns (or rows)
  162. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  163. // get number of rows (or columns)
  164. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  165. assert(num_inner == 2);(void)num_inner;
  166. typedef typename DerivedIX::Scalar Index;
  167. IX.resizeLike(X);
  168. if(dim==1)
  169. {
  170. IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
  171. IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
  172. }else
  173. {
  174. IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
  175. IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
  176. }
  177. // loop over columns (or rows)
  178. for(int i = 0;i<num_outer;i++)
  179. {
  180. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  181. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  182. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  183. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  184. if((ascending && a>b) || (!ascending && a<b))
  185. {
  186. std::swap(a,b);
  187. std::swap(ai,bi);
  188. }
  189. }
  190. }
  191. template <typename DerivedX, typename DerivedY, typename DerivedIX>
  192. IGL_INLINE void igl::sort3(
  193. const Eigen::DenseBase<DerivedX>& X,
  194. const int dim,
  195. const bool ascending,
  196. Eigen::PlainObjectBase<DerivedY>& Y,
  197. Eigen::PlainObjectBase<DerivedIX>& IX)
  198. {
  199. using namespace Eigen;
  200. using namespace std;
  201. typedef typename DerivedY::Scalar YScalar;
  202. // DenseBase doesn't have a .cast function...
  203. //Y = X.template cast<YScalar>();
  204. Y.resizeLike(X);
  205. for(int j=0;j<X.cols();j++)for(int i=0;i<X.rows();i++)Y(i,j)=(YScalar)X(i,j);
  206. // get number of columns (or rows)
  207. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  208. // get number of rows (or columns)
  209. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  210. assert(num_inner == 3);(void)num_inner;
  211. typedef typename DerivedIX::Scalar Index;
  212. IX.resizeLike(X);
  213. if(dim==1)
  214. {
  215. IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
  216. IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
  217. IX.row(2).setConstant(2);// = DerivedIX::Ones (1,IX.cols());
  218. }else
  219. {
  220. IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
  221. IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
  222. IX.col(2).setConstant(2);// = DerivedIX::Ones (IX.rows(),1);
  223. }
  224. const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
  225. {
  226. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  227. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  228. YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
  229. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  230. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  231. Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
  232. if(ascending)
  233. {
  234. // 123 132 213 231 312 321
  235. if(a > b)
  236. {
  237. std::swap(a,b);
  238. std::swap(ai,bi);
  239. }
  240. // 123 132 123 231 132 231
  241. if(b > c)
  242. {
  243. std::swap(b,c);
  244. std::swap(bi,ci);
  245. // 123 123 123 213 123 213
  246. if(a > b)
  247. {
  248. std::swap(a,b);
  249. std::swap(ai,bi);
  250. }
  251. // 123 123 123 123 123 123
  252. }
  253. }else
  254. {
  255. // 123 132 213 231 312 321
  256. if(a < b)
  257. {
  258. std::swap(a,b);
  259. std::swap(ai,bi);
  260. }
  261. // 213 312 213 321 312 321
  262. if(b < c)
  263. {
  264. std::swap(b,c);
  265. std::swap(bi,ci);
  266. // 231 321 231 321 321 321
  267. if(a < b)
  268. {
  269. std::swap(a,b);
  270. std::swap(ai,bi);
  271. }
  272. // 321 321 321 321 321 321
  273. }
  274. }
  275. };
  276. parallel_for(num_outer,inner,16000);
  277. }
  278. template <class T>
  279. IGL_INLINE void igl::sort(
  280. const std::vector<T> & unsorted,
  281. const bool ascending,
  282. std::vector<T> & sorted,
  283. std::vector<size_t> & index_map)
  284. {
  285. // Original unsorted index map
  286. index_map.resize(unsorted.size());
  287. for(size_t i=0;i<unsorted.size();i++)
  288. {
  289. index_map[i] = i;
  290. }
  291. // Sort the index map, using unsorted for comparison
  292. std::sort(
  293. index_map.begin(),
  294. index_map.end(),
  295. igl::IndexLessThan<const std::vector<T>& >(unsorted));
  296. // if not ascending then reverse
  297. if(!ascending)
  298. {
  299. std::reverse(index_map.begin(),index_map.end());
  300. }
  301. // make space for output without clobbering
  302. sorted.resize(unsorted.size());
  303. // reorder unsorted into sorted using index map
  304. igl::reorder(unsorted,index_map,sorted);
  305. }
  306. #ifdef IGL_STATIC_LIBRARY
  307. // Explicit template specialization
  308. // generated by autoexplicit.sh
  309. 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::DenseBase<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> >&);
  310. 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::DenseBase<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> >&);
  311. 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> > &);
  312. 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::DenseBase<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> >&);
  313. 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::DenseBase<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> >&);
  314. 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::DenseBase<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<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::DenseBase<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> >&);
  316. template void igl::sort<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(Eigen::DenseBase<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> >&);
  317. 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::DenseBase<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> >&);
  318. 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::DenseBase<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> >&);
  319. template void igl::sort<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2> >(Eigen::DenseBase<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> >&);
  320. 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::DenseBase<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> >&);
  321. 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::DenseBase<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> >&);
  322. 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> >&);
  323. 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::DenseBase<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> >&);
  324. 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::DenseBase<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> >&);
  325. 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::DenseBase<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> >&);
  326. 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::DenseBase<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> >&);
  327. 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::DenseBase<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> >&);
  328. 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::DenseBase<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> >&);
  329. 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::DenseBase<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> >&);
  330. template void igl::sort<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<long, -1, 1, 0, -1, 1> >(Eigen::DenseBase<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<long, -1, 1, 0, -1, 1> >&);
  331. #endif