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
14#ifndef ANASAZI_BASIC_SORT_HPP
15#define ANASAZI_BASIC_SORT_HPP
16
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...
An implementation of the Anasazi::SortManager that performs a collection of common sorting techniques...
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,...
Anasazi's templated pure virtual class for managing the sorting of approximate eigenvalues computed b...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.