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 // Anasazi: Block Eigensolvers Package
4 //
5 // Copyright 2004 NTESS and the Anasazi contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
14 #ifndef ANASAZI_BASIC_SORT_HPP
15 #define ANASAZI_BASIC_SORT_HPP
16 
24 #include "AnasaziConfigDefs.hpp"
25 #include "AnasaziSortManager.hpp"
26 #include "Teuchos_LAPACK.hpp"
27 #include "Teuchos_ScalarTraits.hpp"
29 
30 namespace Anasazi {
31 
32  template<class MagnitudeType>
33  class BasicSort : public SortManager<MagnitudeType> {
34 
35  public:
36 
43 
48  BasicSort( const std::string &which = "LM" );
49 
51  virtual ~BasicSort();
52 
54 
63  void setSortType( const std::string &which );
64 
79  void sort(std::vector<MagnitudeType> &evals, Teuchos::RCP<std::vector<int> > perm = Teuchos::null, int n = -1) const;
80 
99  void sort(std::vector<MagnitudeType> &r_evals,
100  std::vector<MagnitudeType> &i_evals,
101  Teuchos::RCP<std::vector<int> > perm = Teuchos::null,
102  int n = -1) const;
103 
104  protected:
105 
106  // enum for sort type
107  enum SType {
108  LM, SM,
109  LR, SR,
110  LI, SI
111  };
112  SType which_;
113 
114  // sorting methods
115  template <class LTorGT>
116  struct compMag {
117  // for real-only LM,SM
118  bool operator()(MagnitudeType, MagnitudeType);
119  // for real-only LM,SM with permutation
120  template <class First, class Second>
121  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
122  };
123 
124  template <class LTorGT>
125  struct compMag2 {
126  // for real-imag LM,SM
127  bool operator()(std::pair<MagnitudeType,MagnitudeType>, std::pair<MagnitudeType,MagnitudeType>);
128  // for real-imag LM,SM with permutation
129  template <class First, class Second>
130  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
131  };
132 
133  template <class LTorGT>
134  struct compAlg {
135  // for real-imag LR,SR,LI,SI
136  bool operator()(MagnitudeType, MagnitudeType);
137  template <class First, class Second>
138  bool operator()(std::pair<First,Second>, std::pair<First,Second>);
139  };
140 
141  template <typename pair_type>
142  struct sel1st
143  {
144  const typename pair_type::first_type &operator()(const pair_type &v) const;
145  };
146 
147  template <typename pair_type>
148  struct sel2nd
149  {
150  const typename pair_type::second_type &operator()(const pair_type &v) const;
151  };
152  };
153 
154 
156  // IMPLEMENTATION
158 
159  template<class MagnitudeType>
161  {
162  std::string which = "LM";
163  which = pl.get("Sort Strategy",which);
164  setSortType(which);
165  }
166 
167  template<class MagnitudeType>
168  BasicSort<MagnitudeType>::BasicSort(const std::string &which)
169  {
170  setSortType(which);
171  }
172 
173  template<class MagnitudeType>
175  {}
176 
177  template<class MagnitudeType>
178  void BasicSort<MagnitudeType>::setSortType(const std::string &which)
179  {
180  // make upper case
181  std::string whichlc(which);
182  std::transform(which.begin(),which.end(),whichlc.begin(),(int(*)(int)) std::toupper);
183  if (whichlc == "LM") {
184  which_ = LM;
185  }
186  else if (whichlc == "SM") {
187  which_ = SM;
188  }
189  else if (whichlc == "LR") {
190  which_ = LR;
191  }
192  else if (whichlc == "SR") {
193  which_ = SR;
194  }
195  else if (whichlc == "LI") {
196  which_ = LI;
197  }
198  else if (whichlc == "SI") {
199  which_ = SI;
200  }
201  else {
202  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "Anasazi::BasicSort::setSortType(): sorting order is not valid");
203  }
204  }
205 
206  template<class MagnitudeType>
207  void BasicSort<MagnitudeType>::sort(std::vector<MagnitudeType> &evals, Teuchos::RCP<std::vector<int> > perm, int n) const
208  {
209  TEUCHOS_TEST_FOR_EXCEPTION(n < -1, std::invalid_argument, "Anasazi::BasicSort::sort(r): n must be n >= 0 or n == -1.");
210  if (n == -1) {
211  n = evals.size();
212  }
213  TEUCHOS_TEST_FOR_EXCEPTION(evals.size() < (unsigned int) n,
214  std::invalid_argument, "Anasazi::BasicSort::sort(r): eigenvalue vector size isn't consistent with n.");
215  if (perm != Teuchos::null) {
216  TEUCHOS_TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
217  std::invalid_argument, "Anasazi::BasicSort::sort(r): permutation vector size isn't consistent with n.");
218  }
219 
220  typedef std::greater<MagnitudeType> greater_mt;
221  typedef std::less<MagnitudeType> less_mt;
222 
223  if (perm == Teuchos::null) {
224  //
225  // if permutation index is not required, just sort using the values
226  //
227  if (which_ == LM ) {
228  std::sort(evals.begin(),evals.begin()+n,compMag<greater_mt>());
229  }
230  else if (which_ == SM) {
231  std::sort(evals.begin(),evals.begin()+n,compMag<less_mt>());
232  }
233  else if (which_ == LR) {
234  std::sort(evals.begin(),evals.begin()+n,compAlg<greater_mt>());
235  }
236  else if (which_ == SR) {
237  std::sort(evals.begin(),evals.begin()+n,compAlg<less_mt>());
238  }
239  else {
240  TEUCHOS_TEST_FOR_EXCEPTION(true, SortManagerError, "Anasazi::BasicSort::sort(r): LI or SI sorting invalid for real scalar types." );
241  }
242  }
243  else {
244  //
245  // if permutation index is required, we must sort the two at once
246  // in this case, we arrange a pair structure: <value,index>
247  // default comparison operator for pair<t1,t2> is lexographic:
248  // compare first t1, then t2
249  // this works fine for us here.
250  //
251 
252  // copy the values and indices into the pair structure
253  std::vector< std::pair<MagnitudeType,int> > pairs(n);
254  for (int i=0; i<n; i++) {
255  pairs[i] = std::make_pair(evals[i],i);
256  }
257 
258  // sort the pair structure
259  if (which_ == LM) {
260  std::sort(pairs.begin(),pairs.begin()+n,compMag<greater_mt>());
261  }
262  else if (which_ == SM) {
263  std::sort(pairs.begin(),pairs.begin()+n,compMag<less_mt>());
264  }
265  else if (which_ == LR) {
266  std::sort(pairs.begin(),pairs.begin()+n,compAlg<greater_mt>());
267  }
268  else if (which_ == SR) {
269  std::sort(pairs.begin(),pairs.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  // copy the values and indices out of the pair structure
276  std::transform(pairs.begin(),pairs.end(),evals.begin(),sel1st< std::pair<MagnitudeType,int> >());
277  std::transform(pairs.begin(),pairs.end(),perm->begin(),sel2nd< std::pair<MagnitudeType,int> >());
278  }
279  }
280 
281 
282  template<class T1, class T2>
283  class MakePairOp {
284  public:
285  std::pair<T1,T2> operator()( const T1 &t1, const T2 &t2 )
286  { return std::make_pair(t1, t2); }
287  };
288 
289 
290  template<class MagnitudeType>
291  void BasicSort<MagnitudeType>::sort(std::vector<MagnitudeType> &r_evals,
292  std::vector<MagnitudeType> &i_evals,
293  Teuchos::RCP< std::vector<int> > perm,
294  int n) const
295  {
296 
297  //typedef typename std::vector<MagnitudeType>::iterator r_eval_iter_t; // unused
298  //typedef typename std::vector<MagnitudeType>::iterator i_eval_iter_t; // unused
299 
300  TEUCHOS_TEST_FOR_EXCEPTION(n < -1, std::invalid_argument, "Anasazi::BasicSort::sort(r,i): n must be n >= 0 or n == -1.");
301  if (n == -1) {
302  n = r_evals.size() < i_evals.size() ? r_evals.size() : i_evals.size();
303  }
304  TEUCHOS_TEST_FOR_EXCEPTION(r_evals.size() < (unsigned int) n || i_evals.size() < (unsigned int) n,
305  std::invalid_argument, "Anasazi::BasicSort::sort(r,i): eigenvalue vector size isn't consistent with n.");
306  if (perm != Teuchos::null) {
307  TEUCHOS_TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n,
308  std::invalid_argument, "Anasazi::BasicSort::sort(r,i): permutation vector size isn't consistent with n.");
309  }
310 
311  typedef std::greater<MagnitudeType> greater_mt;
312  typedef std::less<MagnitudeType> less_mt;
313 
314  //
315  // put values into pairs
316  //
317  if (perm == Teuchos::null) {
318  //
319  // not permuting, so we don't need indices in the pairs
320  //
321  std::vector< std::pair<MagnitudeType,MagnitudeType> > pairs(n);
322  // for LM,SM, the order doesn't matter
323  // for LI,SI, the imaginary goes first
324  // for LR,SR, the real goes in first
325  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
326  std::transform(
327  r_evals.begin(), r_evals.begin()+n,
328  i_evals.begin(), pairs.begin(),
329  MakePairOp<MagnitudeType,MagnitudeType>());
330  }
331  else {
332  std::transform(
333  i_evals.begin(), i_evals.begin()+n,
334  r_evals.begin(), pairs.begin(),
335  MakePairOp<MagnitudeType,MagnitudeType>());
336  }
337 
338  if (which_ == LR || which_ == LI) {
339  std::sort(pairs.begin(),pairs.end(),compAlg<greater_mt>());
340  }
341  else if (which_ == SR || which_ == SI) {
342  std::sort(pairs.begin(),pairs.end(),compAlg<less_mt>());
343  }
344  else if (which_ == LM) {
345  std::sort(pairs.begin(),pairs.end(),compMag2<greater_mt>());
346  }
347  else {
348  std::sort(pairs.begin(),pairs.end(),compMag2<less_mt>());
349  }
350 
351  // extract the values
352  // for LM,SM,LR,SR: order is (real,imag)
353  // for LI,SI: order is (imag,real)
354  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
355  std::transform(pairs.begin(),pairs.end(),r_evals.begin(),sel1st< std::pair<MagnitudeType,MagnitudeType> >());
356  std::transform(pairs.begin(),pairs.end(),i_evals.begin(),sel2nd< std::pair<MagnitudeType,MagnitudeType> >());
357  }
358  else {
359  std::transform(pairs.begin(),pairs.end(),r_evals.begin(),sel2nd< std::pair<MagnitudeType,MagnitudeType> >());
360  std::transform(pairs.begin(),pairs.end(),i_evals.begin(),sel1st< std::pair<MagnitudeType,MagnitudeType> >());
361  }
362  }
363  else {
364  //
365  // permuting, we need indices in the pairs
366  //
367  std::vector< std::pair< std::pair<MagnitudeType,MagnitudeType>, int > > pairs(n);
368  // for LM,SM, the order doesn't matter
369  // for LI,SI, the imaginary goes first
370  // for LR,SR, the real goes in first
371  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
372  for (int i=0; i<n; i++) {
373  pairs[i] = std::make_pair(std::make_pair(r_evals[i],i_evals[i]),i);
374  }
375  }
376  else {
377  for (int i=0; i<n; i++) {
378  pairs[i] = std::make_pair(std::make_pair(i_evals[i],r_evals[i]),i);
379  }
380  }
381 
382  if (which_ == LR || which_ == LI) {
383  std::sort(pairs.begin(),pairs.end(),compAlg<greater_mt>());
384  }
385  else if (which_ == SR || which_ == SI) {
386  std::sort(pairs.begin(),pairs.end(),compAlg<less_mt>());
387  }
388  else if (which_ == LM) {
389  std::sort(pairs.begin(),pairs.end(),compMag2<greater_mt>());
390  }
391  else {
392  std::sort(pairs.begin(),pairs.end(),compMag2<less_mt>());
393  }
394 
395  // extract the values
396  // for LM,SM,LR,SR: order is (real,imag)
397  // for LI,SI: order is (imag,real)
398  if (which_ == LR || which_ == SR || which_ == LM || which_ == SM) {
399  for (int i=0; i<n; i++) {
400  r_evals[i] = pairs[i].first.first;
401  i_evals[i] = pairs[i].first.second;
402  (*perm)[i] = pairs[i].second;
403  }
404  }
405  else {
406  for (int i=0; i<n; i++) {
407  i_evals[i] = pairs[i].first.first;
408  r_evals[i] = pairs[i].first.second;
409  (*perm)[i] = pairs[i].second;
410  }
411  }
412  }
413  }
414 
415 
416  template<class MagnitudeType>
417  template<class LTorGT>
418  bool BasicSort<MagnitudeType>::compMag<LTorGT>::operator()(MagnitudeType v1, MagnitudeType v2)
419  {
421  LTorGT comp;
422  return comp( MTT::magnitude(v1), MTT::magnitude(v2) );
423  }
424 
425  template<class MagnitudeType>
426  template<class LTorGT>
427  bool BasicSort<MagnitudeType>::compMag2<LTorGT>::operator()(std::pair<MagnitudeType,MagnitudeType> v1, std::pair<MagnitudeType,MagnitudeType> v2)
428  {
429  MagnitudeType m1 = v1.first*v1.first + v1.second*v1.second;
430  MagnitudeType m2 = v2.first*v2.first + v2.second*v2.second;
431  LTorGT comp;
432  return comp( m1, m2 );
433  }
434 
435  template<class MagnitudeType>
436  template<class LTorGT>
437  bool BasicSort<MagnitudeType>::compAlg<LTorGT>::operator()(MagnitudeType v1, MagnitudeType v2)
438  {
439  LTorGT comp;
440  return comp( v1, v2 );
441  }
442 
443  template<class MagnitudeType>
444  template<class LTorGT>
445  template<class First, class Second>
446  bool BasicSort<MagnitudeType>::compMag<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
447  return (*this)(v1.first,v2.first);
448  }
449 
450  template<class MagnitudeType>
451  template<class LTorGT>
452  template<class First, class Second>
453  bool BasicSort<MagnitudeType>::compMag2<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
454  return (*this)(v1.first,v2.first);
455  }
456 
457  template<class MagnitudeType>
458  template<class LTorGT>
459  template<class First, class Second>
460  bool BasicSort<MagnitudeType>::compAlg<LTorGT>::operator()(std::pair<First,Second> v1, std::pair<First,Second> v2) {
461  return (*this)(v1.first,v2.first);
462  }
463 
464  template <class MagnitudeType>
465  template <typename pair_type>
466  const typename pair_type::first_type &
467  BasicSort<MagnitudeType>::sel1st<pair_type>::operator()(const pair_type &v) const
468  {
469  return v.first;
470  }
471 
472  template <class MagnitudeType>
473  template <typename pair_type>
474  const typename pair_type::second_type &
475  BasicSort<MagnitudeType>::sel2nd<pair_type>::operator()(const pair_type &v) const
476  {
477  return v.second;
478  }
479 
480 } // namespace Anasazi
481 
482 #endif // ANASAZI_BASIC_SORT_HPP
483 
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.