ExaFMM 1
Fast-multipole Method for exascale systems
include/sort.h
Go to the documentation of this file.
00001 /*
00002 Copyright (C) 2011 by Rio Yokota, Simon Layton, Lorena Barba
00003 
00004 Permission is hereby granted, free of charge, to any person obtaining a copy
00005 of this software and associated documentation files (the "Software"), to deal
00006 in the Software without restriction, including without limitation the rights
00007 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008 copies of the Software, and to permit persons to whom the Software is
00009 furnished to do so, subject to the following conditions:
00010 
00011 The above copyright notice and this permission notice shall be included in
00012 all copies or substantial portions of the Software.
00013 
00014 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020 THE SOFTWARE.
00021 */
00022 #ifndef sort_h
00023 #define sort_h
00024 #include "../include/logger.h"
00025 
00026 //! Custom bucket sort for body and cell structures
00027 class Sort : public Logger {
00028 private:
00029   std::vector<int> bucket;                                      //!< Bucket for sorting
00030 
00031 //! Get bucket size for sorting
00032   template<typename T>
00033   void getBucketSize(T &values, int begin, int end, bigint &Imin, int &numBucket) {
00034     typename T::iterator V0 = values.begin()+begin;             // Get begin iterator
00035     typename T::iterator VN = values.begin()+end;               // Get end iterator
00036     Imin = V0->ICELL;                                           // Initialize minimum index
00037     bigint Imax = V0->ICELL;                                    // Initialize maximum index
00038     for( typename T::iterator V=V0; V!=VN; ++V ) {              // Loop over vector
00039       if     ( V->ICELL < Imin ) Imin = V->ICELL;               //  Set minimum index
00040       else if( V->ICELL > Imax ) Imax = V->ICELL;               //  Set maximum index
00041     }                                                           // End loop over vector
00042     numBucket = Imax - Imin + 1;                                // Use range of indices as bucket size
00043     if( numBucket > int(bucket.size()) ) {                      // If bucket size needs to be enlarged
00044       bucket.resize(numBucket);                                 //  Resize bucket vector
00045     }                                                           // Endif for resize
00046   }
00047 
00048 //! Bucket sort for small indices
00049   template<typename T>
00050   void sortICELL(T &values, T &buffer, bigint Imin,
00051                  int numBucket, bool ascend, int begin, int end) {
00052     startTimer("Fill bucket  ");                                // Start timer
00053     for( int i=0; i!=numBucket; ++i ) bucket[i] = 0;            // Initialize bucket
00054     for( int i=begin; i!=end; ++i ) bucket[values[i].ICELL-Imin]++;// Fill bucket
00055     for( int i=1; i!=numBucket; ++i ) bucket[i] += bucket[i-1]; // Scan bucket
00056     stopTimer("Fill bucket  ");                                 // Stop timer
00057     startTimer("Empty bucket ");                                // Start timer
00058     for( int i=end-1; i>=begin; --i ) {                         // Loop over data backwards
00059       bucket[values[i].ICELL-Imin]--;                           //  Empty bucket
00060       int inew = bucket[values[i].ICELL-Imin]+begin;            //  Permutation index
00061       buffer[inew] = values[i];                                 //  Fill buffer
00062     }                                                           // End loop over data
00063     stopTimer("Empty bucket ");                                 // Stop timer
00064     startTimer("Copy value   ");                                // Start timer
00065     if( ascend ) {                                              // If sorting in ascending order
00066 #pragma omp parallel for
00067       for( int i=begin; i<end; ++i ) values[i] = buffer[i];     //  Copy back bodiess in order
00068     } else {                                                    // If sorting in descending order
00069 #pragma omp parallel for
00070       for( int i=begin; i<end; ++i ) values[end-i+begin-1] = buffer[i];// Copy back bodiess in reverse order
00071     }                                                           // Endif for sorting order
00072     stopTimer("Copy value   ");                                 // Stop timer
00073   }
00074 
00075 public:
00076 //! Sort bodies accoring to cell index
00077   void sortBodies(Bodies &bodies, Bodies &buffer, bool ascend=true, int begin=0, int end=0) {
00078     startTimer("Sort bodies  ");                                // Start timer
00079     if( bodies.size() == 0 ) return;                            // Don't do anything if vector is empty
00080     if( end == 0 ) end = bodies.size();                         // Default range is the whole vector
00081     int numBucket = 0;                                          // Initialize bucket size
00082     bigint Imin = 0;                                            // Initialize minimum index
00083     getBucketSize(bodies,begin,end,Imin,numBucket);             // Get bucket size for sorting
00084     stopTimer("Sort bodies  ");                                 // Stop timer
00085     sortICELL(bodies,buffer,Imin,numBucket,ascend,begin,end);   // Call bucket sort for small indices
00086   }
00087 
00088 //! Sort cells according to cell index
00089   void sortCells(Cells &cells, Cells &buffer, bool ascend=true, int begin=0, int end=0) {
00090     startTimer("Sort cells   ");                                // Start timer
00091     if( cells.size() == 0 ) return;                             // Don't do anything if vector is empty
00092     if( end == 0 ) end = cells.size();                          // Default rage is the whole vector
00093     int numBucket = 0;                                          // Initialize bucket size
00094     bigint Imin = 0;                                            // Initialize minimum index
00095     getBucketSize(cells,begin,end,Imin,numBucket);              // Get bucket size for sorting
00096     stopTimer("Sort cells   ");                                 // Stop timer
00097     if( buffer.size() < cells.size() ) buffer.resize(cells.size());// Resize sort buffer if necessary
00098     sortICELL(cells,buffer,Imin,numBucket,ascend,begin,end);    // Call bucket sort for small indices
00099   }
00100 };
00101 
00102 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines