AnasaziBasicSort.hpp

Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Anasazi: Block Eigensolvers Package
00005 //                 Copyright (2004) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00025 //
00026 // ***********************************************************************
00027 // @HEADER
00028 
00033 #ifndef ANASAZI_BASIC_SORT_HPP
00034 #define ANASAZI_BASIC_SORT_HPP
00035 
00043 #include "AnasaziConfigDefs.hpp"
00044 #include "AnasaziSortManager.hpp"
00045 #include "Teuchos_LAPACK.hpp"
00046 #include "Teuchos_ScalarTraits.hpp"
00047 
00048 namespace Anasazi {
00049 
00050   template<class ScalarType, class MV, class OP>
00051   class BasicSort : public SortManager<ScalarType,MV,OP> {
00052     
00053   public:
00054     
00056 
00067     BasicSort( const std::string which = "LM" ) {
00068       setSortType(which);
00069     }
00070 
00072     virtual ~BasicSort() {};
00073 
00075 
00086     void setSortType( const std::string which ) { 
00087       which_ = which; 
00088       TEST_FOR_EXCEPTION(which_.compare("LM") && which_.compare("SM") &&
00089                          which_.compare("LR") && which_.compare("SR") &&
00090                          which_.compare("LI") && which_.compare("SI"), std::invalid_argument, 
00091                          "Anasazi::BasicSort::sort(): sorting order is not valid");
00092     };
00093     
00095 
00104     void sort(Eigensolver<ScalarType,MV,OP>* solver, const int n, std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &evals, std::vector<int> *perm = 0) const;
00105 
00122     void sort(Eigensolver<ScalarType,MV,OP>* solver, 
00123               const int n,
00124               std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &r_evals, 
00125               std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &i_evals, 
00126               std::vector<int> *perm = 0) const;
00127     
00128   protected: 
00129     
00131 
00141     std::string which_;
00142 
00143   };
00144 
00145   template<class ScalarType, class MV, class OP>
00146   void BasicSort<ScalarType,MV,OP>::sort(Eigensolver<ScalarType,MV,OP>* solver, const int n, 
00147                               std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &evals, 
00148                               std::vector<int> *perm) const
00149   {
00150     int i=0,j=0;
00151 
00152     TEST_FOR_EXCEPTION(evals.size() < (unsigned int) n,
00153                        std::invalid_argument, "Anasazi::BasicSort:sort(): eigenvalue vector size isn't consistent with n.");
00154     if (perm) {
00155       TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
00156                          std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n.");
00157     }
00158 
00159     // Temp integer for swapping the index of the permutation, used in all sorting types.
00160     int tempord=0;
00161 
00162     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00163     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00164 
00165     // Temp variable for swapping the eigenvalue used in all sorting types.
00166     MagnitudeType temp;
00167 
00168     Teuchos::LAPACK<int,MagnitudeType> lapack;
00169 
00170     //
00171     // Reset the permutation if it is required.
00172     //
00173     if (perm) {
00174       for (i=0; i < n; i++) {
00175         (*perm)[i] = i;
00176       }
00177     }
00178     //
00179     // These methods use an insertion sort method to circumvent recursive calls.
00180     //---------------------------------------------------------------
00181     // Sort eigenvalues in increasing order of magnitude
00182     //---------------------------------------------------------------
00183     if (!which_.compare("SM")) {
00184       for (j=1; j < n; j++) {
00185         temp = evals[j]; 
00186         if (perm) {
00187           tempord = (*perm)[j];
00188         }
00189         MagnitudeType temp2 = MT::magnitude(evals[j]);
00190         for (i=j-1; i >=0 && MT::magnitude(evals[i]) > temp2; i--) {
00191           evals[i+1] = evals[i];
00192           if (perm) {
00193             (*perm)[i+1]=(*perm)[i];
00194           }
00195         }
00196         evals[i+1] = temp; 
00197         if (perm) {
00198           (*perm)[i+1] = tempord;
00199         }
00200       }
00201       return;
00202     }
00203     //---------------------------------------------------------------
00204     // Sort eigenvalues in increasing order of real part
00205     //---------------------------------------------------------------
00206     if (!which_.compare("SR")) {
00207       for (j=1; j < n; j++) {
00208         temp = evals[j]; 
00209         if (perm) {
00210           tempord = (*perm)[j];
00211         }
00212         for (i=j-1; i >= 0 && evals[i] > temp; i--) {
00213           evals[i+1]=evals[i];
00214           if (perm) {
00215             (*perm)[i+1]=(*perm)[i];
00216           }
00217         }
00218         evals[i+1] = temp; 
00219         if (perm) {
00220           (*perm)[i+1] = tempord;
00221         }
00222       }
00223       return;
00224     }
00225     //---------------------------------------------------------------
00226     // Sort eigenvalues in increasing order of imaginary part
00227     // NOTE:  There is no implementation for this since this sorting
00228     // method assumes only real eigenvalues.
00229     //---------------------------------------------------------------
00230     TEST_FOR_EXCEPTION(!which_.compare("SI"), SortManagerError, 
00231                        "Anasazi::BasicSort::sort() with one arg assumes real eigenvalues");
00232     //---------------------------------------------------------------
00233     // Sort eigenvalues in decreasing order of magnitude
00234     //---------------------------------------------------------------
00235     if (!which_.compare("LM")) {
00236       for (j=1; j < n; j++) {
00237         temp = evals[j]; 
00238         if (perm) {
00239           tempord = (*perm)[j];
00240         }
00241         MagnitudeType temp2 = MT::magnitude(evals[j]);
00242         for (i=j-1; i >= 0 && MT::magnitude(evals[i]) < temp2; i--) {
00243           evals[i+1]=evals[i];
00244           if (perm) {
00245             (*perm)[i+1]=(*perm)[i];
00246           }
00247         }
00248         evals[i+1] = temp; 
00249         if (perm) {
00250           (*perm)[i+1] = tempord;
00251         }
00252       }
00253       return;
00254     }
00255     //---------------------------------------------------------------
00256     // Sort eigenvalues in decreasing order of real part
00257     //---------------------------------------------------------------
00258     if (!which_.compare("LR")) {
00259       for (j=1; j < n; j++) {
00260         temp = evals[j]; 
00261         if (perm) {
00262           tempord = (*perm)[j];
00263         }
00264         for (i=j-1; i >= 0 && evals[i]<temp; i--) {
00265           evals[i+1]=evals[i];
00266           if (perm) {
00267             (*perm)[i+1]=(*perm)[i];
00268           }
00269         }
00270         evals[i+1] = temp; 
00271         if (perm) {
00272           (*perm)[i+1] = tempord;
00273         }
00274       }
00275       return;
00276     }
00277     //---------------------------------------------------------------
00278     // Sort eigenvalues in decreasing order of imaginary part
00279     // NOTE:  There is no implementation for this since this templating
00280     // assumes only real eigenvalues.
00281     //---------------------------------------------------------------
00282     TEST_FOR_EXCEPTION(!which_.compare("LI"), SortManagerError, 
00283                        "Anasazi::BasicSort::sort() with one arg assumes real eigenvalues");
00284     
00285     // The character string held by this class is not valid.  
00286     TEST_FOR_EXCEPTION(true, std::logic_error, 
00287                        "Anasazi::BasicSort::sort(): sorting order is not valid");
00288   }
00289 
00290 
00291   template<class ScalarType, class MV, class OP>
00292   void BasicSort<ScalarType,MV,OP>::sort(Eigensolver<ScalarType,MV,OP>* solver, 
00293                                          const int n,
00294                                          std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &r_evals, 
00295                                          std::vector<typename Teuchos::ScalarTraits<ScalarType>::magnitudeType> &i_evals, 
00296                                          std::vector<int> *perm) const 
00297   {
00298     typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
00299     typedef Teuchos::ScalarTraits<MagnitudeType> MT;
00300 
00301     TEST_FOR_EXCEPTION(r_evals.size() < (unsigned int) n || i_evals.size() < (unsigned int) n,
00302                        std::invalid_argument, "Anasazi::BasicSort:sort(): real and imaginary vector sizes aren't consistent with n.");
00303     if (perm) {
00304       TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
00305                          std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n.");
00306     }
00307     int i=0,j=0;
00308     int tempord=0;
00309 
00310     MagnitudeType temp, tempr, tempi;
00311     Teuchos::LAPACK<int,MagnitudeType> lapack;
00312     //
00313     // Reset the index
00314     //
00315     if (perm) {
00316       for (i=0; i < n; i++) {
00317         (*perm)[i] = i;
00318       }
00319     }
00320     //
00321     // These methods use an insertion sort method to circumvent recursive calls.
00322     //---------------------------------------------------------------
00323     // Sort eigenvalues in increasing order of magnitude
00324     //---------------------------------------------------------------
00325     if (!which_.compare("SM")) {
00326       for (j=1; j < n; j++) {
00327         tempr = r_evals[j]; tempi = i_evals[j]; 
00328         if (perm) {
00329           tempord = (*perm)[j];
00330         }
00331         temp=lapack.LAPY2(r_evals[j],i_evals[j]);
00332         for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i]) > temp; i--) {
00333           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00334           if (perm) {
00335             (*perm)[i+1]=(*perm)[i];
00336           }
00337         }
00338         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00339         if (perm) {
00340           (*perm)[i+1] = tempord;
00341         }
00342       }
00343       return;
00344     }
00345     //---------------------------------------------------------------
00346     // Sort eigenvalues in increasing order of real part
00347     //---------------------------------------------------------------
00348     if (!which_.compare("SR")) {
00349       for (j=1; j < n; j++) {
00350         tempr = r_evals[j]; tempi = i_evals[j]; 
00351         if (perm) {
00352           tempord = (*perm)[j];
00353         }
00354         for (i=j-1; i>=0 && r_evals[i]>tempr; i--) {
00355           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00356           if (perm) {
00357             (*perm)[i+1]=(*perm)[i];
00358           }
00359         }
00360         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00361         if (perm) {
00362           (*perm)[i+1] = tempord;
00363         }
00364       }
00365       return;
00366     }
00367     //---------------------------------------------------------------
00368     // Sort eigenvalues in increasing order of imaginary part
00369     //---------------------------------------------------------------
00370     if (!which_.compare("SI")) {
00371       for (j=1; j < n; j++) {
00372         tempr = r_evals[j]; tempi = i_evals[j]; 
00373         if (perm) {
00374           tempord = (*perm)[j];
00375         }
00376         for (i=j-1; i>=0 && i_evals[i]>tempi; i--) {
00377           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00378           if (perm) {
00379             (*perm)[i+1]=(*perm)[i];
00380           }
00381         }
00382         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00383         if (perm) {
00384           (*perm)[i+1] = tempord;
00385         }
00386       }
00387       return;
00388     }
00389     //---------------------------------------------------------------
00390     // Sort eigenvalues in decreasing order of magnitude
00391     //---------------------------------------------------------------
00392     if (!which_.compare("LM")) {
00393       for (j=1; j < n; j++) {
00394         tempr = r_evals[j]; tempi = i_evals[j]; 
00395         if (perm) {
00396           tempord = (*perm)[j];
00397         }
00398         temp=lapack.LAPY2(r_evals[j],i_evals[j]);
00399         for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])<temp; i--) {
00400           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00401           if (perm) {
00402             (*perm)[i+1]=(*perm)[i];
00403           }
00404         }
00405         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00406         if (perm) {
00407           (*perm)[i+1] = tempord;
00408         }
00409       }        
00410       return;
00411     }
00412     //---------------------------------------------------------------
00413     // Sort eigenvalues in decreasing order of real part
00414     //---------------------------------------------------------------
00415     if (!which_.compare("LR")) {
00416       for (j=1; j < n; j++) {
00417         tempr = r_evals[j]; tempi = i_evals[j]; 
00418         if (perm) {
00419           tempord = (*perm)[j];
00420         }
00421         for (i=j-1; i>=0 && r_evals[i]<tempr; i--) {
00422           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00423           if (perm) {
00424             (*perm)[i+1]=(*perm)[i];
00425           }
00426         }
00427         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00428         if (perm) {
00429           (*perm)[i+1] = tempord;
00430         }
00431       }        
00432       return;
00433     }
00434     //---------------------------------------------------------------
00435     // Sort eigenvalues in decreasing order of imaginary part
00436     //---------------------------------------------------------------
00437     if (!which_.compare("LI")) {
00438       for (j=1; j < n; j++) {
00439         tempr = r_evals[j]; tempi = i_evals[j]; 
00440         if (perm) {
00441           tempord = (*perm)[j];
00442         }
00443         for (i=j-1; i>=0 && i_evals[i]<tempi; i--) {
00444           r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i];
00445           if (perm) {
00446             (*perm)[i+1]=(*perm)[i];
00447           }
00448         }
00449         r_evals[i+1] = tempr; i_evals[i+1] = tempi; 
00450         if (perm) {
00451           (*perm)[i+1] = tempord;
00452         }
00453       }
00454       return;
00455     }
00456 
00457     TEST_FOR_EXCEPTION(true, std::logic_error, 
00458                        "Anasazi::BasicSort::sort(): sorting order is not valid");
00459   }
00460   
00461   
00462 } // namespace Anasazi
00463 
00464 #endif // ANASAZI_BASIC_SORT_HPP
00465 

Generated on Tue Oct 20 12:45:18 2009 for Anasazi by doxygen 1.4.7