STK++ 0.9.13
STK_lapack_SymEigen.h
Go to the documentation of this file.
1/*--------------------------------------------------------------------*/
2/* Copyright (C) 2004-2016 Serge Iovleff
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with this program; if not, write to the
16 Free Software Foundation, Inc.,
17 59 Temple Place,
18 Suite 330,
19 Boston, MA 02111-1307
20 USA
21
22 Contact : S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
23*/
24
25/*
26 * Project: stkpp::Algebra
27 * created on: 20 nov. 2013
28 * Author: iovleff, S..._Dot_I..._At_stkpp_Dot_org (see copyright for ...)
29 **/
30
36#ifndef STK_LAPACK_SYMEIGEN_H
37#define STK_LAPACK_SYMEIGEN_H
38
39#include "STK_ISymEigen.h"
40#include "STK_lapack_Util.h"
41
42namespace STK
43{
44
45// forward declaration
46namespace lapack
47{
48template<class SquareArray> class SymEigen;
49}
50
51namespace hidden
52{
57template<class SquareArray_>
58struct AlgebraTraits< lapack::SymEigen<SquareArray_> >
59{
61};
62
63} // namespace hidden
64
65
66namespace lapack
67{
96template<class SquareArray>
97class SymEigen: public ISymEigen< SymEigen<SquareArray> >
98{
99 public:
101 using Base::eigenValues_;
103 using Base::range_;
104 using Base::norm_;
105 using Base::rank_;
106 using Base::det_;
107
109 SymEigen();
120 SymEigen( SquareArray const& data, bool ref =false);
124 template<class Derived>
125 SymEigen( ArrayBase<Derived> const& data);
129 SymEigen( SymEigen const& eigen);
131 virtual ~SymEigen() {}
132
133 // setters
137 inline void setJobz(char jobz) { jobz_ = jobz;}
143 inline void setRange(char range) { RANGE_ = range;}
148 inline void setUplo(char uplo) { UPLO_ = uplo;}
153 inline void setVlAndVu(Real const& vl, Real const& vu) { VL_ = vl; VU_ = vu;}
160 inline void setIlAndIu(int il, int iu) { IL_ = il; IU_ = iu;}
161
163 inline virtual SymEigen* clone() const { return new SymEigen(*this);}
168 bool runImpl();
169
170 private:
174 int IL_, IU_;
175};
180/* @brief Default Constructor */
181template<class SquareArray>
183 , jobz_('V'), RANGE_('A'), UPLO_('U')
184 , VL_(0.0), VU_(0.0), IL_(0), IU_(0)
185{}
186/* @brief Constructor
187 * @param data reference on a symmetric square matrix
188 * @param ref @c true if we overwrite the data set, @c false otherwise
189 */
190template<class SquareArray>
191SymEigen<SquareArray>::SymEigen( SquareArray const& data, bool ref)
192 : Base(data)
193 , jobz_('V'), RANGE_('A'), UPLO_('U')
194 , VL_(0.0), VU_(0.0), IL_(0), IU_(0)
195{}
196/* @brief Constructor
197 * @param data reference on a symmetric square matrix
198 * @param ref @c true if we overwrite the data set, @c false otherwise
199 */
200template<>
201inline SymEigen<CSquareX>::SymEigen( CSquareX const& data, bool ref)
202 : Base(data, ref)
203 , jobz_('V'), RANGE_('A'), UPLO_('U')
204 , VL_(0.0), VU_(0.0), IL_(0), IU_(0)
205{}
206
207template<class SquareArray>
208template<class Derived>
210 : Base(data)
211 , jobz_('V'), RANGE_('A'), UPLO_('U')
212 , VL_(0.0), VU_(0.0), IL_(0), IU_(0)
213{}
217template<class SquareArray>
219 : Base(eigen)
220 , jobz_(eigen.jobz_), RANGE_(eigen.RANGE_), UPLO_(eigen.UPLO_)
221 , VL_(eigen.VL_), VU_(eigen.VU_), IL_(eigen.IL_), IU_(eigen.IU_)
222 {}
223
224/* @brief Run eigen decomposition
225 * Launch SYEVR LAPACK routine to perform the eigenvalues decomposition.
226 * @return @c true if no error occur, @c false otherwise
227 */
228template<class SquareArray>
230{
231#ifdef STK_ALGEBRA_VERY_VERBOSE
232 stk_cout << _T("Enter in SymEigen::run\n");
233#endif
234 /* copy square matrix with the original data set. */
235 CSquareX data_ = eigenVectors_;
236 // shift data sets
237 data_.shift(0);
238 eigenVectors_.shift(0);
239 eigenValues_.shift(0);
240 this->SupportEigenVectors_.shift(0);
241 /* set default behavior */
242 Real absTol = 0.0; // let Lapack chose the correct tolerance
243 // get optimal size necessary for work
244 Real work; // work is just one place, get the optimal size for work
245 // iwork is just on place, get the optimal size for iWork
246 int iwork, lWork =-1, liwork =-1; // workspace variable
247
248 int info = 1;
249#ifdef STK_ALGEBRA_DEBUG
250 stk_cout << _T("Data dimensions: ") << data_.rows() << " " << data_.cols() << "\n";
251 stk_cout << _T("eigenValues_ dimensions: ") << eigenValues_.rows() << " " << eigenValues_.cols() << "\n";
252 stk_cout << _T("eigenVectors_ dimensions: ") << eigenVectors_.rows() << " " << eigenVectors_.cols() << "\n";
253 stk_cout << _T("Options: ") << jobz_ << " " << RANGE_ << " " << UPLO_ << "\n";
254#endif
255 info = syevr( jobz_, RANGE_, UPLO_
256 , range_.size(), data_.p_data(), range_.size()
257 , VL_, VU_, IL_, IU_
258 , absTol, &rank_, eigenValues_.p_data()
259 , eigenVectors_.p_data(), range_.size(), this->SupportEigenVectors_.p_data()
260 , &work, lWork, &iwork, liwork);
261 // check any error
262 if (info!=0)
263 {
264 if (info>0)
265 { this->msg_error_ = STKERROR_NO_ARG(SymEigen::run,internal error);
266 return false;
267 }
268 this->msg_error_= STKERROR_1ARG(SymEigen::run,-info,error parameter);
269 return false;
270 }
271#ifdef STK_ALGEBRA_DEBUG
272 stk_cout << _T("Size needed:") << (int)work << " " << iwork << " " << "\n";
273#endif
274 // get results and allocate space
275 lWork = (int)work;
276 liwork = iwork;
277 Real* p_work = new Real[lWork];
278 int* p_iwork = new int[liwork];
279
280 // Call SYEVR with the optimal block size
281 info = syevr( jobz_, RANGE_, UPLO_
282 , range_.size(), data_.p_data(), range_.size()
283 , VL_, VU_, IL_, IU_
284 , absTol, &rank_, eigenValues_.p_data()
285 , eigenVectors_.p_data(), range_.size(), this->SupportEigenVectors_.p_data()
287 // recover memory
288 delete[] p_work;
289 delete[] p_iwork;
290
291 // finalize
292 data_.shift(range_.begin());
293 eigenVectors_.shift(range_.begin());
294 eigenValues_.shift(range_.begin());
295 this->SupportEigenVectors_.shift(range_.begin());
296 this->finalizeStep();
297 this->hasRun_ = true;
298 // return the result of the computation
299 if (!info) return true;
300 if (info>0)
301 { this->msg_error_ = STKERROR_NO_ARG(SymEigen::run,internal error);
302 return false;
303 }
304 this->msg_error_= STKERROR_1ARG(SymEigen::run,-info,error parameter);
305 return false;
306}
307
308} // namespace lapack
309
310} // namespace STK
311
312#endif /* STK_LAPACK_SYMEIGEN_H */
In this file we define the ISymEigen class (for a symmetric matrix).
#define STKERROR_NO_ARG(Where, Error)
Definition STK_Macros.h:49
#define STKERROR_1ARG(Where, Arg, Error)
Definition STK_Macros.h:61
#define stk_cout
Standard stk output stream.
#define _T(x)
Let x unmodified.
In this file we define and implement utilities classes and methods for the interface with lapack.
Derived & shift(int beginRows, int beginCols)
shift the Array.
Type *const & p_data() const
virtual bool run()=0
run the computations.
The class ISymEigen is an interface class for the method computing the eigenvalue Decomposition of a ...
hidden::AlgebraTraits< SymEigen< SquareArray > >::SquareArray SquareArray
Range range_
range of the original data set.
CArrayVector< Type, size_ > eigenValues_
Array of the eigenvalues.
CArraySquare< Type, size_ > eigenVectors_
Square matrix or the eigenvectors.
The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
The class SymEigen compute the eigenvalue Decomposition of a symmetric ArrayXX.
char jobz_
Lapack pptions.
ISymEigen< SymEigen< SquareArray > > Base
void setIlAndIu(int il, int iu)
virtual ~SymEigen()
Destructor.
SymEigen()
Default Constructor.
virtual SymEigen * clone() const
clone pattern
void setVlAndVu(Real const &vl, Real const &vu)
bool runImpl()
Run eigenvalues decomposition Launch SYEVR LAPACK routine to perform the eigenvalues decomposition.
int syevr(char jobz, char range, char uplo, int n, Real *a, int lda, Real vl, Real vu, int il, int iu, Real abstol, int *m, Real *w, Real *z, int ldz, int *isuppz, Real *work, int lWork, int *iwork, int liwork)
wrapper of the LAPACK SYEVR routine.
double Real
STK fundamental type of Real values.
The namespace STK is the main domain space of the Statistical ToolKit project.
traits class for the algebra methods.