Anasazi Version of the Day
Loading...
Searching...
No Matches
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
13
14#ifndef ANASAZI_BASIC_SORT_HPP
15#define ANASAZI_BASIC_SORT_HPP
16
23
24#include "AnasaziConfigDefs.hpp"
26#include "Teuchos_LAPACK.hpp"
27#include "Teuchos_ScalarTraits.hpp"
28#include "Teuchos_ParameterList.hpp"
29
30namespace Anasazi {
31
32 template<class MagnitudeType>
33 class BasicSort : public SortManager<MagnitudeType> {
34
35 public:
36
42 BasicSort( Teuchos::ParameterList &pl );
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>
160 BasicSort<MagnitudeType>::BasicSort(Teuchos::ParameterList &pl)
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>
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 {
420 typedef Teuchos::ScalarTraits<MagnitudeType> MTT;
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
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...
virtual ~BasicSort()
Destructor.
BasicSort(Teuchos::ParameterList &pl)
Parameter list driven constructor.
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.
void setSortType(const std::string &which)
Set sort type.
SortManagerError is thrown when the Anasazi::SortManager is unable to sort the numbers,...
SortManager()
Default constructor.
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.