Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziBasicSort.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Anasazi: Block Eigensolvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
46 #ifndef ANASAZI_BASIC_SORT_HPP
47 #define ANASAZI_BASIC_SORT_HPP
48 
56 #include "AnasaziConfigDefs.hpp"
57 #include "AnasaziSortManager.hpp"
58 #include "Teuchos_LAPACK.hpp"
59 #include "Teuchos_ScalarTraits.hpp"
61 
62 namespace Anasazi {
63 
64  template<class MagnitudeType>
65  class BasicSort : public SortManager<MagnitudeType> {
66 
67  public:
68 
75 
80  BasicSort( const std::string &which = "LM" );
81 
83  virtual ~BasicSort();
84 
86 
95  void setSortType( const std::string &which );
96 
111  void sort(std::vector<MagnitudeType> &evals, Teuchos::RCP<std::vector<int> > perm = Teuchos::null, int n = -1) const;
112 
131  void sort(std::vector<MagnitudeType> &r_evals,
132  std::vector<MagnitudeType> &i_evals,
133  Teuchos::RCP<std::vector<int> > perm = Teuchos::null,
134  int n = -1) const;
135 
136  protected:
137 
138  // enum for sort type
139  enum SType {
140  LM, SM,
141  LR, SR,
142  LI, SI
143  };
144  SType which_;
145 
146  // sorting methods
147  template <class LTorGT>
148  struct compMag {
149  // for real-only LM,SM
150  bool operator()(MagnitudeType, MagnitudeType);
151  // for real-only LM,SM with permutation
152  template <class First, class Second>
153  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
154  };
155 
156  template <class LTorGT>
157  struct compMag2 {
158  // for real-imag LM,SM
159  bool operator()(std::pair<MagnitudeType,MagnitudeType>, std::pair<MagnitudeType,MagnitudeType>);
160  // for real-imag LM,SM with permutation
161  template <class First, class Second>
162  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
163  };
164 
165  template <class LTorGT>
166  struct compAlg {
167  // for real-imag LR,SR,LI,SI
168  bool operator()(MagnitudeType, MagnitudeType);
169  template <class First, class Second>
170  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
171  };
172 
173  template <typename pair_type>
174  struct sel1st
175  {
176  const typename pair_type::first_type &operator()(const pair_type &v) const;
177  };
178 
179  template <typename pair_type>
180  struct sel2nd
181  {
182  const typename pair_type::second_type &operator()(const pair_type &v) const;
183  };
184  };
185 
186 
188  // IMPLEMENTATION
190 
191  template<class MagnitudeType>
193  {
194  std::string which = "LM";
195  which = pl.get("Sort Strategy",which);
196  setSortType(which);
197  }
198 
199  template<class MagnitudeType>
200  BasicSort<MagnitudeType>::BasicSort(const std::string &which)
201  {
202  setSortType(which);
203  }
204 
205  template<class MagnitudeType>
207  {}
208 
209  template<class MagnitudeType>
210  void BasicSort<MagnitudeType>::setSortType(const std::string &which)
211  {
212  // make upper case
213  std::string whichlc(which);
214  std::transform(which.begin(),which.end(),whichlc.begin(),(int(*)(int)) std::toupper);
215  if (whichlc == "LM") {
216  which_ = LM;
217  }
218  else if (whichlc == "SM") {
219  which_ = SM;
220  }
221  else if (whichlc == "LR") {
222  which_ = LR;
223  }
224  else if (whichlc == "SR") {
225  which_ = SR;
226  }
227  else if (whichlc == "LI") {
228  which_ = LI;
229  }
230  else if (whichlc == "SI") {
231  which_ = SI;
232  }
233  else {
234  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Anasazi::BasicSort::setSortType(): sorting order is not valid");
235  }
236  }
237 
238  template<class MagnitudeType>
239  void BasicSort<MagnitudeType>::sort(std::vector<MagnitudeType> &evals, Teuchos::RCP<std::vector<int> > perm, int n) const
240  {
241  TEUCHOS_TEST_FOR_EXCEPTION(n < -1, std::invalid_argument, "Anasazi::BasicSort::sort(r): n must be n >= 0 or n == -1.");
242  if (n == -1) {
243  n = evals.size();
244  }
245  TEUCHOS_TEST_FOR_EXCEPTION(evals.size() < (unsigned int) n,
246  std::invalid_argument, "Anasazi::BasicSort::sort(r): eigenvalue vector size isn't consistent with n.");
247  if (perm != Teuchos::null) {
248  TEUCHOS_TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
249  std::invalid_argument, "Anasazi::BasicSort::sort(r): permutation vector size isn't consistent with n.");
250  }
251 
252  typedef std::greater<MagnitudeType> greater_mt;
253  typedef std::less<MagnitudeType> less_mt;
254 
255  if (perm == Teuchos::null) {
256  //
257  // if permutation index is not required, just sort using the values
258  //
259  if (which_ == LM ) {
260  std::sort(evals.begin(),evals.begin()+n,compMag<greater_mt>());
261  }
262  else if (which_ == SM) {
263  std::sort(evals.begin(),evals.begin()+n,compMag<less_mt>());
264  }
265  else if (which_ == LR) {
266  std::sort(evals.begin(),evals.begin()+n,compAlg<greater_mt>());
267  }
268  else if (which_ == SR) {
269  std::sort(evals.begin(),evals.begin()+n,compAlg<less_mt>());
270  }
271  else {
272  TEUCHOS_TEST_FOR_EXCEPTION(true, SortManagerError, "Anasazi::BasicSort::sort(r): LI or SI sorting invalid for real scalar types." );
273  }
274  }
275  else {
276  //
277  // if permutation index is required, we must sort the two at once
278  // in this case, we arrange a pair structure: <value,index>
279  // default comparison operator for pair<t1,t2> is lexographic:
280  // compare first t1, then t2
281  // this works fine for us here.
282  //
283 
284  // copy the values and indices into the pair structure
285  std::vector< std::pair<MagnitudeType,int> > pairs(n);
286  for (int i=0; i<n; i++) {
287  pairs[i] = std::make_pair(evals[i],i);
288  }
289 
290  // sort the pair structure
291  if (which_ == LM) {
292  std::sort(pairs.begin(),pairs.begin()+n,compMag<greater_mt>());
293  }
294  else if (which_ == SM) {
295  std::sort(pairs.begin(),pairs.begin()+n,compMag<less_mt>());
296  }
297  else if (which_ == LR) {
298  std::sort(pairs.begin(),pairs.begin()+n,compAlg<greater_mt>());
299  }
300  else if (which_ == SR) {
301  std::sort(pairs.begin(),pairs.begin()+n,compAlg<less_mt>());
302  }
303  else {
304  TEUCHOS_TEST_FOR_EXCEPTION(true, SortManagerError, "Anasazi::BasicSort::sort(r): LI or SI sorting invalid for real scalar types." );
305  }
306 
307  // copy the values and indices out of the pair structure
308  std::transform(pairs.begin(),pairs.end(),evals.begin(),sel1st< std::pair<MagnitudeType,int> >());
309  std::transform(pairs.begin(),pairs.end(),perm->begin(),sel2nd< std::pair<MagnitudeType,int> >());
310  }
311  }
312 
313 
314  template<class T1, class T2>
315  class MakePairOp {
316  public:
317  std::pair<T1,T2> operator()( const T1 &t1, const T2 &t2 )
318  { return std::make_pair(t1, t2); }
319  };
320 
321 
322  template<class MagnitudeType>
323  void BasicSort<MagnitudeType>::sort(std::vector<MagnitudeType> &r_evals,
324  std::vector<MagnitudeType> &i_evals,
325  Teuchos::RCP< std::vector<int> > perm,
326  int n) const
327  {
328 
329  //typedef typename std::vector<MagnitudeType>::iterator r_eval_iter_t; // unused
330  //typedef typename std::vector<MagnitudeType>::iterator i_eval_iter_t; // unused
331 
332  TEUCHOS_TEST_FOR_EXCEPTION(n < -1, std::invalid_argument, "Anasazi::BasicSort::sort(r,i): n must be n >= 0 or n == -1.");
333  if (n == -1) {
334  n = r_evals.size() < i_evals.size() ? r_evals.size() : i_evals.size();
335  }
336  TEUCHOS_TEST_FOR_EXCEPTION(r_evals.size() < (unsigned int) n || i_evals.size() < (unsigned int) n,
337  std::invalid_argument, "Anasazi::BasicSort::sort(r,i): eigenvalue vector size isn't consistent with n.");
338  if (perm != Teuchos::null) {
339  TEUCHOS_TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
340  std::invalid_argument, "Anasazi::BasicSort::sort(r,i): permutation vector size isn't consistent with n.");
341  }
342 
343  typedef std::greater<MagnitudeType> greater_mt;
344  typedef std::less<MagnitudeType> less_mt;
345 
346  //
347  // put values into pairs
348  //
349  if (perm == Teuchos::null) {
350  //
351  // not permuting, so we don't need indices in the pairs
352  //
353  std::vector< std::pair<MagnitudeType,MagnitudeType> > pairs(n);
354  // for LM,SM, the order doesn't matter
355  // for LI,SI, the imaginary goes first
356  // for LR,SR, the real goes in first
357  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
358  std::transform(
359  r_evals.begin(), r_evals.begin()+n,
360  i_evals.begin(), pairs.begin(),
361  MakePairOp<MagnitudeType,MagnitudeType>());
362  }
363  else {
364  std::transform(
365  i_evals.begin(), i_evals.begin()+n,
366  r_evals.begin(), pairs.begin(),
367  MakePairOp<MagnitudeType,MagnitudeType>());
368  }
369 
370  if (which_ == LR || which_ == LI) {
371  std::sort(pairs.begin(),pairs.end(),compAlg<greater_mt>());
372  }
373  else if (which_ == SR || which_ == SI) {
374  std::sort(pairs.begin(),pairs.end(),compAlg<less_mt>());
375  }
376  else if (which_ == LM) {
377  std::sort(pairs.begin(),pairs.end(),compMag2<greater_mt>());
378  }
379  else {
380  std::sort(pairs.begin(),pairs.end(),compMag2<less_mt>());
381  }
382 
383  // extract the values
384  // for LM,SM,LR,SR: order is (real,imag)
385  // for LI,SI: order is (imag,real)
386  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
387  std::transform(pairs.begin(),pairs.end(),r_evals.begin(),sel1st< std::pair<MagnitudeType,MagnitudeType> >());
388  std::transform(pairs.begin(),pairs.end(),i_evals.begin(),sel2nd< std::pair<MagnitudeType,MagnitudeType> >());
389  }
390  else {
391  std::transform(pairs.begin(),pairs.end(),r_evals.begin(),sel2nd< std::pair<MagnitudeType,MagnitudeType> >());
392  std::transform(pairs.begin(),pairs.end(),i_evals.begin(),sel1st< std::pair<MagnitudeType,MagnitudeType> >());
393  }
394  }
395  else {
396  //
397  // permuting, we need indices in the pairs
398  //
399  std::vector< std::pair< std::pair<MagnitudeType,MagnitudeType>, int > > pairs(n);
400  // for LM,SM, the order doesn't matter
401  // for LI,SI, the imaginary goes first
402  // for LR,SR, the real goes in first
403  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
404  for (int i=0; i<n; i++) {
405  pairs[i] = std::make_pair(std::make_pair(r_evals[i],i_evals[i]),i);
406  }
407  }
408  else {
409  for (int i=0; i<n; i++) {
410  pairs[i] = std::make_pair(std::make_pair(i_evals[i],r_evals[i]),i);
411  }
412  }
413 
414  if (which_ == LR || which_ == LI) {
415  std::sort(pairs.begin(),pairs.end(),compAlg<greater_mt>());
416  }
417  else if (which_ == SR || which_ == SI) {
418  std::sort(pairs.begin(),pairs.end(),compAlg<less_mt>());
419  }
420  else if (which_ == LM) {
421  std::sort(pairs.begin(),pairs.end(),compMag2<greater_mt>());
422  }
423  else {
424  std::sort(pairs.begin(),pairs.end(),compMag2<less_mt>());
425  }
426 
427  // extract the values
428  // for LM,SM,LR,SR: order is (real,imag)
429  // for LI,SI: order is (imag,real)
430  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
431  for (int i=0; i<n; i++) {
432  r_evals[i] = pairs[i].first.first;
433  i_evals[i] = pairs[i].first.second;
434  (*perm)[i] = pairs[i].second;
435  }
436  }
437  else {
438  for (int i=0; i<n; i++) {
439  i_evals[i] = pairs[i].first.first;
440  r_evals[i] = pairs[i].first.second;
441  (*perm)[i] = pairs[i].second;
442  }
443  }
444  }
445  }
446 
447 
448  template<class MagnitudeType>
449  template<class LTorGT>
450  bool BasicSort<MagnitudeType>::compMag<LTorGT>::operator()(MagnitudeType v1, MagnitudeType v2)
451  {
453  LTorGT comp;
454  return comp( MTT::magnitude(v1), MTT::magnitude(v2) );
455  }
456 
457  template<class MagnitudeType>
458  template<class LTorGT>
459  bool BasicSort<MagnitudeType>::compMag2<LTorGT>::operator()(std::pair<MagnitudeType,MagnitudeType> v1, std::pair<MagnitudeType,MagnitudeType> v2)
460  {
461  MagnitudeType m1 = v1.first*v1.first + v1.second*v1.second;
462  MagnitudeType m2 = v2.first*v2.first + v2.second*v2.second;
463  LTorGT comp;
464  return comp( m1, m2 );
465  }
466 
467  template<class MagnitudeType>
468  template<class LTorGT>
469  bool BasicSort<MagnitudeType>::compAlg<LTorGT>::operator()(MagnitudeType v1, MagnitudeType v2)
470  {
471  LTorGT comp;
472  return comp( v1, v2 );
473  }
474 
475  template<class MagnitudeType>
476  template<class LTorGT>
477  template<class First, class Second>
478  bool BasicSort<MagnitudeType>::compMag<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
479  return (*this)(v1.first,v2.first);
480  }
481 
482  template<class MagnitudeType>
483  template<class LTorGT>
484  template<class First, class Second>
485  bool BasicSort<MagnitudeType>::compMag2<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
486  return (*this)(v1.first,v2.first);
487  }
488 
489  template<class MagnitudeType>
490  template<class LTorGT>
491  template<class First, class Second>
492  bool BasicSort<MagnitudeType>::compAlg<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
493  return (*this)(v1.first,v2.first);
494  }
495 
496  template <class MagnitudeType>
497  template <typename pair_type>
498  const typename pair_type::first_type &
499  BasicSort<MagnitudeType>::sel1st<pair_type>::operator()(const pair_type &v) const
500  {
501  return v.first;
502  }
503 
504  template <class MagnitudeType>
505  template <typename pair_type>
506  const typename pair_type::second_type &
507  BasicSort<MagnitudeType>::sel2nd<pair_type>::operator()(const pair_type &v) const
508  {
509  return v.second;
510  }
511 
512 } // namespace Anasazi
513 
514 #endif // ANASAZI_BASIC_SORT_HPP
515 
BasicSort(Teuchos::ParameterList &pl)
Parameter list driven constructor.
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
T & get(const std::string &name, T def_value)
void setSortType(const std::string &which)
Set sort type.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
SortManagerError is thrown when the Anasazi::SortManager is unable to sort the numbers, due to some failure of the sort method or error in calling it.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
Virtual base class which defines the interface between an eigensolver and a class whose job is the so...
void sort(std::vector< MagnitudeType > &evals, Teuchos::RCP< std::vector< int > > perm=Teuchos::null, int n=-1) const
Sort real eigenvalues, optionally returning the permutation vector.
Anasazi&#39;s templated pure virtual class for managing the sorting of approximate eigenvalues computed b...
virtual ~BasicSort()
Destructor.