source: Sophya/trunk/SophyaExt/LinAlg/intflapack.cc@ 2567

Last change on this file since 2567 was 2567, checked in by cmv, 21 years ago
  • change argument for SVD_DC
  • add Least Square with SVD DC (cmv 27/07/04)
File size: 39.9 KB
RevLine 
[2322]1#include <iostream>
[2567]2#include <math.h>
[775]3#include "intflapack.h"
[1342]4#include "tvector.h"
5#include "tmatrix.h"
[814]6#include <typeinfo>
[775]7
[2567]8#define GARDMEM 5
9
[2556]10/*************** Pour memoire (Christophe) ***************
11Les dispositions memoires (FORTRAN) pour les vecteurs et matrices LAPACK:
12
131./ --- REAL X(N):
14 if an array X of dimension (N) holds a vector x,
15 then X(i) holds "x_i" for i=1,...,N
16
172./ --- REAL A(LDA,N):
18 if a two-dimensional array A of dimension (LDA,N) holds an m-by-n matrix A,
19 then A(i,j) holds "a_ij" for i=1,...,m et j=1,...,n (LDA must be at least m).
20 Note that array arguments are usually declared in the software as assumed-size
21 arrays (last dimension *), for example: REAL A(LDA,*)
22 --- Rangement en memoire:
23 | 11 12 13 14 |
24 Ex: Real A(4,4): A = | 21 22 23 24 |
25 | 31 32 33 34 |
26 | 41 42 43 44 |
27 memoire: {11 21 31 41} {12 22 32 42} {13 23 33 43} {14 24 34 44}
28 First indice (line) "i" varies then the second (column):
29 (put all the first column, then put all the second column,
30 ..., then put all the last column)
31***********************************************************/
32
[1424]33/*!
34 \defgroup LinAlg LinAlg module
35 This module contains classes and functions for complex linear
36 algebra on arrays. This module is intended mainly to have
37 classes implementing C++ interfaces between Sophya objects
38 and external linear algebra libraries, such as LAPACK.
39*/
40
41/*!
42 \class SOPHYA::LapackServer
43 \ingroup LinAlg
44 This class implements an interface to LAPACK library driver routines.
45 The LAPACK (Linear Algebra PACKage) is a collection high performance
46 routines to solve common problems in numerical linear algebra.
47 its is available from http://www.netlib.org.
48
49 The present version of our LapackServer (Feb 2001) provides only
50 interfaces for the linear system solver and singular value
51 decomposition (SVD). Only arrays with BaseArray::FortranMemoryMapping
52 can be handled by LapackServer. LapackServer can be instanciated
53 for simple and double precision real or complex array types.
54
55 The example below shows solving a linear system A*X = B
56
57 \code
58 #include "intflapack.h"
59 // ...
60 // Use FortranMemoryMapping as default
61 BaseArray::SetDefaultMemoryMapping(BaseArray::FortranMemoryMapping);
62 // Create an fill the arrays A and B
63 int n = 20;
64 Matrix A(n, n);
65 A = RandomSequence();
66 Vector X(n),B(n);
67 X = RandomSequence();
68 B = A*X;
69 // Solve the linear system A*X = B
70 LapackServer<r_8> lps;
71 lps.LinSolve(A,B);
72 // We get the result in B, which should be equal to X ...
73 // Compute the difference B-X ;
74 Vector diff = B-X;
75 \endcode
76
77*/
78
[2556]79////////////////////////////////////////////////////////////////////////////////////
[775]80extern "C" {
[2554]81// Le calculateur de workingspace
82 int_4 ilaenv_(int_4 *ispec,char *name,char *opts,int_4 *n1,int_4 *n2,int_4 *n3,int_4 *n4,
83 int_4 nc1,int_4 nc2);
84
[1342]85// Drivers pour resolution de systemes lineaires
86 void sgesv_(int_4* n, int_4* nrhs, r_4* a, int_4* lda,
87 int_4* ipiv, r_4* b, int_4* ldb, int_4* info);
88 void dgesv_(int_4* n, int_4* nrhs, r_8* a, int_4* lda,
89 int_4* ipiv, r_8* b, int_4* ldb, int_4* info);
90 void cgesv_(int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
91 int_4* ipiv, complex<r_4>* b, int_4* ldb, int_4* info);
92 void zgesv_(int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
93 int_4* ipiv, complex<r_8>* b, int_4* ldb, int_4* info);
94
[2554]95// Drivers pour resolution de systemes lineaires symetriques
96 void ssysv_(char* uplo, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
97 int_4* ipiv, r_4* b, int_4* ldb,
98 r_4* work, int_4* lwork, int_4* info);
99 void dsysv_(char* uplo, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
100 int_4* ipiv, r_8* b, int_4* ldb,
101 r_8* work, int_4* lwork, int_4* info);
102 void csysv_(char* uplo, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
103 int_4* ipiv, complex<r_4>* b, int_4* ldb,
104 complex<r_4>* work, int_4* lwork, int_4* info);
105 void zsysv_(char* uplo, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
106 int_4* ipiv, complex<r_8>* b, int_4* ldb,
107 complex<r_8>* work, int_4* lwork, int_4* info);
108
109// Driver pour resolution de systemes au sens de Xi2
[1494]110 void sgels_(char * trans, int_4* m, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
111 r_4* b, int_4* ldb, r_4* work, int_4* lwork, int_4* info);
112 void dgels_(char * trans, int_4* m, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
113 r_8* b, int_4* ldb, r_8* work, int_4* lwork, int_4* info);
114 void cgels_(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
115 complex<r_4>* b, int_4* ldb, complex<r_4>* work, int_4* lwork, int_4* info);
116 void zgels_(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
117 complex<r_8>* b, int_4* ldb, complex<r_8>* work, int_4* lwork, int_4* info);
118
[2567]119// Driver pour resolution de systemes au sens de Xi2 par SVD Divide & Conquer
120 void sgelsd_(int_4* m,int_4* n,int_4* nrhs,r_4* a,int_4* lda,
121 r_4* b,int_4* ldb,r_4* s,r_4* rcond,int_4* rank,
122 r_4* work,int_4* lwork,int_4* iwork,int_4* info);
123 void dgelsd_(int_4* m,int_4* n,int_4* nrhs,r_8* a,int_4* lda,
124 r_8* b,int_4* ldb,r_8* s,r_8* rcond,int_4* rank,
125 r_8* work,int_4* lwork,int_4* iwork,int_4* info);
126 void cgelsd_(int_4* m,int_4* n,int_4* nrhs,complex<r_4>* a,int_4* lda,
127 complex<r_4>* b,int_4* ldb,r_4* s,r_4* rcond,int_4* rank,
128 complex<r_4>* work,int_4* lwork,r_4* rwork,int_4* iwork,int_4* info);
129 void zgelsd_(int_4* m,int_4* n,int_4* nrhs,complex<r_8>* a,int_4* lda,
130 complex<r_8>* b,int_4* ldb,r_8* s,r_8* rcond,int_4* rank,
131 complex<r_8>* work,int_4* lwork,r_8* rwork,int_4* iwork,int_4* info);
132
[1342]133// Driver pour decomposition SVD
134 void sgesvd_(char* jobu, char* jobvt, int_4* m, int_4* n, r_4* a, int_4* lda,
135 r_4* s, r_4* u, int_4* ldu, r_4* vt, int_4* ldvt,
136 r_4* work, int_4* lwork, int_4* info);
137 void dgesvd_(char* jobu, char* jobvt, int_4* m, int_4* n, r_8* a, int_4* lda,
138 r_8* s, r_8* u, int_4* ldu, r_8* vt, int_4* ldvt,
139 r_8* work, int_4* lwork, int_4* info);
140 void cgesvd_(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
[2559]141 r_4* s, complex<r_4>* u, int_4* ldu, complex<r_4>* vt, int_4* ldvt,
142 complex<r_4>* work, int_4* lwork, r_4* rwork, int_4* info);
[1342]143 void zgesvd_(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
[2559]144 r_8* s, complex<r_8>* u, int_4* ldu, complex<r_8>* vt, int_4* ldvt,
145 complex<r_8>* work, int_4* lwork, r_8* rwork, int_4* info);
[2556]146
[2561]147// Driver pour decomposition SVD Divide and Conquer
148 void sgesdd_(char* jobz, int_4* m, int_4* n, r_4* a, int_4* lda,
149 r_4* s, r_4* u, int_4* ldu, r_4* vt, int_4* ldvt,
150 r_4* work, int_4* lwork, int_4* iwork, int_4* info);
151 void dgesdd_(char* jobz, int_4* m, int_4* n, r_8* a, int_4* lda,
152 r_8* s, r_8* u, int_4* ldu, r_8* vt, int_4* ldvt,
153 r_8* work, int_4* lwork, int_4* iwork, int_4* info);
154 void cgesdd_(char* jobz, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
155 r_4* s, complex<r_4>* u, int_4* ldu, complex<r_4>* vt, int_4* ldvt,
156 complex<r_4>* work, int_4* lwork, r_4* rwork, int_4* iwork, int_4* info);
157 void zgesdd_(char* jobz, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
158 r_8* s, complex<r_8>* u, int_4* ldu, complex<r_8>* vt, int_4* ldvt,
159 complex<r_8>* work, int_4* lwork, r_8* rwork, int_4* iwork, int_4* info);
160
[2556]161// Driver pour eigen decomposition for symetric/hermitian matrices
162 void ssyev_(char* jobz, char* uplo, int_4* n, r_4* a, int_4* lda, r_4* w,
163 r_4* work, int_4 *lwork, int_4* info);
164 void dsyev_(char* jobz, char* uplo, int_4* n, r_8* a, int_4* lda, r_8* w,
165 r_8* work, int_4 *lwork, int_4* info);
166 void cheev_(char* jobz, char* uplo, int_4* n, complex<r_4>* a, int_4* lda, r_4* w,
167 complex<r_4>* work, int_4 *lwork, r_4* rwork, int_4* info);
168 void zheev_(char* jobz, char* uplo, int_4* n, complex<r_8>* a, int_4* lda, r_8* w,
169 complex<r_8>* work, int_4 *lwork, r_8* rwork, int_4* info);
170
171// Driver pour eigen decomposition for general squared matrices
172 void sgeev_(char* jobl, char* jobvr, int_4* n, r_4* a, int_4* lda, r_4* wr, r_4* wi,
173 r_4* vl, int_4* ldvl, r_4* vr, int_4* ldvr,
174 r_4* work, int_4 *lwork, int_4* info);
175 void dgeev_(char* jobl, char* jobvr, int_4* n, r_8* a, int_4* lda, r_8* wr, r_8* wi,
176 r_8* vl, int_4* ldvl, r_8* vr, int_4* ldvr,
177 r_8* work, int_4 *lwork, int_4* info);
178 void cgeev_(char* jobl, char* jobvr, int_4* n, complex<r_4>* a, int_4* lda, complex<r_4>* w,
179 complex<r_4>* vl, int_4* ldvl, complex<r_4>* vr, int_4* ldvr,
180 complex<r_4>* work, int_4 *lwork, r_4* rwork, int_4* info);
181 void zgeev_(char* jobl, char* jobvr, int_4* n, complex<r_8>* a, int_4* lda, complex<r_8>* w,
182 complex<r_8>* vl, int_4* ldvl, complex<r_8>* vr, int_4* ldvr,
183 complex<r_8>* work, int_4 *lwork, r_8* rwork, int_4* info);
184
[775]185}
186
[1342]187// -------------- Classe LapackServer<T> --------------
188
[2556]189////////////////////////////////////////////////////////////////////////////////////
[814]190template <class T>
[1344]191LapackServer<T>::LapackServer()
[1342]192{
193 SetWorkSpaceSizeFactor();
194}
195
196template <class T>
[1344]197LapackServer<T>::~LapackServer()
[1342]198{
199}
200
[2556]201// --- ATTENTION BUG POSSIBLE dans l'avenir (CMV) --- REZA A LIRE S.T.P.
[2554]202// -> Cette connerie de Fortran/C interface
203// Dans les routines fortran de lapack:
204// Appel depuis le C avec:
205// int_4 lwork = -1;
206// SUBROUTINE SSYSV( UPLO,N,NRHS,A,LDA,IPIV,B,LDB,WORK,LWORK,INFO)
207// INTEGER INFO, LDA, LDB, LWORK, N, NRHS
208// LOGICAL LQUERY
209// LQUERY = ( LWORK.EQ.-1 )
210// ELSE IF( LWORK.LT.1 .AND. .NOT.LQUERY ) THEN
211// ==> le test est bien interprete sous Linux mais pas sous OSF
212// ==> Sous OSF "LWORK.EQ.-1" est FALSE quand on passe lwork=-1 par argument
213// ==> POUR REZA: confusion entier 4 / 8 bits ??? (bizarre on l'aurait vu avant?)
[2556]214////////////////////////////////////////////////////////////////////////////////////
[2554]215template <class T>
216int_4 LapackServer<T>::ilaenv_en_C(int_4 ispec,char *name,char *opts,int_4 n1,int_4 n2,int_4 n3,int_4 n4)
217{
218 int_4 nc1 = strlen(name);
219 int_4 nc2 = strlen(opts);
220 int_4 rc=0;
221 rc = ilaenv_(&ispec,name,opts,&n1,&n2,&n3,&n4,nc1,nc2);
222 //cout<<"ilaenv_en_C("<<ispec<<","<<name<<"("<<nc1<<"),"<<opts<<"("<<nc2<<"),"
223 // <<n1<<","<<n2<<","<<n3<<","<<n4<<") = "<<rc<<endl;
224 return rc;
225}
226
[2556]227////////////////////////////////////////////////////////////////////////////////////
[2563]228//! Interface to Lapack linear system solver driver s/d/c/zgesv().
229/*! Solve the linear system a * x = b using LU factorization.
230 Input arrays should have FortranMemory mapping (column packed).
[1424]231 \param a : input matrix, overwritten on output
232 \param b : input-output, input vector b, contains x on exit
233 \return : return code from lapack driver _gesv()
234 */
[1342]235template <class T>
[1042]236int LapackServer<T>::LinSolve(TArray<T>& a, TArray<T> & b)
[814]237{
238 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
239 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b NbDimensions() != 2"));
240
[1342]241 int_4 rowa = a.RowsKA();
242 int_4 cola = a.ColsKA();
243 int_4 rowb = b.RowsKA();
244 int_4 colb = b.ColsKA();
[814]245 if ( a.Size(rowa) != a.Size(cola))
246 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Not a square Array"));
[1042]247 if ( a.Size(rowa) != b.Size(rowb))
[814]248 throw(SzMismatchError("LapackServer::LinSolve(a,b) RowSize(a <> b) "));
249
250 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
[1342]251 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b Not Column Packed"));
[814]252
253 int_4 n = a.Size(rowa);
254 int_4 nrhs = b.Size(colb);
255 int_4 lda = a.Step(cola);
256 int_4 ldb = b.Step(colb);
257 int_4 info;
258 int_4* ipiv = new int_4[n];
259
260 if (typeid(T) == typeid(r_4) )
261 sgesv_(&n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb, &info);
262 else if (typeid(T) == typeid(r_8) )
263 dgesv_(&n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb, &info);
264 else if (typeid(T) == typeid(complex<r_4>) )
265 cgesv_(&n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
266 (complex<r_4> *)b.Data(), &ldb, &info);
267 else if (typeid(T) == typeid(complex<r_8>) )
268 zgesv_(&n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
269 (complex<r_8> *)b.Data(), &ldb, &info);
270 else {
271 delete[] ipiv;
272 string tn = typeid(T).name();
273 cerr << " LapackServer::LinSolve(a,b) - Unsupported DataType T = " << tn << endl;
274 throw TypeMismatchExc("LapackServer::LinSolve(a,b) - Unsupported DataType (T)");
275 }
276 delete[] ipiv;
[1042]277 return(info);
[814]278}
279
[2556]280////////////////////////////////////////////////////////////////////////////////////
[2563]281//! Interface to Lapack linear system solver driver s/d/c/zsysv().
282/*! Solve the linear system a * x = b with a symetric matrix using LU factorization.
283 Input arrays should have FortranMemory mapping (column packed).
[2554]284 \param a : input matrix symetric , overwritten on output
285 \param b : input-output, input vector b, contains x on exit
[2563]286 \return : return code from lapack driver _sysv()
[2554]287 */
288template <class T>
289int LapackServer<T>::LinSolveSym(TArray<T>& a, TArray<T> & b)
290// --- REMARQUES DE CMV ---
291// 1./ contrairement a ce qui est dit dans la doc, il s'agit
292// de matrices SYMETRIQUES complexes et non HERMITIENNES !!!
293// 2./ pourquoi les routines de LinSolve pour des matrices symetriques
[2556]294// sont plus de deux fois plus lentes que les LinSolve generales sur OSF
295// et sensiblement plus lentes sous Linux ???
[2554]296{
297 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
298 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Or b NbDimensions() != 2"));
299 int_4 rowa = a.RowsKA();
300 int_4 cola = a.ColsKA();
301 int_4 rowb = b.RowsKA();
302 int_4 colb = b.ColsKA();
303 if ( a.Size(rowa) != a.Size(cola))
304 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Not a square Array"));
305 if ( a.Size(rowa) != b.Size(rowb))
306 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) RowSize(a <> b) "));
307
308 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
309 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Or b Not Column Packed"));
310
311 int_4 n = a.Size(rowa);
312 int_4 nrhs = b.Size(colb);
313 int_4 lda = a.Step(cola);
314 int_4 ldb = b.Step(colb);
315 int_4 info = 0;
316 int_4* ipiv = new int_4[n];
317 int_4 lwork = -1;
318 T * work = NULL;
319
320 char uplo = 'U'; // char uplo = 'L';
321 char struplo[5]; struplo[0] = uplo; struplo[1] = '\0';
322
323 if (typeid(T) == typeid(r_4) ) {
[2567]324 lwork = ilaenv_en_C(1,"SSYTRF",struplo,n,-1,-1,-1) * n;
325 work = new T[lwork +GARDMEM];
[2554]326 ssysv_(&uplo, &n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb,
327 (r_4 *)work, &lwork, &info);
328 } else if (typeid(T) == typeid(r_8) ) {
[2567]329 lwork = ilaenv_en_C(1,"DSYTRF",struplo,n,-1,-1,-1) * n;
330 work = new T[lwork +GARDMEM];
[2554]331 dsysv_(&uplo, &n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb,
332 (r_8 *)work, &lwork, &info);
333 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]334 lwork = ilaenv_en_C(1,"CSYTRF",struplo,n,-1,-1,-1) * n;
335 work = new T[lwork +GARDMEM];
[2554]336 csysv_(&uplo, &n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
337 (complex<r_4> *)b.Data(), &ldb,
338 (complex<r_4> *)work, &lwork, &info);
339 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]340 lwork = ilaenv_en_C(1,"ZSYTRF",struplo,n,-1,-1,-1) * n;
341 work = new T[lwork +GARDMEM];
[2554]342 zsysv_(&uplo, &n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
343 (complex<r_8> *)b.Data(), &ldb,
344 (complex<r_8> *)work, &lwork, &info);
345 } else {
[2556]346 if(work) delete[] work;
[2554]347 delete[] ipiv;
348 string tn = typeid(T).name();
349 cerr << " LapackServer::LinSolveSym(a,b) - Unsupported DataType T = " << tn << endl;
350 throw TypeMismatchExc("LapackServer::LinSolveSym(a,b) - Unsupported DataType (T)");
351 }
[2556]352 if(work) delete[] work;
[2554]353 delete[] ipiv;
354 return(info);
355}
356
[2556]357////////////////////////////////////////////////////////////////////////////////////
[1566]358//! Interface to Lapack least squares solver driver s/d/c/zgels().
359/*! Solves the linear least squares problem defined by an m-by-n matrix
[2563]360 \b a and an m element vector \b b , using QR or LQ factorization .
[1566]361 A solution \b x to the overdetermined system of linear equations
362 b = a * x is computed, minimizing the norm of b-a*x.
363 Underdetermined systems (m<n) are not yet handled.
364 Inout arrays should have FortranMemory mapping (column packed).
365 \param a : input matrix, overwritten on output
366 \param b : input-output, input vector b, contains x on exit.
367 \return : return code from lapack driver _gels()
368 \warning : b is not resized.
369 */
370/*
371 $CHECK$ - A faire - cas m<n
372 If the linear system is underdetermined, the minimum norm
373 solution is computed.
374*/
375
[1494]376template <class T>
377int LapackServer<T>::LeastSquareSolve(TArray<T>& a, TArray<T> & b)
378{
379 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
[2561]380 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b NbDimensions() != 2"));
[1494]381
382 int_4 rowa = a.RowsKA();
383 int_4 cola = a.ColsKA();
384 int_4 rowb = b.RowsKA();
385 int_4 colb = b.ColsKA();
386
387
388 if ( a.Size(rowa) != b.Size(rowb))
389 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) RowSize(a <> b) "));
390
391 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
[1566]392 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b Not Column Packed"));
[1494]393
[1566]394 if ( a.Size(rowa) < a.Size(cola)) { // $CHECK$ - m<n a changer
395 cout << " LapackServer<T>::LeastSquareSolve() - m<n - Not yet implemented for "
396 << " underdetermined systems ! " << endl;
397 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) NRows<NCols - "));
398 }
[1494]399 int_4 m = a.Size(rowa);
400 int_4 n = a.Size(cola);
401 int_4 nrhs = b.Size(colb);
402
403 int_4 lda = a.Step(cola);
404 int_4 ldb = b.Step(colb);
405 int_4 info;
406
407 int_4 minmn = (m < n) ? m : n;
408 int_4 maxmn = (m > n) ? m : n;
409 int_4 maxmnrhs = (nrhs > maxmn) ? nrhs : maxmn;
410 if (maxmnrhs < 1) maxmnrhs = 1;
411
412 int_4 lwork = minmn+maxmnrhs*5;
413 T * work = new T[lwork];
414
415 char trans = 'N';
416
417 if (typeid(T) == typeid(r_4) )
418 sgels_(&trans, &m, &n, &nrhs, (r_4 *)a.Data(), &lda,
419 (r_4 *)b.Data(), &ldb, (r_4 *)work, &lwork, &info);
420 else if (typeid(T) == typeid(r_8) )
421 dgels_(&trans, &m, &n, &nrhs, (r_8 *)a.Data(), &lda,
422 (r_8 *)b.Data(), &ldb, (r_8 *)work, &lwork, &info);
423 else if (typeid(T) == typeid(complex<r_4>) )
424 cgels_(&trans, &m, &n, &nrhs, (complex<r_4> *)a.Data(), &lda,
425 (complex<r_4> *)b.Data(), &ldb, (complex<r_4> *)work, &lwork, &info);
426 else if (typeid(T) == typeid(complex<r_8>) )
427 zgels_(&trans, &m, &n, &nrhs, (complex<r_8> *)a.Data(), &lda,
428 (complex<r_8> *)b.Data(), &ldb, (complex<r_8> *)work, &lwork, &info);
429 else {
430 delete[] work;
431 string tn = typeid(T).name();
432 cerr << " LapackServer::LeastSquareSolve(a,b) - Unsupported DataType T = " << tn << endl;
433 throw TypeMismatchExc("LapackServer::LeastSquareSolve(a,b) - Unsupported DataType (T)");
434 }
435 delete[] work;
436 return(info);
437}
438
[2567]439////////////////////////////////////////////////////////////////////////////////////
440//! Interface to Lapack least squares solver driver s/d/c/zgelsd().
441/*! Solves the linear least squares problem defined by an m-by-n matrix
442 \b a and an m element vector \b b , using SVD factorization Divide and Conquer.
443 Inout arrays should have FortranMemory mapping (column packed).
444 \param rcond : definition of zero value (S(i) <= RCOND*S(0) are treated as zero).
445 If RCOND < 0, machine precision is used instead.
446 \param a : input matrix, overwritten on output
447 \param b : input vector b overwritten by solution on output (beware of size changing)
448 \param x : output matrix of solutions.
449 \return : return code from lapack driver _gelsd()
450 \warning : b is not resized.
451 */
452template <class T>
453int LapackServer<T>::LeastSquareSolveSVD_DC(TMatrix<T>& a,TMatrix<T>& b,TVector<r_8>& s,int_4& rank,r_8 rcond)
454{
455 if ( ( a.NbDimensions() != 2 ) )
456 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) a != 2"));
457
458 if (!a.IsPacked() || !b.IsPacked())
459 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) a Or b Not Packed"));
[1494]460
[2567]461 int_4 m = a.NRows();
462 int_4 n = a.NCols();
463
464 if(b.NRows() != n)
465 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) bad matching dim between a and b"));
466
467 int_4 nrhs = b.NCols();
468 int_4 minmn = (m < n) ? m : n;
469 int_4 maxmn = (m > n) ? m : n;
470
471 if(b.NRows() != n)
472 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) bad matching dim between a and b"));
473
474 int_4 lda = m;
475 int_4 ldb = maxmn;
476 int_4 info;
477
478 { // Use {} for automatic des-alloc bsave
479 TMatrix<T> bsave(n,nrhs); bsave.SetMemoryMapping(BaseArray::FortranMemoryMapping);
480 bsave = b;
481 b.ReSize(maxmn,nrhs); b = (T) 0;
482 for(int i=0;i<n;i++) for(int j=0;j<nrhs;j++) b(i,j) = bsave(i,j);
483 }
484 s.ReSize(minmn);
485
486 int_4 smlsiz = 25;
487 if(typeid(T) == typeid(r_4) ) smlsiz = ilaenv_en_C(9,"SGELSD"," ",0,0,0,0);
488 else if(typeid(T) == typeid(r_8) ) smlsiz = ilaenv_en_C(9,"DGELSD"," ",0,0,0,0);
489 else if(typeid(T) == typeid(complex<r_4>) ) smlsiz = ilaenv_en_C(9,"CGELSD"," ",0,0,0,0);
490 else if(typeid(T) == typeid(complex<r_8>) ) smlsiz = ilaenv_en_C(9,"ZGELSD"," ",0,0,0,0);
491 if(smlsiz<0) smlsiz = 0;
492
493 r_8 dum = log((r_8)minmn/(r_8)(smlsiz+1.)) / log(2.);
494 int_4 nlvl = int_4(dum) + 1; if(nlvl<0) nlvl = 0;
495
496 if(typeid(T) == typeid(r_4) ) {
497 int_4 lwork = 12*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + minmn*nrhs + (smlsiz+1)*(smlsiz+1);
498 r_4* work = new r_4[lwork +GARDMEM];
499 int_4* iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
500 r_4* sloc = new r_4[minmn];
501 r_4 srcond = rcond;
502 sgelsd_(&m,&n,&nrhs,(r_4*)a.Data(),&lda,
503 (r_4*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
504 (r_4*)work,&lwork,(int_4*)iwork,&info);
505 for(int_4 i=0;i<minmn;i++) s(i) = sloc[i];
506 delete [] sloc; delete [] work; delete [] iwork;
507 } else if(typeid(T) == typeid(r_8) ) {
508 int_4 lwork = 12*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + minmn*nrhs + (smlsiz+1)*(smlsiz+1);
509 r_8* work = new r_8[lwork +GARDMEM];
510 int_4* iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
511 dgelsd_(&m,&n,&nrhs,(r_8*)a.Data(),&lda,
512 (r_8*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
513 (r_8*)work,&lwork,(int_4*)iwork,&info);
514 delete [] work; delete [] iwork;
515 } else if(typeid(T) == typeid(complex<r_4>) ) {
516 int_4 lwork = 2*minmn + minmn*nrhs;
517 complex<r_4>* work = new complex<r_4>[lwork +GARDMEM];
518 int_4 lrwork = 10*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);
519 r_4* rwork = new r_4[lrwork +GARDMEM];
520 int_4* iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
521 r_4* sloc = new r_4[minmn];
522 r_4 srcond = rcond;
523 cgelsd_(&m,&n,&nrhs,(complex<r_4>*)a.Data(),&lda,
524 (complex<r_4>*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
525 (complex<r_4>*)work,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
526 for(int_4 i=0;i<minmn;i++) s(i) = sloc[i];
527 delete [] sloc; delete [] work; delete [] rwork; delete [] iwork;
528 } else if(typeid(T) == typeid(complex<r_8>) ) {
529 int_4 lwork = 2*minmn + minmn*nrhs;
530 complex<r_8>* work = new complex<r_8>[lwork +GARDMEM];
531 int_4 lrwork = 10*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);
532 r_8* rwork = new r_8[lrwork +GARDMEM];
533 int_4* iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
534 r_8 srcond = rcond;
535 zgelsd_(&m,&n,&nrhs,(complex<r_8>*)a.Data(),&lda,
536 (complex<r_8>*)b.Data(),&ldb,(r_8*)s.Data(),&srcond,&rank,
537 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
538 delete [] work; delete [] rwork; delete [] iwork;
539 } else {
540 string tn = typeid(T).name();
541 cerr << " LapackServer::LeastSquareSolveSVD_DC(a,b) - Unsupported DataType T = " << tn << endl;
542 throw TypeMismatchExc("LapackServer::LeastSquareSolveSVD_DC(a,b) - Unsupported DataType (T)");
543 }
544
545 return(info);
546}
547
548
[2556]549////////////////////////////////////////////////////////////////////////////////////
[1424]550//! Interface to Lapack SVD driver s/d/c/zgesv().
551/*! Computes the vector of singular values of \b a. Input arrays
552 should have FortranMemoryMapping (column packed).
553 \param a : input m-by-n matrix
554 \param s : Vector of min(m,n) singular values (descending order)
555 \return : return code from lapack driver _gesvd()
556 */
557
[1342]558template <class T>
559int LapackServer<T>::SVD(TArray<T>& a, TArray<T> & s)
560{
561 return (SVDDriver(a, s, NULL, NULL) );
562}
563
[1424]564//! Interface to Lapack SVD driver s/d/c/zgesv().
565/*! Computes the vector of singular values of \b a, as well as
566 right and left singular vectors of \b a.
567 \f[
568 A = U \Sigma V^T , ( A = U \Sigma V^H \ complex)
569 \f]
570 \f[
571 A v_i = \sigma_i u_i \ and A^T u_i = \sigma_i v_i \ (A^H \ complex)
572 \f]
573 U and V are orthogonal (unitary) matrices.
574 \param a : input m-by-n matrix (in FotranMemoryMapping)
575 \param s : Vector of min(m,n) singular values (descending order)
576 \param u : Matrix of left singular vectors
577 \param vt : Transpose of right singular vectors.
578 \return : return code from lapack driver _gesvd()
579 */
[1342]580template <class T>
581int LapackServer<T>::SVD(TArray<T>& a, TArray<T> & s, TArray<T> & u, TArray<T> & vt)
582{
583 return (SVDDriver(a, s, &u, &vt) );
584}
585
[1424]586
587//! Interface to Lapack SVD driver s/d/c/zgesv().
[1342]588template <class T>
589int LapackServer<T>::SVDDriver(TArray<T>& a, TArray<T> & s, TArray<T>* up, TArray<T>* vtp)
590{
591 if ( ( a.NbDimensions() != 2 ) )
[2561]592 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a.NbDimensions() != 2"));
[1342]593
594 int_4 rowa = a.RowsKA();
595 int_4 cola = a.ColsKA();
596
597 if ( !a.IsPacked(rowa) )
[2561]598 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a Not Column Packed "));
[1342]599
600 int_4 m = a.Size(rowa);
601 int_4 n = a.Size(cola);
602 int_4 maxmn = (m > n) ? m : n;
603 int_4 minmn = (m < n) ? m : n;
604
605 char jobu, jobvt;
606 jobu = 'N';
607 jobvt = 'N';
608
609 sa_size_t sz[2];
610 if ( up != NULL) {
611 if ( dynamic_cast< TVector<T> * > (vtp) )
[2561]612 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for u !") );
[1342]613 up->SetMemoryMapping(BaseArray::FortranMemoryMapping);
614 sz[0] = sz[1] = m;
615 up->ReSize(2, sz );
616 jobu = 'A';
617 }
618 else {
619 up = new TMatrix<T>(1,1);
620 jobu = 'N';
621 }
622 if ( vtp != NULL) {
623 if ( dynamic_cast< TVector<T> * > (vtp) )
[2561]624 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for vt !") );
[1342]625 vtp->SetMemoryMapping(BaseArray::FortranMemoryMapping);
626 sz[0] = sz[1] = n;
627 vtp->ReSize(2, sz );
628 jobvt = 'A';
629 }
630 else {
631 vtp = new TMatrix<T>(1,1);
632 jobvt = 'N';
633 }
634
635 TVector<T> *vs = dynamic_cast< TVector<T> * > (&s);
636 if (vs) vs->ReSize(minmn);
637 else {
638 TMatrix<T> *ms = dynamic_cast< TMatrix<T> * > (&s);
639 if (ms) ms->ReSize(minmn,1);
640 else {
641 sz[0] = minmn; sz[1] = 1;
642 s.ReSize(1, sz);
643 }
644 }
645
646 int_4 lda = a.Step(a.ColsKA());
647 int_4 ldu = up->Step(up->ColsKA());
648 int_4 ldvt = vtp->Step(vtp->ColsKA());
[2567]649 int_4 info;
[1342]650
651 int_4 lwork = maxmn*5*wspace_size_factor;
652 T * work = new T[lwork];
653
[2559]654 if (typeid(T) == typeid(r_4) ) {
[1342]655 sgesvd_(&jobu, &jobvt, &m, &n, (r_4 *)a.Data(), &lda,
656 (r_4 *)s.Data(), (r_4 *) up->Data(), &ldu, (r_4 *)vtp->Data(), &ldvt,
657 (r_4 *)work, &lwork, &info);
[2559]658 } else if (typeid(T) == typeid(r_8) ) {
[1342]659 dgesvd_(&jobu, &jobvt, &m, &n, (r_8 *)a.Data(), &lda,
660 (r_8 *)s.Data(), (r_8 *) up->Data(), &ldu, (r_8 *)vtp->Data(), &ldvt,
661 (r_8 *)work, &lwork, &info);
[2559]662 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]663 r_4 * rwork = new r_4[5*minmn +GARDMEM];
[2559]664 r_4 * sloc = new r_4[minmn];
[1342]665 cgesvd_(&jobu, &jobvt, &m, &n, (complex<r_4> *)a.Data(), &lda,
[2559]666 (r_4 *)sloc, (complex<r_4> *) up->Data(), &ldu,
[1342]667 (complex<r_4> *)vtp->Data(), &ldvt,
[2559]668 (complex<r_4> *)work, &lwork, (r_4 *)rwork, &info);
669 for(int_4 i=0;i<minmn;i++) s[i] = sloc[i];
670 delete [] rwork; delete [] sloc;
671 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]672 r_8 * rwork = new r_8[5*minmn +GARDMEM];
[2559]673 r_8 * sloc = new r_8[minmn];
[1342]674 zgesvd_(&jobu, &jobvt, &m, &n, (complex<r_8> *)a.Data(), &lda,
[2559]675 (r_8 *)sloc, (complex<r_8> *) up->Data(), &ldu,
[1342]676 (complex<r_8> *)vtp->Data(), &ldvt,
[2559]677 (complex<r_8> *)work, &lwork, (r_8 *)rwork, &info);
678 for(int_4 i=0;i<minmn;i++) s[i] = sloc[i];
679 delete [] rwork; delete [] sloc;
680 } else {
[1342]681 if (jobu == 'N') delete up;
682 if (jobvt == 'N') delete vtp;
683 string tn = typeid(T).name();
684 cerr << " LapackServer::SVDDriver(...) - Unsupported DataType T = " << tn << endl;
[2561]685 throw TypeMismatchExc("LapackServer::SVDDriver(a,b) - Unsupported DataType (T)");
[1342]686 }
687
688 if (jobu == 'N') delete up;
689 if (jobvt == 'N') delete vtp;
690 return(info);
691}
692
[2556]693
[2561]694//! Interface to Lapack SVD driver s/d/c/zgesdd().
695/*! Same as SVD but with Divide and Conquer method */
696template <class T>
[2563]697int LapackServer<T>::SVD_DC(TMatrix<T>& a, TVector<r_8>& s, TMatrix<T>& u, TMatrix<T>& vt)
[2561]698{
699
700 if ( !a.IsPacked() )
701 throw(SzMismatchError("LapackServer::SVD_DC(a, ...) a Not Packed "));
702
703 int_4 m = a.NRows();
704 int_4 n = a.NCols();
705 int_4 maxmn = (m > n) ? m : n;
706 int_4 minmn = (m < n) ? m : n;
707 int_4 supermax = 4*minmn*minmn+4*minmn; if(maxmn>supermax) supermax=maxmn;
708
709 char jobz = 'A';
710
711 s.ReSize(minmn);
712 u.ReSize(m,m);
713 vt.ReSize(n,n);
714
715 int_4 lda = n;
716 int_4 ldu = u.NCols();
717 int_4 ldvt = vt.NCols();
718 int_4 info;
719
720 if(typeid(T) == typeid(r_4) ) {
[2563]721 r_4* sloc = new r_4[minmn];
[2561]722 int_4 lwork = 3*minmn*minmn + supermax;
[2567]723 r_4* work = new r_4[lwork +GARDMEM];
724 int_4* iwork = new int_4[8*minmn +GARDMEM];
[2561]725 sgesdd_(&jobz,&m,&n,(r_4*)a.Data(),&lda,
[2563]726 (r_4*)sloc,(r_4*)u.Data(),&ldu,(r_4*)vt.Data(),&ldvt,
[2561]727 (r_4*)work,&lwork,(int_4*)iwork,&info);
[2563]728 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
729 delete [] sloc; delete [] work; delete [] iwork;
[2561]730 } else if(typeid(T) == typeid(r_8) ) {
731 int_4 lwork = 3*minmn*minmn + supermax;
[2567]732 r_8* work = new r_8[lwork +GARDMEM];
733 int_4* iwork = new int_4[8*minmn +GARDMEM];
[2561]734 dgesdd_(&jobz,&m,&n,(r_8*)a.Data(),&lda,
735 (r_8*)s.Data(),(r_8*)u.Data(),&ldu,(r_8*)vt.Data(),&ldvt,
736 (r_8*)work,&lwork,(int_4*)iwork,&info);
737 delete [] work; delete [] iwork;
738 } else if(typeid(T) == typeid(complex<r_4>) ) {
739 r_4* sloc = new r_4[minmn];
740 int_4 lwork = minmn*minmn+2*minmn+maxmn;
[2567]741 complex<r_4>* work = new complex<r_4>[lwork +GARDMEM];
742 r_4* rwork = new r_4[5*minmn*minmn+5*minmn +GARDMEM];
743 int_4* iwork = new int_4[8*minmn +GARDMEM];
[2561]744 cgesdd_(&jobz,&m,&n,(complex<r_4>*)a.Data(),&lda,
745 (r_4*)sloc,(complex<r_4>*)u.Data(),&ldu,(complex<r_4>*)vt.Data(),&ldvt,
746 (complex<r_4>*)work,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
[2563]747 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
[2561]748 delete [] sloc; delete [] work; delete [] rwork; delete [] iwork;
749 } else if(typeid(T) == typeid(complex<r_8>) ) {
750 int_4 lwork = minmn*minmn+2*minmn+maxmn;
[2567]751 complex<r_8>* work = new complex<r_8>[lwork +GARDMEM];
752 r_8* rwork = new r_8[5*minmn*minmn+5*minmn +GARDMEM];
753 int_4* iwork = new int_4[8*minmn +GARDMEM];
[2561]754 zgesdd_(&jobz,&m,&n,(complex<r_8>*)a.Data(),&lda,
[2563]755 (r_8*)s.Data(),(complex<r_8>*)u.Data(),&ldu,(complex<r_8>*)vt.Data(),&ldvt,
[2561]756 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
[2563]757 delete [] work; delete [] rwork; delete [] iwork;
[2561]758 } else {
759 string tn = typeid(T).name();
760 cerr << " LapackServer::SVD_DC(...) - Unsupported DataType T = " << tn << endl;
761 throw TypeMismatchExc("LapackServer::SVD_DC - Unsupported DataType (T)");
762 }
763
764 return(info);
765}
766
767
[2556]768////////////////////////////////////////////////////////////////////////////////////
769/*! Computes the eigen values and eigen vectors of a symetric (or hermitian) matrix \b a.
770 Input arrays should have FortranMemoryMapping (column packed).
771 \param a : input symetric (or hermitian) n-by-n matrix
772 \param b : Vector of eigenvalues (descending order)
773 \param eigenvector : if true compute eigenvectors, if not only eigenvalues
774 \param a : on return array of eigenvectors (same order than eval, one vector = one column)
[2561]775 \return : return code from lapack driver
[2556]776 */
777
778template <class T>
779int LapackServer<T>::LapackEigenSym(TArray<T>& a, TVector<r_8>& b, bool eigenvector)
780{
781 if ( a.NbDimensions() != 2 )
782 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a NbDimensions() != 2"));
783 int_4 rowa = a.RowsKA();
784 int_4 cola = a.ColsKA();
785 if ( a.Size(rowa) != a.Size(cola))
786 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a Not a square Array"));
787 if (!a.IsPacked(rowa))
788 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a Not Column Packed"));
789
[2561]790 char uplo='U';
[2556]791 char jobz='N'; if(eigenvector) jobz='V';
792
793 int_4 n = a.Size(rowa);
794 int_4 lda = a.Step(cola);
795 int_4 info = 0;
796
797 b.ReSize(n); b = 0.;
798
799 if (typeid(T) == typeid(r_4) ) {
[2567]800 int_4 lwork = 3*n-1; r_4* work = new r_4[lwork +GARDMEM];
[2556]801 r_4* w = new r_4[n];
[2561]802 ssyev_(&jobz,&uplo,&n,(r_4 *)a.Data(),&lda,(r_4 *)w,(r_4 *)work,&lwork,&info);
[2556]803 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
804 delete [] work; delete [] w;
805 } else if (typeid(T) == typeid(r_8) ) {
[2567]806 int_4 lwork = 3*n-1; r_8* work = new r_8[lwork +GARDMEM];
[2556]807 r_8* w = new r_8[n];
[2561]808 dsyev_(&jobz,&uplo,&n,(r_8 *)a.Data(),&lda,(r_8 *)w,(r_8 *)work,&lwork,&info);
[2556]809 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
810 delete [] work; delete [] w;
811 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]812 int_4 lwork = 2*n-1; complex<r_4>* work = new complex<r_4>[lwork +GARDMEM];
813 r_4* rwork = new r_4[3*n-2 +GARDMEM]; r_4* w = new r_4[n];
[2561]814 cheev_(&jobz,&uplo,&n,(complex<r_4> *)a.Data(),&lda,(r_4 *)w
[2556]815 ,(complex<r_4> *)work,&lwork,(r_4 *)rwork,&info);
816 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
817 delete [] work; delete [] rwork; delete [] w;
818 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]819 int_4 lwork = 2*n-1; complex<r_8>* work = new complex<r_8>[lwork +GARDMEM];
820 r_8* rwork = new r_8[3*n-2 +GARDMEM]; r_8* w = new r_8[n];
[2561]821 zheev_(&jobz,&uplo,&n,(complex<r_8> *)a.Data(),&lda,(r_8 *)w
[2556]822 ,(complex<r_8> *)work,&lwork,(r_8 *)rwork,&info);
823 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
824 delete [] work; delete [] rwork; delete [] w;
825 } else {
826 string tn = typeid(T).name();
827 cerr << " LapackServer::LapackEigenSym(a,b) - Unsupported DataType T = " << tn << endl;
828 throw TypeMismatchExc("LapackServer::LapackEigenSym(a,b) - Unsupported DataType (T)");
829 }
830
831 return(info);
832}
833
834////////////////////////////////////////////////////////////////////////////////////
835/*! Computes the eigen values and eigen vectors of a general squared matrix \b a.
836 Input arrays should have FortranMemoryMapping (column packed).
837 \param a : input general n-by-n matrix
838 \param eval : Vector of eigenvalues (complex double precision)
839 \param evec : Matrix of eigenvector (same order than eval, one vector = one column)
840 \param eigenvector : if true compute (right) eigenvectors, if not only eigenvalues
841 \param a : on return array of eigenvectors
[2561]842 \return : return code from lapack driver
[2556]843 \verbatim
844 eval : contains the computed eigenvalues.
845 --- For real matrices "a" :
846 Complex conjugate pairs of eigenvalues appear consecutively
847 with the eigenvalue having the positive imaginary part first.
848 evec : the right eigenvectors v(j) are stored one after another
849 in the columns of evec, in the same order as their eigenvalues.
850 --- For real matrices "a" :
851 If the j-th eigenvalue is real, then v(j) = evec(:,j),
852 the j-th column of evec.
853 If the j-th and (j+1)-st eigenvalues form a complex
854 conjugate pair, then v(j) = evec(:,j) + i*evec(:,j+1) and
855 v(j+1) = evec(:,j) - i*evec(:,j+1).
856 \endverbatim
857*/
858
859template <class T>
860int LapackServer<T>::LapackEigen(TArray<T>& a, TVector< complex<r_8> >& eval, TMatrix<T>& evec, bool eigenvector)
861{
862 if ( a.NbDimensions() != 2 )
863 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a NbDimensions() != 2"));
864 int_4 rowa = a.RowsKA();
865 int_4 cola = a.ColsKA();
866 if ( a.Size(rowa) != a.Size(cola))
867 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a Not a square Array"));
868 if (!a.IsPacked(rowa))
869 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a Not Column Packed"));
870
[2561]871 char jobvl = 'N';
[2556]872 char jobvr = 'N'; if(eigenvector) jobvr='V';
873
874 int_4 n = a.Size(rowa);
875 int_4 lda = a.Step(cola);
876 int_4 info = 0;
877
878 eval.ReSize(n); eval = complex<r_8>(0.,0.);
879 if(eigenvector) {evec.ReSize(n,n); evec = (T) 0.;}
880 int_4 ldvr = n, ldvl = 1;
881
882 if (typeid(T) == typeid(r_4) ) {
[2567]883 int_4 lwork = 4*n; r_4* work = new r_4[lwork +GARDMEM];
[2556]884 r_4* wr = new r_4[n]; r_4* wi = new r_4[n]; r_4* vl = NULL;
[2561]885 sgeev_(&jobvl,&jobvr,&n,(r_4 *)a.Data(),&lda,(r_4 *)wr,(r_4 *)wi,
[2556]886 (r_4 *)vl,&ldvl,(r_4 *)evec.Data(),&ldvr,
887 (r_4 *)work,&lwork,&info);
888 if(info==0) for(int i=0;i<n;i++) eval(i) = complex<r_8>(wr[i],wi[i]);
889 delete [] work; delete [] wr; delete [] wi;
890 } else if (typeid(T) == typeid(r_8) ) {
[2567]891 int_4 lwork = 4*n; r_8* work = new r_8[lwork +GARDMEM];
[2556]892 r_8* wr = new r_8[n]; r_8* wi = new r_8[n]; r_8* vl = NULL;
[2561]893 dgeev_(&jobvl,&jobvr,&n,(r_8 *)a.Data(),&lda,(r_8 *)wr,(r_8 *)wi,
[2556]894 (r_8 *)vl,&ldvl,(r_8 *)evec.Data(),&ldvr,
895 (r_8 *)work,&lwork,&info);
896 if(info==0) for(int i=0;i<n;i++) eval(i) = complex<r_8>(wr[i],wi[i]);
897 delete [] work; delete [] wr; delete [] wi;
898 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]899 int_4 lwork = 2*n; complex<r_4>* work = new complex<r_4>[lwork +GARDMEM];
900 r_4* rwork = new r_4[2*n +GARDMEM]; r_4* vl = NULL; TVector< complex<r_4> > w(n);
[2561]901 cgeev_(&jobvl,&jobvr,&n,(complex<r_4> *)a.Data(),&lda,(complex<r_4> *)w.Data(),
[2556]902 (complex<r_4> *)vl,&ldvl,(complex<r_4> *)evec.Data(),&ldvr,
903 (complex<r_4> *)work,&lwork,(r_4 *)rwork,&info);
904 if(info==0) for(int i=0;i<n;i++) eval(i) = w(i);
905 delete [] work; delete [] rwork;
906 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]907 int_4 lwork = 2*n; complex<r_8>* work = new complex<r_8>[lwork +GARDMEM];
908 r_8* rwork = new r_8[2*n +GARDMEM]; r_8* vl = NULL;
[2561]909 zgeev_(&jobvl,&jobvr,&n,(complex<r_8> *)a.Data(),&lda,(complex<r_8> *)eval.Data(),
[2556]910 (complex<r_8> *)vl,&ldvl,(complex<r_8> *)evec.Data(),&ldvr,
911 (complex<r_8> *)work,&lwork,(r_8 *)rwork,&info);
912 delete [] work; delete [] rwork;
913 } else {
914 string tn = typeid(T).name();
915 cerr << " LapackServer::LapackEigen(a,b) - Unsupported DataType T = " << tn << endl;
916 throw TypeMismatchExc("LapackServer::LapackEigen(a,b) - Unsupported DataType (T)");
917 }
918
919 return(info);
920}
921
922
923
924
925
926////////////////////////////////////////////////////////////////////////////////////
[775]927void rztest_lapack(TArray<r_4>& aa, TArray<r_4>& bb)
928{
929 if ( aa.NbDimensions() != 2 ) throw(SzMismatchError("rztest_lapack(TMatrix<r_4> A Not a Matrix"));
930 if ( aa.SizeX() != aa.SizeY()) throw(SzMismatchError("rztest_lapack(TMatrix<r_4> A Not a square Matrix"));
931 if ( bb.NbDimensions() != 2 ) throw(SzMismatchError("rztest_lapack(TMatrix<r_4> A Not a Matrix"));
[788]932 if ( bb.SizeX() != aa.SizeX() ) throw(SzMismatchError("rztest_lapack(TMatrix<r_4> A <> B "));
[775]933 if ( !bb.IsPacked() || !bb.IsPacked() )
934 throw(SzMismatchError("rztest_lapack(TMatrix<r_4> Not packed A or B "));
935
[788]936 int_4 n = aa.SizeX();
937 int_4 nrhs = bb.SizeY();
[775]938 int_4 lda = n;
[788]939 int_4 ldb = bb.SizeX();
[775]940 int_4 info;
941 int_4* ipiv = new int_4[n];
942 sgesv_(&n, &nrhs, aa.Data(), &lda, ipiv, bb.Data(), &ldb, &info);
[814]943 delete[] ipiv;
[775]944 cout << "rztest_lapack/Info= " << info << endl;
945 cout << aa << "\n" << bb << endl;
946 return;
947}
[814]948
949///////////////////////////////////////////////////////////////
950#ifdef __CXX_PRAGMA_TEMPLATES__
951#pragma define_template LapackServer<r_4>
952#pragma define_template LapackServer<r_8>
953#pragma define_template LapackServer< complex<r_4> >
954#pragma define_template LapackServer< complex<r_8> >
955#endif
956
957#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
958template class LapackServer<r_4>;
959template class LapackServer<r_8>;
960template class LapackServer< complex<r_4> >;
961template class LapackServer< complex<r_8> >;
962#endif
963
964#if defined(OS_LINUX)
965// Pour le link avec f2c sous Linux
966extern "C" {
967 void MAIN__();
968}
969
970void MAIN__()
971{
972 cerr << "MAIN__() function for linking with libf2c.a " << endl;
973 cerr << " This function should never be called !!! " << endl;
974 throw PError("MAIN__() should not be called - see intflapack.cc");
975}
976#endif
Note: See TracBrowser for help on using the repository browser.