sort.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  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. Y = X.derived().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 DerivedIX::Scalar Index;
  164. IX.resizeLike(X);
  165. if(dim==1)
  166. {
  167. IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
  168. IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
  169. }else
  170. {
  171. IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
  172. IX.col(1).setConstant(1);// = 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::DenseBase<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 DerivedY::Scalar YScalar;
  199. Y = X.derived().template cast<YScalar>();
  200. Y.resizeLike(X);
  201. for(int j=0;j<X.cols();j++)for(int i=0;i<X.rows();i++)Y(i,j)=(YScalar)X(i,j);
  202. // get number of columns (or rows)
  203. int num_outer = (dim == 1 ? X.cols() : X.rows() );
  204. // get number of rows (or columns)
  205. int num_inner = (dim == 1 ? X.rows() : X.cols() );
  206. assert(num_inner == 3);(void)num_inner;
  207. typedef typename DerivedIX::Scalar Index;
  208. IX.resizeLike(X);
  209. if(dim==1)
  210. {
  211. IX.row(0).setConstant(0);// = DerivedIX::Zero(1,IX.cols());
  212. IX.row(1).setConstant(1);// = DerivedIX::Ones (1,IX.cols());
  213. IX.row(2).setConstant(2);// = DerivedIX::Ones (1,IX.cols());
  214. }else
  215. {
  216. IX.col(0).setConstant(0);// = DerivedIX::Zero(IX.rows(),1);
  217. IX.col(1).setConstant(1);// = DerivedIX::Ones (IX.rows(),1);
  218. IX.col(2).setConstant(2);// = DerivedIX::Ones (IX.rows(),1);
  219. }
  220. const auto & inner = [&IX,&Y,&dim,&ascending](const Index & i)
  221. {
  222. YScalar & a = (dim==1 ? Y(0,i) : Y(i,0));
  223. YScalar & b = (dim==1 ? Y(1,i) : Y(i,1));
  224. YScalar & c = (dim==1 ? Y(2,i) : Y(i,2));
  225. Index & ai = (dim==1 ? IX(0,i) : IX(i,0));
  226. Index & bi = (dim==1 ? IX(1,i) : IX(i,1));
  227. Index & ci = (dim==1 ? IX(2,i) : IX(i,2));
  228. if(ascending)
  229. {
  230. // 123 132 213 231 312 321
  231. if(a > b)
  232. {
  233. std::swap(a,b);
  234. std::swap(ai,bi);
  235. }
  236. // 123 132 123 231 132 231
  237. if(b > c)
  238. {
  239. std::swap(b,c);
  240. std::swap(bi,ci);
  241. // 123 123 123 213 123 213
  242. if(a > b)
  243. {
  244. std::swap(a,b);
  245. std::swap(ai,bi);
  246. }
  247. // 123 123 123 123 123 123
  248. }
  249. }else
  250. {
  251. // 123 132 213 231 312 321
  252. if(a < b)
  253. {
  254. std::swap(a,b);
  255. std::swap(ai,bi);
  256. }
  257. // 213 312 213 321 312 321
  258. if(b < c)
  259. {
  260. std::swap(b,c);
  261. std::swap(bi,ci);
  262. // 231 321 231 321 321 321
  263. if(a < b)
  264. {
  265. std::swap(a,b);
  266. std::swap(ai,bi);
  267. }
  268. // 321 321 321 321 321 321
  269. }
  270. }
  271. };
  272. parallel_for(num_outer,inner,16000);
  273. }
  274. template <class T>
  275. IGL_INLINE void igl::sort(
  276. const std::vector<T> & unsorted,
  277. const bool ascending,
  278. std::vector<T> & sorted,
  279. std::vector<size_t> & index_map)
  280. {
  281. // Original unsorted index map
  282. index_map.resize(unsorted.size());
  283. for(size_t i=0;i<unsorted.size();i++)
  284. {
  285. index_map[i] = i;
  286. }
  287. // Sort the index map, using unsorted for comparison
  288. std::sort(
  289. index_map.begin(),
  290. index_map.end(),
  291. igl::IndexLessThan<const std::vector<T>& >(unsorted));
  292. // if not ascending then reverse
  293. if(!ascending)
  294. {
  295. std::reverse(index_map.begin(),index_map.end());
  296. }
  297. // make space for output without clobbering
  298. sorted.resize(unsorted.size());
  299. // reorder unsorted into sorted using index map
  300. igl::reorder(unsorted,index_map,sorted);
  301. }
  302. #ifdef IGL_STATIC_LIBRARY
  303. // Explicit template instantiation
  304. // generated by autoexplicit.sh
  305. template void igl::sort<Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, 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, 2, 0, -1, 2> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
  306. // generated by autoexplicit.sh
  307. 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> >&);
  308. 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> >&);
  309. 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> > &);
  310. 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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  314. 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> >&);
  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::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> >&);
  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::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> >&);
  317. 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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  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::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> >&);
  328. 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> >&);
  329. #endif