casa  $Rev:20696$
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
GenSort.h
Go to the documentation of this file.
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