casa
$Rev:20696$
|
00001 //# GenSort.h: General sort functions 00002 //# Copyright (C) 1993,1994,1995,1996,1997,1999 00003 //# Associated Universities, Inc. Washington DC, USA. 00004 //# 00005 //# This library is free software; you can redistribute it and/or modify it 00006 //# under the terms of the GNU Library General Public License as published by 00007 //# the Free Software Foundation; either version 2 of the License, or (at your 00008 //# option) any later version. 00009 //# 00010 //# This library is distributed in the hope that it will be useful, but WITHOUT 00011 //# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00012 //# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public 00013 //# License for more details. 00014 //# 00015 //# You should have received a copy of the GNU Library General Public License 00016 //# along with this library; if not, write to the Free Software Foundation, 00017 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. 00018 //# 00019 //# Correspondence concerning AIPS++ should be addressed as follows: 00020 //# Internet email: aips2-request@nrao.edu. 00021 //# Postal address: AIPS++ Project Office 00022 //# National Radio Astronomy Observatory 00023 //# 520 Edgemont Road 00024 //# Charlottesville, VA 22903-2475 USA 00025 //# 00026 //# $Id: GenSort.h 20551 2009-03-25 00:11:33Z Malte.Marquarding $ 00027 00028 #ifndef CASA_GENSORT_H 00029 #define CASA_GENSORT_H 00030 00031 #include <casa/aips.h> 00032 #include <casa/Utilities/Sort.h> 00033 00034 namespace casa { //# NAMESPACE CASA - BEGIN 00035 00036 //# Forward declarations. 00037 template<class T> class Array; 00038 template<class T> class Vector; 00039 template<class T> class Block; 00040 00041 // <summary> General in-place sort functions </summary> 00042 // <use visibility=local> 00043 // <reviewed reviewer="Friso Olnon" date="1995/03/16" tests="tGenSort" demos=""> 00044 00045 // <synopsis> 00046 // 00047 // The static member functions of this templated class are highly optimized 00048 // sort functions. They do an in-place sort of an array of values. The 00049 // functions are templated, so they can in principle be used with any 00050 // data type. However, if used with non-builtin data types, their 00051 // class must provide certain functions (see <em>Template Type Argument 00052 // Requirements</em>). 00053 // 00054 // If it is impossible or too expensive to define these functions, the 00055 // <linkto class=Sort>Sort</linkto> class can be used instead. This sorts 00056 // indirectly using an index array. Instead of the functions mentioned 00057 // above it requires a comparison routine. 00058 // 00059 // The <src>GenSort</src> functions can sort: 00060 // <ul> 00061 // <li> C-arrays of values; 00062 // <li> <src>Array</src>s of values -- the array can have any shape 00063 // and the increment can be >1; 00064 // <li> <src>Block</src>s of values -- there is a special function to 00065 // sort less elements than the size of the <src>Block</src>. 00066 // </ul> 00067 // 00068 // The sort order can be specified in the order field: 00069 // <dl> 00070 // <dt> <src>Sort::Ascending</src> (default), 00071 // <dt> <src>Sort::Descending</src>. 00072 // </dl> 00073 // 00074 // A sort algorithm can be given in the options field: 00075 // <dl> 00076 // <dt> <src>Sort::QuickSort</src> (default) 00077 // <dd> is the fastest. It is about 4-6 times faster 00078 // than the qsort function on the SUN. No worst case has been 00079 // found, even not for cases where qsort is terribly slow. 00080 // <dt> <src>Sort::HeapSort</src> 00081 // <dd> is about twice as slow as quicksort. 00082 // It has the advantage that the worst case is always o(n*log(n)), 00083 // while quicksort can have hypothetical inputs with o(n*n). 00084 // <dt> <src>Sort::InsSort</src> 00085 // <dd> is o(n*n) for random inputs. It is, however, the 00086 // only stable sort (i.e. equal values remain in the original order). 00087 // </dl> 00088 // <src>Sort::NoDuplicates</src> in the options field indicates that 00089 // duplicate values should be removed. Multiple options can be given by 00090 // or-ing them, e.g. <src>Sort::HeapSort | Sort::NoDuplicates</src>. 00091 // <p> 00092 // All the sort functions return the number of values sorted as their 00093 // function value; when duplicate values have been removed, the number of 00094 // unique valuess will be returned. 00095 // <p> 00096 // The class also provides a function to find the k-th largest value 00097 // in an array of values. This uses a stripped-down version of quicksort 00098 // and is at least 6 times faster than a full quicksort. 00099 // </synopsis> 00100 00101 // <templating arg=T> 00102 // <li> <src>operator=</src> to assign when swapping elements 00103 // <li> <src>operator<</src>, <src>operator></src> and 00104 // <src>operator==</src> to compare elements 00105 // <li> default constructor to allocate a temporary 00106 // </templating> 00107 00108 template<class T> class GenSort 00109 { 00110 public: 00111 00112 // Sort a C-array containing <src>nr</src> <src>T</src>-type objects. 00113 // The sort is done in place. 00114 static uInt sort (T*, uInt nr, Sort::Order = Sort::Ascending, 00115 int options = Sort::QuickSort); 00116 00117 // Sort an <src>Array</src> of <src>T</src>-type objects 00118 // The sort is done in place. 00119 static uInt sort (Array<T>&, Sort::Order = Sort::Ascending, 00120 int options = Sort::QuickSort); 00121 00122 // Sort <src>nr</src> <src>T</src>-type objects in the <src>Block</src>. 00123 // The sort is done in place. 00124 static uInt sort (Block<T>&, uInt nr, Sort::Order = Sort::Ascending, 00125 int options = Sort::QuickSort); 00126 00127 // Find the k-th largest value. 00128 // Note: it does a partial sort, thus the data array gets changed.. 00129 static T kthLargest (T* data, uInt nr, uInt k); 00130 00131 private: 00132 // Sort C-array using quicksort. 00133 static uInt quickSort (T*, uInt nr, Sort::Order, int options); 00134 // Sort C-array using heapsort. 00135 static uInt heapSort (T*, uInt nr, Sort::Order, int options); 00136 // Sort C-array using insertion sort. 00137 static uInt insSort (T*, uInt nr, Sort::Order, int options); 00138 00139 // Swap 2 elements in array. 00140 static inline void swap (T&, T&); 00141 00142 // Quicksort in ascending order. 00143 static void quickSortAsc (T*, Int); 00144 // Quicksort in descending order. 00145 static void quickSortDesc (T*, Int); 00146 00147 // Heapsort in ascending order. 00148 static void heapSortAsc (T*, Int); 00149 // Heapsort in descending order. 00150 static void heapSortDesc (T*, Int); 00151 // Helper function for ascending heapsort. 00152 static void heapAscSiftDown (Int, Int, T*); 00153 // Helper function for descending heapsort. 00154 static void heapDescSiftDown (Int, Int, T*); 00155 00156 // Insertion sort in ascending order. 00157 static uInt insSortAsc (T*, Int, int option); 00158 // Insertion sort in descending order. 00159 static uInt insSortDesc (T*, Int, int option); 00160 // Insertion sort in ascending order allowing duplicates. 00161 // This is also used by quicksort for its last steps. 00162 static uInt insSortAscDup (T*, Int); 00163 // Insertion sort in descending order allowing duplicates. 00164 // This is also used by quicksort for its last steps. 00165 static uInt insSortDescDup (T*, Int); 00166 // Insertion sort in ascending order allowing no duplicates. 00167 // This is also used by the other sort algorithms to skip duplicates. 00168 static uInt insSortAscNoDup (T*, Int); 00169 // Insertion sort in descending order allowing no duplicates. 00170 // This is also used by the other sort algorithms to skip duplicates. 00171 static uInt insSortDescNoDup (T*, Int); 00172 }; 00173 00174 00175 // <summary> General indirect sort functions </summary> 00176 // <use visibility=local> 00177 // <reviewed reviewer="" date="" tests="" demos=""> 00178 00179 // <synopsis> 00180 // This class is similar to <linkto class=GenSort>GenSort</linkto>. 00181 // The only difference is that the functions in this class sort 00182 // indirectly instead of in-place. 00183 // They return the result of the sort as an sorted vector of indices 00184 // This is slower, because an extra indirection is involved in each 00185 // comparison. However, this sort allows to sort const data. 00186 // Another advantage is that this sort is always stable (i.e. equal 00187 // values are kept in their original order). 00188 00189 template<class T> class GenSortIndirect 00190 { 00191 public: 00192 00193 // Sort a C-array containing <src>nr</src> <src>T</src>-type objects. 00194 // The resulting index vector gives the sorted indices. 00195 static uInt sort (Vector<uInt>& indexVector, const T* data, uInt nr, 00196 Sort::Order = Sort::Ascending, 00197 int options = Sort::QuickSort); 00198 00199 // Sort a C-array containing <src>nr</src> <src>T</src>-type objects. 00200 // The resulting index vector gives the sorted indices. 00201 static uInt sort (Vector<uInt>& indexVector, const Array<T>& data, 00202 Sort::Order = Sort::Ascending, 00203 int options = Sort::QuickSort); 00204 00205 // Sort a C-array containing <src>nr</src> <src>T</src>-type objects. 00206 // The resulting index vector gives the sorted indices. 00207 static uInt sort (Vector<uInt>& indexVector, const Block<T>& data, uInt nr, 00208 Sort::Order = Sort::Ascending, 00209 int options = Sort::QuickSort); 00210 00211 private: 00212 // Sort container using quicksort. 00213 static uInt quickSort (uInt* inx, const T* data, 00214 uInt nr, Sort::Order, int options); 00215 // Sort container using heapsort. 00216 static uInt heapSort (uInt* inx, const T* data, 00217 uInt nr, Sort::Order, int options); 00218 // Sort container using insertion sort. 00219 static uInt insSort (uInt* inx, const T* data, 00220 uInt nr, Sort::Order, int options); 00221 00222 // Swap 2 indices. 00223 static inline void swapInx (uInt& index1, uInt& index2); 00224 00225 // Check if 2 values are in ascending order. 00226 // When equal, the order is correct if index1<index2. 00227 static inline int isAscending (const T* data, Int index1, Int index2); 00228 00229 // Check if 2 values are in descending order. 00230 // When equal, the order is correct if index1<index2. 00231 static inline int isDescending (const T*, Int index1, Int index2); 00232 00233 00234 // Quicksort in ascending order. 00235 static void quickSortAsc (uInt* inx, const T*, Int nr); 00236 // Quicksort in descending order. 00237 static void quickSortDesc (uInt* inx, const T*, Int nr); 00238 00239 // Heapsort in ascending order. 00240 static void heapSortAsc (uInt* inx, const T*, Int nr); 00241 // Heapsort in descending order. 00242 static void heapSortDesc (uInt* inx, const T*, Int nr); 00243 // Helper function for ascending heapsort. 00244 static void heapAscSiftDown (uInt* inx, Int, Int, const T*); 00245 // Helper function for descending heapsort. 00246 static void heapDescSiftDown (uInt* inx, Int, Int, const T*); 00247 00248 // Insertion sort in ascending order. 00249 static uInt insSortAsc (uInt* inx, const T*, Int nr, int option); 00250 // Insertion sort in descending order. 00251 static uInt insSortDesc (uInt* inx, const T*, Int nr, int option); 00252 // Insertion sort in ascending order allowing duplicates. 00253 // This is also used by quicksort for its last steps. 00254 static uInt insSortAscDup (uInt* inx, const T*, Int nr); 00255 // Insertion sort in descending order allowing duplicates. 00256 // This is also used by quicksort for its last steps. 00257 static uInt insSortDescDup (uInt* inx, const T*, Int nr); 00258 // Insertion sort in ascending order allowing no duplicates. 00259 // This is also used by the other sort algorithms to skip duplicates. 00260 static uInt insSortAscNoDup (uInt* inx, const T*, Int nr); 00261 // Insertion sort in descending order allowing no duplicates. 00262 // This is also used by the other sort algorithms to skip duplicates. 00263 static uInt insSortDescNoDup (uInt* inx, const T*, Int nr); 00264 }; 00265 00266 00267 // <summary> Global in-place sort functions </summary> 00268 00269 // The following global functions are easier to use than the static 00270 // <linkto class=GenSort>GenSort</linkto> member functions. 00271 // They do an in-place sort of data, thus the data themselves are moved 00272 // ending up in the requested order. 00273 // <p> 00274 // The default sorting method is QuickSort, which is the fastest. 00275 // However, there are pathological cases where it can be slow. 00276 // HeapSort is about twice a slow, but its speed is guaranteed. 00277 // InsSort (insertion sort) can be very, very slow, but it is the only 00278 // stable sort method (i.e. equal values are kept in their original order). 00279 // However, <linkto name=genSortIndirect> indirect sorting methods </linkto> 00280 // are available to make QuickSort and HeapSort stable. 00281 // <p> 00282 // All sort methods have an option to skip duplicate values. This is the 00283 // only case where the returned number of values can be less than the 00284 // original number of values. 00285 00286 // <group name=genSortInPlace> 00287 00288 // In-place sort in ascending order using QuickSort. 00289 // <group> 00290 template<class T> 00291 inline 00292 uInt genSort (T* data, uInt nr) 00293 { return GenSort<T>::sort (data, nr, Sort::Ascending, Sort::QuickSort); } 00294 00295 template<class T> 00296 inline 00297 uInt genSort (Array<T>& data) 00298 { return GenSort<T>::sort (data, Sort::Ascending, Sort::QuickSort); } 00299 00300 template<class T> 00301 inline 00302 uInt genSort (Block<T>& data) 00303 { return GenSort<T>::sort (data, data.nelements(), Sort::Ascending, 00304 Sort::QuickSort); } 00305 00306 template<class T> 00307 inline 00308 uInt genSort (Block<T>& data, uInt nr) 00309 { return GenSort<T>::sort (data, nr, Sort::Ascending, Sort::QuickSort); } 00310 // </group> 00311 00312 // In-place sort in ascending order using given option. 00313 // This option gives the sort method (Sort::QuickSort, Sort::HeapSort 00314 // or Sort::InsSort) and/or the option Sort::NoDuplicates. 00315 // <group> 00316 template<class T> 00317 inline 00318 uInt genSort (T* data, uInt nr, int options) 00319 { return GenSort<T>::sort (data, nr, Sort::Ascending, options); } 00320 template<class T> 00321 inline 00322 uInt genSort (Array<T>& data, int options) 00323 { return GenSort<T>::sort (data, Sort::Ascending, options); } 00324 template<class T> 00325 inline 00326 uInt genSort (Block<T>& data, int options) 00327 { return GenSort<T>::sort (data, data.nelements(), Sort::Ascending, 00328 options); } 00329 template<class T> 00330 inline 00331 uInt genSort (Block<T>& data, uInt nr, int options) 00332 { return GenSort<T>::sort (data, nr, Sort::Ascending, options); } 00333 // </group> 00334 00335 // In-place sort in given order using QuickSort. 00336 // The order must be Sort::Ascending or Sort::Descending. 00337 // <group> 00338 template<class T> 00339 inline 00340 uInt genSort (T* data, uInt nr, Sort::Order order) 00341 { return GenSort<T>::sort (data, nr, order, Sort::QuickSort); } 00342 template<class T> 00343 inline 00344 uInt genSort (Array<T>& data, Sort::Order order) 00345 { return GenSort<T>::sort (data, order, Sort::QuickSort); } 00346 template<class T> 00347 inline 00348 uInt genSort (Block<T>& data, Sort::Order order) 00349 { return GenSort<T>::sort (data, data.nelements(), order, 00350 Sort::QuickSort); } 00351 template<class T> 00352 inline 00353 uInt genSort (Block<T>& data, uInt nr, Sort::Order order) 00354 { return GenSort<T>::sort (data, nr, order, Sort::QuickSort); } 00355 // </group> 00356 00357 // In-place sort in given order using given option. 00358 // This option gives the sort method (Sort::QuickSort, Sort::HeapSort, 00359 // or Sort::InsSort) and/or the option Sort::NoDuplicates. 00360 // The order must be Sort::Ascending or Sort::Descending. 00361 // <group> 00362 template<class T> 00363 inline 00364 uInt genSort (T* data, uInt nr, Sort::Order order, int options) 00365 { return GenSort<T>::sort (data, nr, order, options); } 00366 template<class T> 00367 inline 00368 uInt genSort (Array<T>& data, Sort::Order order, int options) 00369 { return GenSort<T>::sort (data, order, options); } 00370 template<class T> 00371 inline 00372 uInt genSort (Block<T>& data, Sort::Order order, int options) 00373 { return GenSort<T>::sort (data, data.nelements(), order, options); } 00374 template<class T> 00375 inline 00376 uInt genSort (Block<T>& data, uInt nr, Sort::Order order, int options) 00377 { return GenSort<T>::sort (data, nr, order, options); } 00378 // </group> 00379 00380 // </group> 00381 00382 00383 00384 // <summary> Global indirect sort functions </summary> 00385 00386 // The following global functions easier to use than the static 00387 // <linkto class=GenSortIndirect>GenSortIndirect</linkto> member functions. 00388 // They do an indirect sort of data, thus the data themselves are not moved. 00389 // Rather an index vector is returned giving the sorted data indices. 00390 // <p> 00391 // The default sorting method is QuickSort, which is the fastest. 00392 // However, there are pathological cases where it can be slow. 00393 // HeapSort is about twice a slow, but its speed is guaranteed. 00394 // InsSort (insertion sort) can be very, very slow. 00395 // <p> 00396 // Unlike the <linkto name=genSortInPlace> in-place sorting methods 00397 // </linkto>, all indirect sorting methods are stable (i.e. equal 00398 // values are left in their original order). 00399 // <p> 00400 // All sort methods have an option to skip duplicate values. This is the 00401 // only case where the returned number of values can be less than the 00402 // original number of values. 00403 00404 // <group name=genSortIndirect> 00405 00406 // Indirect sort in ascending order using QuickSort. 00407 // <group> 00408 template<class T> 00409 inline 00410 uInt genSort (Vector<uInt>& indexVector, const T* data, uInt nr) 00411 { return GenSortIndirect<T>::sort (indexVector, data, nr, Sort::Ascending, 00412 Sort::QuickSort); } 00413 00414 template<class T> 00415 inline 00416 uInt genSort (Vector<uInt>& indexVector, const Array<T>& data) 00417 { return GenSortIndirect<T>::sort (indexVector, data, Sort::Ascending, 00418 Sort::QuickSort); } 00419 00420 template<class T> 00421 inline 00422 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data) 00423 { return GenSortIndirect<T>::sort (indexVector, data, data.nelements(), 00424 Sort::Ascending, Sort::QuickSort); } 00425 00426 template<class T> 00427 inline 00428 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, uInt nr) 00429 { return GenSortIndirect<T>::sort (indexVector, data, nr, 00430 Sort::Ascending, Sort::QuickSort); } 00431 // </group> 00432 00433 // Indirect sort in ascending order using given option. 00434 // This option gives the sort method (Sort::QuickSort, Sort::HeapSort, 00435 // or Sort::InsSort) and/or the option Sort::NoDuplicates. 00436 // <group> 00437 template<class T> 00438 inline 00439 uInt genSort (Vector<uInt>& indexVector, const T* data, uInt nr, int options) 00440 { return GenSortIndirect<T>::sort (indexVector, data, nr, 00441 Sort::Ascending, options); } 00442 template<class T> 00443 inline 00444 uInt genSort (Vector<uInt>& indexVector, const Array<T>& data, int options) 00445 { return GenSortIndirect<T>::sort (indexVector, data, 00446 Sort::Ascending, options); } 00447 template<class T> 00448 inline 00449 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, int options) 00450 { return GenSortIndirect<T>::sort (indexVector, data, data.nelements(), 00451 Sort::Ascending, options); } 00452 template<class T> 00453 inline 00454 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, 00455 uInt nr, int options) 00456 { return GenSortIndirect<T>::sort (indexVector, data, nr, 00457 Sort::Ascending, options); } 00458 // </group> 00459 00460 // Indirect sort in given order using QuickSort. 00461 // The order must be Sort::Ascending or Sort::Descending. 00462 // <group> 00463 template<class T> 00464 inline 00465 uInt genSort (Vector<uInt>& indexVector, const T* data, 00466 uInt nr, Sort::Order order) 00467 { return GenSortIndirect<T>::sort (indexVector, data, nr, order, 00468 Sort::QuickSort); } 00469 template<class T> 00470 inline 00471 uInt genSort (Vector<uInt>& indexVector, const Array<T>& data, 00472 Sort::Order order) 00473 { return GenSortIndirect<T>::sort (indexVector, data, order, 00474 Sort::QuickSort); } 00475 template<class T> 00476 inline 00477 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, 00478 Sort::Order order) 00479 { return GenSortIndirect<T>::sort (indexVector, data, data.nelements(), 00480 order, Sort::QuickSort); } 00481 template<class T> 00482 inline 00483 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, 00484 uInt nr, Sort::Order order) 00485 { return GenSortIndirect<T>::sort (indexVector, data, nr, order, 00486 Sort::QuickSort); } 00487 // </group> 00488 00489 // Indirect sort in given order using given option. 00490 // This option gives the sort method (Sort::QuickSort, Sort::HeapSort, 00491 // or Sort::InsSort) and/or the option Sort::NoDuplicates. 00492 // The order must be Sort::Ascending or Sort::Descending. 00493 // <group> 00494 template<class T> 00495 inline 00496 uInt genSort (Vector<uInt>& indexVector, const T* data, uInt nr, 00497 Sort::Order order, int options) 00498 { return GenSortIndirect<T>::sort (indexVector, data, nr, 00499 order, options); } 00500 template<class T> 00501 inline 00502 uInt genSort (Vector<uInt>& indexVector, Array<T>& data, 00503 Sort::Order order, int options) 00504 { return GenSortIndirect<T>::sort (indexVector, data, order, options); } 00505 template<class T> 00506 inline 00507 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, 00508 Sort::Order order, int options) 00509 { return GenSortIndirect<T>::sort (indexVector, data, data.nelements(), 00510 order, options); } 00511 template<class T> 00512 inline 00513 uInt genSort (Vector<uInt>& indexVector, const Block<T>& data, uInt nr, 00514 Sort::Order order, int options) 00515 { return GenSortIndirect<T>::sort (indexVector, data, nr, 00516 order, options); } 00517 // </group> 00518 00519 // </group> 00520 00521 00522 00523 00524 // Implement inline member functions. 00525 00526 template<class T> 00527 inline void GenSort<T>::swap (T& l, T& r) 00528 { 00529 T t = l; 00530 l = r; 00531 r = t; 00532 } 00533 template<class T> 00534 inline void GenSortIndirect<T>::swapInx (uInt& i, uInt& j) 00535 { 00536 uInt t = i; 00537 i = j; 00538 j = t; 00539 } 00540 template<class T> 00541 inline int GenSortIndirect<T>::isAscending (const T* data, Int i, Int j) 00542 { 00543 return (data[i] > data[j] || (data[i] == data[j] && i > j)); 00544 } 00545 template<class T> 00546 inline int GenSortIndirect<T>::isDescending (const T* data, Int i, Int j) 00547 { 00548 return (data[i] < data[j] || (data[i] == data[j] && i > j)); 00549 } 00550 00551 00552 00553 } //# NAMESPACE CASA - END 00554 00555 #ifndef CASACORE_NO_AUTO_TEMPLATES 00556 #include <casa/Utilities/GenSort.tcc> 00557 #endif //# CASACORE_NO_AUTO_TEMPLATES 00558 #endif