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

Last change on this file since 2880 was 2880, checked in by ansari, 20 years ago

Ajout declaration ilaenv - oublie - Reza 3 Jan 2006

File size: 47.2 KB
RevLine 
[2322]1#include <iostream>
[2567]2#include <math.h>
[2615]3#include "sopnamsp.h"
[775]4#include "intflapack.h"
[1342]5#include "tvector.h"
6#include "tmatrix.h"
[814]7#include <typeinfo>
[775]8
[2567]9#define GARDMEM 5
10
[2556]11/*************** Pour memoire (Christophe) ***************
12Les dispositions memoires (FORTRAN) pour les vecteurs et matrices LAPACK:
13
141./ --- REAL X(N):
15 if an array X of dimension (N) holds a vector x,
16 then X(i) holds "x_i" for i=1,...,N
17
182./ --- REAL A(LDA,N):
19 if a two-dimensional array A of dimension (LDA,N) holds an m-by-n matrix A,
20 then A(i,j) holds "a_ij" for i=1,...,m et j=1,...,n (LDA must be at least m).
21 Note that array arguments are usually declared in the software as assumed-size
22 arrays (last dimension *), for example: REAL A(LDA,*)
23 --- Rangement en memoire:
24 | 11 12 13 14 |
25 Ex: Real A(4,4): A = | 21 22 23 24 |
26 | 31 32 33 34 |
27 | 41 42 43 44 |
28 memoire: {11 21 31 41} {12 22 32 42} {13 23 33 43} {14 24 34 44}
29 First indice (line) "i" varies then the second (column):
30 (put all the first column, then put all the second column,
31 ..., then put all the last column)
32***********************************************************/
33
[1424]34/*!
35 \defgroup LinAlg LinAlg module
36 This module contains classes and functions for complex linear
37 algebra on arrays. This module is intended mainly to have
38 classes implementing C++ interfaces between Sophya objects
39 and external linear algebra libraries, such as LAPACK.
40*/
41
42/*!
43 \class SOPHYA::LapackServer
44 \ingroup LinAlg
45 This class implements an interface to LAPACK library driver routines.
46 The LAPACK (Linear Algebra PACKage) is a collection high performance
47 routines to solve common problems in numerical linear algebra.
48 its is available from http://www.netlib.org.
49
[2646]50 The present version of LapackServer (Feb 2005) provides
51 interfaces for the linear system solver, singular value
52 decomposition (SVD), Least square solver and
53 eigen value / eigen vector decomposition.
54 Only arrays with BaseArray::FortranMemoryMapping
[1424]55 can be handled by LapackServer. LapackServer can be instanciated
56 for simple and double precision real or complex array types.
[2646]57 \warning The input array is overwritten in most cases.
[1424]58 The example below shows solving a linear system A*X = B
59
60 \code
61 #include "intflapack.h"
62 // ...
63 // Use FortranMemoryMapping as default
64 BaseArray::SetDefaultMemoryMapping(BaseArray::FortranMemoryMapping);
65 // Create an fill the arrays A and B
66 int n = 20;
67 Matrix A(n, n);
68 A = RandomSequence();
69 Vector X(n),B(n);
70 X = RandomSequence();
71 B = A*X;
72 // Solve the linear system A*X = B
73 LapackServer<r_8> lps;
74 lps.LinSolve(A,B);
75 // We get the result in B, which should be equal to X ...
76 // Compute the difference B-X ;
77 Vector diff = B-X;
78 \endcode
79
80*/
81
[2875]82/*
83 Decembre 2005 : Suite portage AIX xlC
84 On declare des noms en majuscule pour les routines fortran -
85 avec ou sans underscore _ , suivant les systemes
86*/
87#ifdef AIX
88
[2880]89#define ilaenv ilaenv
90
[2875]91#define sgesv sgesv
92#define dgesv dgesv
93#define cgesv cgesv
94#define zgesv zgesv
95
96#define ssysv ssysv
97#define dsysv dsysv
98#define csysv csysv
99#define zsysv zsysv
100
101#define sgels sgels
102#define dgels dgels
103#define cgels cgels
104#define zgels zgels
105
106#define sgelsd sgelsd
107#define dgelsd dgelsd
108#define cgelsd cgelsd
109#define zgelsd zgelsd
110
111#define sgesvd sgesvd
112#define dgesvd dgesvd
113#define cgesvd cgesvd
114#define zgesvd zgesvd
115
116#define sgesdd sgesdd
117#define dgesdd dgesdd
118#define cgesdd cgesdd
119#define zgesdd zgesdd
120
121#define ssyev ssyev
122#define dsyev dsyev
123#define cheev cheev
124#define zheev zheev
125
126#define sgeev sgeev
127#define dgeev dgeev
128#define cgeev cgeev
129#define zgeev zgeev
130
131#else
[2880]132#define ilaenv ilaenv_
[2875]133
134#define sgesv sgesv_
135#define dgesv dgesv_
136#define cgesv cgesv_
137#define zgesv zgesv_
138
139#define ssysv ssysv_
140#define dsysv dsysv_
141#define csysv csysv_
142#define zsysv zsysv_
143
144#define sgels sgels_
145#define dgels dgels_
146#define cgels cgels_
147#define zgels zgels_
148
149#define sgelsd sgelsd_
150#define dgelsd dgelsd_
151#define cgelsd cgelsd_
152#define zgelsd zgelsd_
153
154#define sgesvd sgesvd_
155#define dgesvd dgesvd_
156#define cgesvd cgesvd_
157#define zgesvd zgesvd_
158
159#define sgesdd sgesdd_
160#define dgesdd dgesdd_
161#define cgesdd cgesdd_
162#define zgesdd zgesdd_
163
164#define ssyev ssyev_
165#define dsyev dsyev_
166#define cheev cheev_
167#define zheev zheev_
168
169#define sgeev sgeev_
170#define dgeev dgeev_
171#define cgeev cgeev_
172#define zgeev zgeev_
173
174#endif
[2556]175////////////////////////////////////////////////////////////////////////////////////
[775]176extern "C" {
[2554]177// Le calculateur de workingspace
[2875]178 int_4 ilaenv(int_4 *ispec,char *name,char *opts,int_4 *n1,int_4 *n2,int_4 *n3,int_4 *n4,
[2554]179 int_4 nc1,int_4 nc2);
180
[1342]181// Drivers pour resolution de systemes lineaires
[2875]182 void sgesv(int_4* n, int_4* nrhs, r_4* a, int_4* lda,
[1342]183 int_4* ipiv, r_4* b, int_4* ldb, int_4* info);
[2875]184 void dgesv(int_4* n, int_4* nrhs, r_8* a, int_4* lda,
[1342]185 int_4* ipiv, r_8* b, int_4* ldb, int_4* info);
[2875]186 void cgesv(int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
[1342]187 int_4* ipiv, complex<r_4>* b, int_4* ldb, int_4* info);
[2875]188 void zgesv(int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
[1342]189 int_4* ipiv, complex<r_8>* b, int_4* ldb, int_4* info);
190
[2554]191// Drivers pour resolution de systemes lineaires symetriques
[2875]192 void ssysv(char* uplo, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
[2554]193 int_4* ipiv, r_4* b, int_4* ldb,
194 r_4* work, int_4* lwork, int_4* info);
[2875]195 void dsysv(char* uplo, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
[2554]196 int_4* ipiv, r_8* b, int_4* ldb,
197 r_8* work, int_4* lwork, int_4* info);
[2875]198 void csysv(char* uplo, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
[2554]199 int_4* ipiv, complex<r_4>* b, int_4* ldb,
200 complex<r_4>* work, int_4* lwork, int_4* info);
[2875]201 void zsysv(char* uplo, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
[2554]202 int_4* ipiv, complex<r_8>* b, int_4* ldb,
203 complex<r_8>* work, int_4* lwork, int_4* info);
204
205// Driver pour resolution de systemes au sens de Xi2
[2875]206 void sgels(char * trans, int_4* m, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
[1494]207 r_4* b, int_4* ldb, r_4* work, int_4* lwork, int_4* info);
[2875]208 void dgels(char * trans, int_4* m, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
[1494]209 r_8* b, int_4* ldb, r_8* work, int_4* lwork, int_4* info);
[2875]210 void cgels(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
[1494]211 complex<r_4>* b, int_4* ldb, complex<r_4>* work, int_4* lwork, int_4* info);
[2875]212 void zgels(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
[1494]213 complex<r_8>* b, int_4* ldb, complex<r_8>* work, int_4* lwork, int_4* info);
214
[2567]215// Driver pour resolution de systemes au sens de Xi2 par SVD Divide & Conquer
[2875]216 void sgelsd(int_4* m,int_4* n,int_4* nrhs,r_4* a,int_4* lda,
[2567]217 r_4* b,int_4* ldb,r_4* s,r_4* rcond,int_4* rank,
218 r_4* work,int_4* lwork,int_4* iwork,int_4* info);
[2875]219 void dgelsd(int_4* m,int_4* n,int_4* nrhs,r_8* a,int_4* lda,
[2567]220 r_8* b,int_4* ldb,r_8* s,r_8* rcond,int_4* rank,
221 r_8* work,int_4* lwork,int_4* iwork,int_4* info);
[2875]222 void cgelsd(int_4* m,int_4* n,int_4* nrhs,complex<r_4>* a,int_4* lda,
[2567]223 complex<r_4>* b,int_4* ldb,r_4* s,r_4* rcond,int_4* rank,
224 complex<r_4>* work,int_4* lwork,r_4* rwork,int_4* iwork,int_4* info);
[2875]225 void zgelsd(int_4* m,int_4* n,int_4* nrhs,complex<r_8>* a,int_4* lda,
[2567]226 complex<r_8>* b,int_4* ldb,r_8* s,r_8* rcond,int_4* rank,
227 complex<r_8>* work,int_4* lwork,r_8* rwork,int_4* iwork,int_4* info);
228
[1342]229// Driver pour decomposition SVD
[2875]230 void sgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, r_4* a, int_4* lda,
[1342]231 r_4* s, r_4* u, int_4* ldu, r_4* vt, int_4* ldvt,
232 r_4* work, int_4* lwork, int_4* info);
[2875]233 void dgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, r_8* a, int_4* lda,
[1342]234 r_8* s, r_8* u, int_4* ldu, r_8* vt, int_4* ldvt,
235 r_8* work, int_4* lwork, int_4* info);
[2875]236 void cgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
[2559]237 r_4* s, complex<r_4>* u, int_4* ldu, complex<r_4>* vt, int_4* ldvt,
238 complex<r_4>* work, int_4* lwork, r_4* rwork, int_4* info);
[2875]239 void zgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
[2559]240 r_8* s, complex<r_8>* u, int_4* ldu, complex<r_8>* vt, int_4* ldvt,
241 complex<r_8>* work, int_4* lwork, r_8* rwork, int_4* info);
[2556]242
[2561]243// Driver pour decomposition SVD Divide and Conquer
[2875]244 void sgesdd(char* jobz, int_4* m, int_4* n, r_4* a, int_4* lda,
[2561]245 r_4* s, r_4* u, int_4* ldu, r_4* vt, int_4* ldvt,
246 r_4* work, int_4* lwork, int_4* iwork, int_4* info);
[2875]247 void dgesdd(char* jobz, int_4* m, int_4* n, r_8* a, int_4* lda,
[2561]248 r_8* s, r_8* u, int_4* ldu, r_8* vt, int_4* ldvt,
249 r_8* work, int_4* lwork, int_4* iwork, int_4* info);
[2875]250 void cgesdd(char* jobz, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
[2561]251 r_4* s, complex<r_4>* u, int_4* ldu, complex<r_4>* vt, int_4* ldvt,
252 complex<r_4>* work, int_4* lwork, r_4* rwork, int_4* iwork, int_4* info);
[2875]253 void zgesdd(char* jobz, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
[2561]254 r_8* s, complex<r_8>* u, int_4* ldu, complex<r_8>* vt, int_4* ldvt,
255 complex<r_8>* work, int_4* lwork, r_8* rwork, int_4* iwork, int_4* info);
256
[2556]257// Driver pour eigen decomposition for symetric/hermitian matrices
[2875]258 void ssyev(char* jobz, char* uplo, int_4* n, r_4* a, int_4* lda, r_4* w,
[2556]259 r_4* work, int_4 *lwork, int_4* info);
[2875]260 void dsyev(char* jobz, char* uplo, int_4* n, r_8* a, int_4* lda, r_8* w,
[2556]261 r_8* work, int_4 *lwork, int_4* info);
[2875]262 void cheev(char* jobz, char* uplo, int_4* n, complex<r_4>* a, int_4* lda, r_4* w,
[2556]263 complex<r_4>* work, int_4 *lwork, r_4* rwork, int_4* info);
[2875]264 void zheev(char* jobz, char* uplo, int_4* n, complex<r_8>* a, int_4* lda, r_8* w,
[2556]265 complex<r_8>* work, int_4 *lwork, r_8* rwork, int_4* info);
266
267// Driver pour eigen decomposition for general squared matrices
[2875]268 void sgeev(char* jobl, char* jobvr, int_4* n, r_4* a, int_4* lda, r_4* wr, r_4* wi,
[2556]269 r_4* vl, int_4* ldvl, r_4* vr, int_4* ldvr,
270 r_4* work, int_4 *lwork, int_4* info);
[2875]271 void dgeev(char* jobl, char* jobvr, int_4* n, r_8* a, int_4* lda, r_8* wr, r_8* wi,
[2556]272 r_8* vl, int_4* ldvl, r_8* vr, int_4* ldvr,
273 r_8* work, int_4 *lwork, int_4* info);
[2875]274 void cgeev(char* jobl, char* jobvr, int_4* n, complex<r_4>* a, int_4* lda, complex<r_4>* w,
[2556]275 complex<r_4>* vl, int_4* ldvl, complex<r_4>* vr, int_4* ldvr,
276 complex<r_4>* work, int_4 *lwork, r_4* rwork, int_4* info);
[2875]277 void zgeev(char* jobl, char* jobvr, int_4* n, complex<r_8>* a, int_4* lda, complex<r_8>* w,
[2556]278 complex<r_8>* vl, int_4* ldvl, complex<r_8>* vr, int_4* ldvr,
279 complex<r_8>* work, int_4 *lwork, r_8* rwork, int_4* info);
280
[775]281}
282
[1342]283// -------------- Classe LapackServer<T> --------------
284
[2556]285////////////////////////////////////////////////////////////////////////////////////
[814]286template <class T>
[1344]287LapackServer<T>::LapackServer()
[1342]288{
289 SetWorkSpaceSizeFactor();
290}
291
292template <class T>
[1344]293LapackServer<T>::~LapackServer()
[1342]294{
295}
296
[2556]297////////////////////////////////////////////////////////////////////////////////////
[2554]298template <class T>
299int_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)
300{
[2572]301 int_4 nc1 = strlen(name), nc2 = strlen(opts), rc=0;
[2875]302 rc = ilaenv(&ispec,name,opts,&n1,&n2,&n3,&n4,nc1,nc2);
[2554]303 //cout<<"ilaenv_en_C("<<ispec<<","<<name<<"("<<nc1<<"),"<<opts<<"("<<nc2<<"),"
304 // <<n1<<","<<n2<<","<<n3<<","<<n4<<") = "<<rc<<endl;
305 return rc;
306}
307
[2572]308template <class T>
309int_4 LapackServer<T>::type2i4(void *val,int nbytes)
310// Retourne un entier contenant la valeur contenue dans val
311// - nbytes = nombre de bytes dans le contenu de val
312// ex: r_4 x = 3.4; type2i4(&x,4) -> 3
313// ex: r_8 x = 3.4; type2i4(&x,8) -> 3
314// ex: complex<r_4> x(3.4,7.8); type2i4(&x,4) -> 3
315// ex: complex<r_8> x(3.4,7.8); type2i4(&x,8) -> 3
316{
317 r_4* x4; r_8* x8; int_4 lw=0;
318 if(nbytes==4) {x4 = (r_4*)val; lw = (int_4)(*x4);}
319 else {x8 = (r_8*)val; lw = (int_4)(*x8);}
320 return lw;
321}
322
[2556]323////////////////////////////////////////////////////////////////////////////////////
[2563]324//! Interface to Lapack linear system solver driver s/d/c/zgesv().
325/*! Solve the linear system a * x = b using LU factorization.
326 Input arrays should have FortranMemory mapping (column packed).
[1424]327 \param a : input matrix, overwritten on output
328 \param b : input-output, input vector b, contains x on exit
329 \return : return code from lapack driver _gesv()
330 */
[1342]331template <class T>
[1042]332int LapackServer<T>::LinSolve(TArray<T>& a, TArray<T> & b)
[814]333{
334 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
335 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b NbDimensions() != 2"));
336
[1342]337 int_4 rowa = a.RowsKA();
338 int_4 cola = a.ColsKA();
339 int_4 rowb = b.RowsKA();
340 int_4 colb = b.ColsKA();
[814]341 if ( a.Size(rowa) != a.Size(cola))
342 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Not a square Array"));
[1042]343 if ( a.Size(rowa) != b.Size(rowb))
[814]344 throw(SzMismatchError("LapackServer::LinSolve(a,b) RowSize(a <> b) "));
345
346 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
[1342]347 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b Not Column Packed"));
[814]348
349 int_4 n = a.Size(rowa);
350 int_4 nrhs = b.Size(colb);
351 int_4 lda = a.Step(cola);
352 int_4 ldb = b.Step(colb);
353 int_4 info;
354 int_4* ipiv = new int_4[n];
355
356 if (typeid(T) == typeid(r_4) )
[2875]357 sgesv(&n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb, &info);
[814]358 else if (typeid(T) == typeid(r_8) )
[2875]359 dgesv(&n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb, &info);
[814]360 else if (typeid(T) == typeid(complex<r_4>) )
[2875]361 cgesv(&n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
[814]362 (complex<r_4> *)b.Data(), &ldb, &info);
363 else if (typeid(T) == typeid(complex<r_8>) )
[2875]364 zgesv(&n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
[814]365 (complex<r_8> *)b.Data(), &ldb, &info);
366 else {
367 delete[] ipiv;
368 string tn = typeid(T).name();
369 cerr << " LapackServer::LinSolve(a,b) - Unsupported DataType T = " << tn << endl;
370 throw TypeMismatchExc("LapackServer::LinSolve(a,b) - Unsupported DataType (T)");
371 }
372 delete[] ipiv;
[1042]373 return(info);
[814]374}
375
[2556]376////////////////////////////////////////////////////////////////////////////////////
[2563]377//! Interface to Lapack linear system solver driver s/d/c/zsysv().
378/*! Solve the linear system a * x = b with a symetric matrix using LU factorization.
379 Input arrays should have FortranMemory mapping (column packed).
[2554]380 \param a : input matrix symetric , overwritten on output
381 \param b : input-output, input vector b, contains x on exit
[2563]382 \return : return code from lapack driver _sysv()
[2554]383 */
384template <class T>
385int LapackServer<T>::LinSolveSym(TArray<T>& a, TArray<T> & b)
386// --- REMARQUES DE CMV ---
387// 1./ contrairement a ce qui est dit dans la doc, il s'agit
388// de matrices SYMETRIQUES complexes et non HERMITIENNES !!!
389// 2./ pourquoi les routines de LinSolve pour des matrices symetriques
[2556]390// sont plus de deux fois plus lentes que les LinSolve generales sur OSF
391// et sensiblement plus lentes sous Linux ???
[2554]392{
393 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
394 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Or b NbDimensions() != 2"));
395 int_4 rowa = a.RowsKA();
396 int_4 cola = a.ColsKA();
397 int_4 rowb = b.RowsKA();
398 int_4 colb = b.ColsKA();
399 if ( a.Size(rowa) != a.Size(cola))
400 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Not a square Array"));
401 if ( a.Size(rowa) != b.Size(rowb))
402 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) RowSize(a <> b) "));
403
404 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
405 throw(SzMismatchError("LapackServer::LinSolveSym(a,b) a Or b Not Column Packed"));
406
407 int_4 n = a.Size(rowa);
408 int_4 nrhs = b.Size(colb);
409 int_4 lda = a.Step(cola);
410 int_4 ldb = b.Step(colb);
411 int_4 info = 0;
412 int_4* ipiv = new int_4[n];
413 int_4 lwork = -1;
414 T * work = NULL;
[2572]415 T wkget[2];
[2554]416
417 char uplo = 'U'; // char uplo = 'L';
418 char struplo[5]; struplo[0] = uplo; struplo[1] = '\0';
419
420 if (typeid(T) == typeid(r_4) ) {
[2875]421 ssysv(&uplo, &n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb,
[2572]422 (r_4 *)wkget, &lwork, &info);
423 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]424 ssysv(&uplo, &n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb,
[2554]425 (r_4 *)work, &lwork, &info);
426 } else if (typeid(T) == typeid(r_8) ) {
[2875]427 dsysv(&uplo, &n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb,
[2572]428 (r_8 *)wkget, &lwork, &info);
429 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]430 dsysv(&uplo, &n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb,
[2554]431 (r_8 *)work, &lwork, &info);
432 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2875]433 csysv(&uplo, &n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
[2554]434 (complex<r_4> *)b.Data(), &ldb,
[2572]435 (complex<r_4> *)wkget, &lwork, &info);
436 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]437 csysv(&uplo, &n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
[2572]438 (complex<r_4> *)b.Data(), &ldb,
[2554]439 (complex<r_4> *)work, &lwork, &info);
440 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2875]441 zsysv(&uplo, &n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
[2554]442 (complex<r_8> *)b.Data(), &ldb,
[2572]443 (complex<r_8> *)wkget, &lwork, &info);
444 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]445 zsysv(&uplo, &n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
[2572]446 (complex<r_8> *)b.Data(), &ldb,
[2554]447 (complex<r_8> *)work, &lwork, &info);
448 } else {
[2556]449 if(work) delete[] work;
[2554]450 delete[] ipiv;
451 string tn = typeid(T).name();
452 cerr << " LapackServer::LinSolveSym(a,b) - Unsupported DataType T = " << tn << endl;
453 throw TypeMismatchExc("LapackServer::LinSolveSym(a,b) - Unsupported DataType (T)");
454 }
[2556]455 if(work) delete[] work;
[2554]456 delete[] ipiv;
457 return(info);
458}
459
[2556]460////////////////////////////////////////////////////////////////////////////////////
[1566]461//! Interface to Lapack least squares solver driver s/d/c/zgels().
462/*! Solves the linear least squares problem defined by an m-by-n matrix
[2563]463 \b a and an m element vector \b b , using QR or LQ factorization .
[1566]464 A solution \b x to the overdetermined system of linear equations
465 b = a * x is computed, minimizing the norm of b-a*x.
466 Underdetermined systems (m<n) are not yet handled.
467 Inout arrays should have FortranMemory mapping (column packed).
468 \param a : input matrix, overwritten on output
469 \param b : input-output, input vector b, contains x on exit.
470 \return : return code from lapack driver _gels()
471 \warning : b is not resized.
472 */
473/*
474 $CHECK$ - A faire - cas m<n
475 If the linear system is underdetermined, the minimum norm
476 solution is computed.
477*/
478
[1494]479template <class T>
480int LapackServer<T>::LeastSquareSolve(TArray<T>& a, TArray<T> & b)
481{
482 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
[2561]483 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b NbDimensions() != 2"));
[1494]484
485 int_4 rowa = a.RowsKA();
486 int_4 cola = a.ColsKA();
487 int_4 rowb = b.RowsKA();
488 int_4 colb = b.ColsKA();
489
490
491 if ( a.Size(rowa) != b.Size(rowb))
492 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) RowSize(a <> b) "));
493
494 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
[1566]495 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b Not Column Packed"));
[1494]496
[1566]497 if ( a.Size(rowa) < a.Size(cola)) { // $CHECK$ - m<n a changer
498 cout << " LapackServer<T>::LeastSquareSolve() - m<n - Not yet implemented for "
499 << " underdetermined systems ! " << endl;
500 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) NRows<NCols - "));
501 }
[1494]502 int_4 m = a.Size(rowa);
503 int_4 n = a.Size(cola);
504 int_4 nrhs = b.Size(colb);
505
506 int_4 lda = a.Step(cola);
507 int_4 ldb = b.Step(colb);
508 int_4 info;
509
510 int_4 minmn = (m < n) ? m : n;
511 int_4 maxmn = (m > n) ? m : n;
512 int_4 maxmnrhs = (nrhs > maxmn) ? nrhs : maxmn;
513 if (maxmnrhs < 1) maxmnrhs = 1;
514
[2572]515 int_4 lwork = -1; //minmn+maxmnrhs*5;
516 T * work = NULL;
517 T wkget[2];
[1494]518
519 char trans = 'N';
520
[2572]521 if (typeid(T) == typeid(r_4) ) {
[2875]522 sgels(&trans, &m, &n, &nrhs, (r_4 *)a.Data(), &lda,
[2572]523 (r_4 *)b.Data(), &ldb, (r_4 *)wkget, &lwork, &info);
524 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]525 sgels(&trans, &m, &n, &nrhs, (r_4 *)a.Data(), &lda,
[1494]526 (r_4 *)b.Data(), &ldb, (r_4 *)work, &lwork, &info);
[2572]527 } else if (typeid(T) == typeid(r_8) ) {
[2875]528 dgels(&trans, &m, &n, &nrhs, (r_8 *)a.Data(), &lda,
[2572]529 (r_8 *)b.Data(), &ldb, (r_8 *)wkget, &lwork, &info);
530 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]531 dgels(&trans, &m, &n, &nrhs, (r_8 *)a.Data(), &lda,
[1494]532 (r_8 *)b.Data(), &ldb, (r_8 *)work, &lwork, &info);
[2572]533 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2875]534 cgels(&trans, &m, &n, &nrhs, (complex<r_4> *)a.Data(), &lda,
[2572]535 (complex<r_4> *)b.Data(), &ldb, (complex<r_4> *)wkget, &lwork, &info);
536 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]537 cgels(&trans, &m, &n, &nrhs, (complex<r_4> *)a.Data(), &lda,
[1494]538 (complex<r_4> *)b.Data(), &ldb, (complex<r_4> *)work, &lwork, &info);
[2572]539 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2875]540 zgels(&trans, &m, &n, &nrhs, (complex<r_8> *)a.Data(), &lda,
[2572]541 (complex<r_8> *)b.Data(), &ldb, (complex<r_8> *)wkget, &lwork, &info);
542 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]543 zgels(&trans, &m, &n, &nrhs, (complex<r_8> *)a.Data(), &lda,
[1494]544 (complex<r_8> *)b.Data(), &ldb, (complex<r_8> *)work, &lwork, &info);
[2572]545 } else {
546 if(work) delete [] work; work=NULL;
[1494]547 string tn = typeid(T).name();
548 cerr << " LapackServer::LeastSquareSolve(a,b) - Unsupported DataType T = " << tn << endl;
549 throw TypeMismatchExc("LapackServer::LeastSquareSolve(a,b) - Unsupported DataType (T)");
550 }
[2572]551 if(work) delete [] work;
[1494]552 return(info);
553}
554
[2567]555////////////////////////////////////////////////////////////////////////////////////
[2646]556//! Square matrix inversion using Lapack linear system solver
557/*! Compute the inverse of a square matrix using linear system solver routine
558 Input arrays should have FortranMemory mapping (column packed).
559 \param a : input matrix, overwritten on output
560 \param ainv : output matrix, contains inverse(a) on exit.
561 ainv is allocated if it has size 0
562 If not allocated, ainv is automatically
563 \return : return code from LapackServer::LinSolve()
564 \sa LapackServer::LinSolve()
565 */
566template <class T>
567int LapackServer<T>::ComputeInverse(TMatrix<T>& a, TMatrix<T> & ainv)
568{
569 if ( a.NbDimensions() != 2 )
570 throw(SzMismatchError("LapackServer::Inverse() NDim(a) != 2"));
571 if ( a.GetMemoryMapping() != BaseArray::FortranMemoryMapping )
572 throw(SzMismatchError("LapackServer::Inverse() a NOT in FortranMemoryMapping"));
573 if ( a.NRows() != a.NCols() )
574 throw(SzMismatchError("LapackServer::Inverse() a NOT square matrix (a.NRows!=a.NCols)"));
575 if (ainv.IsAllocated()) {
576 bool smo, ssz;
577 ssz = a.CompareSizes(ainv, smo);
578 if ( (ssz == false) || (smo == false) )
579 throw(SzMismatchError("LapackServer::Inverse() ainv<>a Size/MemOrg mismatch "));
580 }
581 else ainv.SetSize(a.NRows(), a.NCols(), BaseArray::FortranMemoryMapping, false);
582 ainv = IdentityMatrix();
583 return LinSolve(a, ainv);
584}
585
586////////////////////////////////////////////////////////////////////////////////////
[2567]587//! Interface to Lapack least squares solver driver s/d/c/zgelsd().
588/*! Solves the linear least squares problem defined by an m-by-n matrix
589 \b a and an m element vector \b b , using SVD factorization Divide and Conquer.
590 Inout arrays should have FortranMemory mapping (column packed).
591 \param rcond : definition of zero value (S(i) <= RCOND*S(0) are treated as zero).
592 If RCOND < 0, machine precision is used instead.
593 \param a : input matrix, overwritten on output
594 \param b : input vector b overwritten by solution on output (beware of size changing)
595 \param x : output matrix of solutions.
[2572]596 \param rank : output the rank of the matrix.
[2567]597 \return : return code from lapack driver _gelsd()
598 \warning : b is not resized.
599 */
600template <class T>
601int LapackServer<T>::LeastSquareSolveSVD_DC(TMatrix<T>& a,TMatrix<T>& b,TVector<r_8>& s,int_4& rank,r_8 rcond)
602{
603 if ( ( a.NbDimensions() != 2 ) )
604 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) a != 2"));
605
606 if (!a.IsPacked() || !b.IsPacked())
607 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) a Or b Not Packed"));
[1494]608
[2567]609 int_4 m = a.NRows();
610 int_4 n = a.NCols();
611
[2572]612 if(b.NRows() != m)
[2567]613 throw(SzMismatchError("LapackServer::LeastSquareSolveSVD_DC(a,b) bad matching dim between a and b"));
614
615 int_4 nrhs = b.NCols();
616 int_4 minmn = (m < n) ? m : n;
617 int_4 maxmn = (m > n) ? m : n;
618
619 int_4 lda = m;
620 int_4 ldb = maxmn;
621 int_4 info;
622
[2572]623 { // Use {} for automatic des-allocation of "bsave"
624 TMatrix<T> bsave(m,nrhs); bsave.SetMemoryMapping(BaseArray::FortranMemoryMapping);
[2567]625 bsave = b;
626 b.ReSize(maxmn,nrhs); b = (T) 0;
[2572]627 for(int i=0;i<m;i++) for(int j=0;j<nrhs;j++) b(i,j) = bsave(i,j);
628 } // Use {} for automatic des-allocation of "bsave"
[2567]629 s.ReSize(minmn);
630
[2572]631 int_4 smlsiz = 25; // Normallement ilaenv_en_C(9,...) renvoie toujours 25
[2567]632 if(typeid(T) == typeid(r_4) ) smlsiz = ilaenv_en_C(9,"SGELSD"," ",0,0,0,0);
633 else if(typeid(T) == typeid(r_8) ) smlsiz = ilaenv_en_C(9,"DGELSD"," ",0,0,0,0);
634 else if(typeid(T) == typeid(complex<r_4>) ) smlsiz = ilaenv_en_C(9,"CGELSD"," ",0,0,0,0);
635 else if(typeid(T) == typeid(complex<r_8>) ) smlsiz = ilaenv_en_C(9,"ZGELSD"," ",0,0,0,0);
636 if(smlsiz<0) smlsiz = 0;
637 r_8 dum = log((r_8)minmn/(r_8)(smlsiz+1.)) / log(2.);
638 int_4 nlvl = int_4(dum) + 1; if(nlvl<0) nlvl = 0;
639
[2572]640 T * work = NULL;
641 int_4 * iwork = NULL;
642 int_4 lwork=-1, lrwork;
643 T wkget[2];
644
[2567]645 if(typeid(T) == typeid(r_4) ) {
646 r_4* sloc = new r_4[minmn];
647 r_4 srcond = rcond;
[2572]648 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
[2875]649 sgelsd(&m,&n,&nrhs,(r_4*)a.Data(),&lda,
[2567]650 (r_4*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
[2572]651 (r_4*)wkget,&lwork,(int_4*)iwork,&info);
652 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]653 sgelsd(&m,&n,&nrhs,(r_4*)a.Data(),&lda,
[2572]654 (r_4*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
[2567]655 (r_4*)work,&lwork,(int_4*)iwork,&info);
656 for(int_4 i=0;i<minmn;i++) s(i) = sloc[i];
[2572]657 delete [] sloc;
[2567]658 } else if(typeid(T) == typeid(r_8) ) {
[2572]659 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
[2875]660 dgelsd(&m,&n,&nrhs,(r_8*)a.Data(),&lda,
[2567]661 (r_8*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
[2572]662 (r_8*)wkget,&lwork,(int_4*)iwork,&info);
663 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]664 dgelsd(&m,&n,&nrhs,(r_8*)a.Data(),&lda,
[2572]665 (r_8*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
[2567]666 (r_8*)work,&lwork,(int_4*)iwork,&info);
667 } else if(typeid(T) == typeid(complex<r_4>) ) {
[2572]668 // Cf meme remarque que ci-dessous (complex<r_8)
669 lrwork = 10*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);
670 int_4 lrwork_d = 12*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + minmn*nrhs + (smlsiz+1)*(smlsiz+1);
671 if(lrwork_d > lrwork) lrwork = lrwork_d;
[2567]672 r_4* rwork = new r_4[lrwork +GARDMEM];
[2572]673 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
[2567]674 r_4* sloc = new r_4[minmn];
675 r_4 srcond = rcond;
[2875]676 cgelsd(&m,&n,&nrhs,(complex<r_4>*)a.Data(),&lda,
[2567]677 (complex<r_4>*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
[2572]678 (complex<r_4>*)wkget,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
679 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]680 cgelsd(&m,&n,&nrhs,(complex<r_4>*)a.Data(),&lda,
[2572]681 (complex<r_4>*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
[2567]682 (complex<r_4>*)work,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
683 for(int_4 i=0;i<minmn;i++) s(i) = sloc[i];
[2572]684 delete [] sloc; delete [] rwork;
[2567]685 } else if(typeid(T) == typeid(complex<r_8>) ) {
[2572]686 // CMV: Bizarrement, la formule donnee dans zgelsd() plante pour des N grands (500)
687 // On prend (par analogie) la formule pour "lwork" de dgelsd()
688 lrwork = 10*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + 3*smlsiz*nrhs + (smlsiz+1)*(smlsiz+1);
689 int_4 lrwork_d = 12*minmn + 2*minmn*smlsiz + 8*minmn*nlvl + minmn*nrhs + (smlsiz+1)*(smlsiz+1);
690 if(lrwork_d > lrwork) lrwork = lrwork_d;
[2567]691 r_8* rwork = new r_8[lrwork +GARDMEM];
[2572]692 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
[2875]693 zgelsd(&m,&n,&nrhs,(complex<r_8>*)a.Data(),&lda,
[2572]694 (complex<r_8>*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
695 (complex<r_8>*)wkget,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
696 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]697 zgelsd(&m,&n,&nrhs,(complex<r_8>*)a.Data(),&lda,
[2572]698 (complex<r_8>*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
[2567]699 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
[2572]700 delete [] rwork;
[2567]701 } else {
[2572]702 if(work) delete [] work; work=NULL;
703 if(iwork) delete [] iwork; iwork=NULL;
[2567]704 string tn = typeid(T).name();
705 cerr << " LapackServer::LeastSquareSolveSVD_DC(a,b) - Unsupported DataType T = " << tn << endl;
706 throw TypeMismatchExc("LapackServer::LeastSquareSolveSVD_DC(a,b) - Unsupported DataType (T)");
707 }
708
[2572]709 if(work) delete [] work; if(iwork) delete [] iwork;
[2567]710 return(info);
711}
712
713
[2556]714////////////////////////////////////////////////////////////////////////////////////
[1424]715//! Interface to Lapack SVD driver s/d/c/zgesv().
716/*! Computes the vector of singular values of \b a. Input arrays
717 should have FortranMemoryMapping (column packed).
718 \param a : input m-by-n matrix
719 \param s : Vector of min(m,n) singular values (descending order)
720 \return : return code from lapack driver _gesvd()
721 */
722
[1342]723template <class T>
724int LapackServer<T>::SVD(TArray<T>& a, TArray<T> & s)
725{
726 return (SVDDriver(a, s, NULL, NULL) );
727}
728
[1424]729//! Interface to Lapack SVD driver s/d/c/zgesv().
730/*! Computes the vector of singular values of \b a, as well as
731 right and left singular vectors of \b a.
732 \f[
733 A = U \Sigma V^T , ( A = U \Sigma V^H \ complex)
734 \f]
735 \f[
736 A v_i = \sigma_i u_i \ and A^T u_i = \sigma_i v_i \ (A^H \ complex)
737 \f]
738 U and V are orthogonal (unitary) matrices.
[2572]739 \param a : input m-by-n matrix (in FortranMemoryMapping)
[1424]740 \param s : Vector of min(m,n) singular values (descending order)
[2572]741 \param u : m-by-m Matrix of left singular vectors
742 \param vt : Transpose of right singular vectors (n-by-n matrix).
[1424]743 \return : return code from lapack driver _gesvd()
744 */
[1342]745template <class T>
746int LapackServer<T>::SVD(TArray<T>& a, TArray<T> & s, TArray<T> & u, TArray<T> & vt)
747{
748 return (SVDDriver(a, s, &u, &vt) );
749}
750
[1424]751
752//! Interface to Lapack SVD driver s/d/c/zgesv().
[1342]753template <class T>
754int LapackServer<T>::SVDDriver(TArray<T>& a, TArray<T> & s, TArray<T>* up, TArray<T>* vtp)
755{
756 if ( ( a.NbDimensions() != 2 ) )
[2561]757 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a.NbDimensions() != 2"));
[1342]758
759 int_4 rowa = a.RowsKA();
760 int_4 cola = a.ColsKA();
761
762 if ( !a.IsPacked(rowa) )
[2561]763 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a Not Column Packed "));
[1342]764
765 int_4 m = a.Size(rowa);
766 int_4 n = a.Size(cola);
767 int_4 maxmn = (m > n) ? m : n;
768 int_4 minmn = (m < n) ? m : n;
769
770 char jobu, jobvt;
771 jobu = 'N';
772 jobvt = 'N';
773
774 sa_size_t sz[2];
775 if ( up != NULL) {
776 if ( dynamic_cast< TVector<T> * > (vtp) )
[2561]777 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for u !") );
[1342]778 up->SetMemoryMapping(BaseArray::FortranMemoryMapping);
779 sz[0] = sz[1] = m;
780 up->ReSize(2, sz );
781 jobu = 'A';
782 }
783 else {
784 up = new TMatrix<T>(1,1);
785 jobu = 'N';
786 }
787 if ( vtp != NULL) {
788 if ( dynamic_cast< TVector<T> * > (vtp) )
[2561]789 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for vt !") );
[1342]790 vtp->SetMemoryMapping(BaseArray::FortranMemoryMapping);
791 sz[0] = sz[1] = n;
792 vtp->ReSize(2, sz );
793 jobvt = 'A';
794 }
795 else {
796 vtp = new TMatrix<T>(1,1);
797 jobvt = 'N';
798 }
799
800 TVector<T> *vs = dynamic_cast< TVector<T> * > (&s);
801 if (vs) vs->ReSize(minmn);
802 else {
803 TMatrix<T> *ms = dynamic_cast< TMatrix<T> * > (&s);
804 if (ms) ms->ReSize(minmn,1);
805 else {
806 sz[0] = minmn; sz[1] = 1;
807 s.ReSize(1, sz);
808 }
809 }
810
811 int_4 lda = a.Step(a.ColsKA());
812 int_4 ldu = up->Step(up->ColsKA());
813 int_4 ldvt = vtp->Step(vtp->ColsKA());
[2567]814 int_4 info;
[1342]815
[2572]816 int_4 lwork = -1; // maxmn*5 *wspace_size_factor;
817 T * work = NULL; // = new T[lwork];
818 T wkget[2];
[1342]819
[2559]820 if (typeid(T) == typeid(r_4) ) {
[2875]821 sgesvd(&jobu, &jobvt, &m, &n, (r_4 *)a.Data(), &lda,
[1342]822 (r_4 *)s.Data(), (r_4 *) up->Data(), &ldu, (r_4 *)vtp->Data(), &ldvt,
[2572]823 (r_4 *)wkget, &lwork, &info);
824 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]825 sgesvd(&jobu, &jobvt, &m, &n, (r_4 *)a.Data(), &lda,
[2572]826 (r_4 *)s.Data(), (r_4 *) up->Data(), &ldu, (r_4 *)vtp->Data(), &ldvt,
[1342]827 (r_4 *)work, &lwork, &info);
[2559]828 } else if (typeid(T) == typeid(r_8) ) {
[2875]829 dgesvd(&jobu, &jobvt, &m, &n, (r_8 *)a.Data(), &lda,
[1342]830 (r_8 *)s.Data(), (r_8 *) up->Data(), &ldu, (r_8 *)vtp->Data(), &ldvt,
[2572]831 (r_8 *)wkget, &lwork, &info);
832 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]833 dgesvd(&jobu, &jobvt, &m, &n, (r_8 *)a.Data(), &lda,
[2572]834 (r_8 *)s.Data(), (r_8 *) up->Data(), &ldu, (r_8 *)vtp->Data(), &ldvt,
[1342]835 (r_8 *)work, &lwork, &info);
[2559]836 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]837 r_4 * rwork = new r_4[5*minmn +GARDMEM];
[2559]838 r_4 * sloc = new r_4[minmn];
[2875]839 cgesvd(&jobu, &jobvt, &m, &n, (complex<r_4> *)a.Data(), &lda,
[2559]840 (r_4 *)sloc, (complex<r_4> *) up->Data(), &ldu,
[1342]841 (complex<r_4> *)vtp->Data(), &ldvt,
[2572]842 (complex<r_4> *)wkget, &lwork, (r_4 *)rwork, &info);
843 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]844 cgesvd(&jobu, &jobvt, &m, &n, (complex<r_4> *)a.Data(), &lda,
[2572]845 (r_4 *)sloc, (complex<r_4> *) up->Data(), &ldu,
846 (complex<r_4> *)vtp->Data(), &ldvt,
[2559]847 (complex<r_4> *)work, &lwork, (r_4 *)rwork, &info);
848 for(int_4 i=0;i<minmn;i++) s[i] = sloc[i];
849 delete [] rwork; delete [] sloc;
850 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]851 r_8 * rwork = new r_8[5*minmn +GARDMEM];
[2559]852 r_8 * sloc = new r_8[minmn];
[2875]853 zgesvd(&jobu, &jobvt, &m, &n, (complex<r_8> *)a.Data(), &lda,
[2559]854 (r_8 *)sloc, (complex<r_8> *) up->Data(), &ldu,
[1342]855 (complex<r_8> *)vtp->Data(), &ldvt,
[2572]856 (complex<r_8> *)wkget, &lwork, (r_8 *)rwork, &info);
857 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]858 zgesvd(&jobu, &jobvt, &m, &n, (complex<r_8> *)a.Data(), &lda,
[2572]859 (r_8 *)sloc, (complex<r_8> *) up->Data(), &ldu,
860 (complex<r_8> *)vtp->Data(), &ldvt,
[2559]861 (complex<r_8> *)work, &lwork, (r_8 *)rwork, &info);
862 for(int_4 i=0;i<minmn;i++) s[i] = sloc[i];
863 delete [] rwork; delete [] sloc;
864 } else {
[2572]865 if(work) delete [] work; work=NULL;
[1342]866 if (jobu == 'N') delete up;
867 if (jobvt == 'N') delete vtp;
868 string tn = typeid(T).name();
869 cerr << " LapackServer::SVDDriver(...) - Unsupported DataType T = " << tn << endl;
[2561]870 throw TypeMismatchExc("LapackServer::SVDDriver(a,b) - Unsupported DataType (T)");
[1342]871 }
872
[2572]873 if(work) delete [] work;
[1342]874 if (jobu == 'N') delete up;
875 if (jobvt == 'N') delete vtp;
876 return(info);
877}
878
[2556]879
[2561]880//! Interface to Lapack SVD driver s/d/c/zgesdd().
881/*! Same as SVD but with Divide and Conquer method */
882template <class T>
[2563]883int LapackServer<T>::SVD_DC(TMatrix<T>& a, TVector<r_8>& s, TMatrix<T>& u, TMatrix<T>& vt)
[2561]884{
885
886 if ( !a.IsPacked() )
887 throw(SzMismatchError("LapackServer::SVD_DC(a, ...) a Not Packed "));
888
889 int_4 m = a.NRows();
890 int_4 n = a.NCols();
891 int_4 maxmn = (m > n) ? m : n;
892 int_4 minmn = (m < n) ? m : n;
893 int_4 supermax = 4*minmn*minmn+4*minmn; if(maxmn>supermax) supermax=maxmn;
894
895 char jobz = 'A';
896
897 s.ReSize(minmn);
898 u.ReSize(m,m);
899 vt.ReSize(n,n);
900
[2572]901 int_4 lda = m;
902 int_4 ldu = m;
903 int_4 ldvt = n;
904 int_4 info;
905 int_4 lwork=-1;
906 T * work = NULL;
907 int_4 * iwork = NULL;
908 T wkget[2];
909
[2561]910 if(typeid(T) == typeid(r_4) ) {
[2563]911 r_4* sloc = new r_4[minmn];
[2572]912 iwork = new int_4[8*minmn +GARDMEM];
[2875]913 sgesdd(&jobz,&m,&n,(r_4*)a.Data(),&lda,
[2563]914 (r_4*)sloc,(r_4*)u.Data(),&ldu,(r_4*)vt.Data(),&ldvt,
[2572]915 (r_4*)wkget,&lwork,(int_4*)iwork,&info);
916 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]917 sgesdd(&jobz,&m,&n,(r_4*)a.Data(),&lda,
[2572]918 (r_4*)sloc,(r_4*)u.Data(),&ldu,(r_4*)vt.Data(),&ldvt,
[2561]919 (r_4*)work,&lwork,(int_4*)iwork,&info);
[2563]920 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
[2572]921 delete [] sloc;
[2561]922 } else if(typeid(T) == typeid(r_8) ) {
[2572]923 iwork = new int_4[8*minmn +GARDMEM];
[2875]924 dgesdd(&jobz,&m,&n,(r_8*)a.Data(),&lda,
[2561]925 (r_8*)s.Data(),(r_8*)u.Data(),&ldu,(r_8*)vt.Data(),&ldvt,
[2572]926 (r_8*)wkget,&lwork,(int_4*)iwork,&info);
927 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]928 dgesdd(&jobz,&m,&n,(r_8*)a.Data(),&lda,
[2572]929 (r_8*)s.Data(),(r_8*)u.Data(),&ldu,(r_8*)vt.Data(),&ldvt,
[2561]930 (r_8*)work,&lwork,(int_4*)iwork,&info);
931 } else if(typeid(T) == typeid(complex<r_4>) ) {
932 r_4* sloc = new r_4[minmn];
[2567]933 r_4* rwork = new r_4[5*minmn*minmn+5*minmn +GARDMEM];
[2572]934 iwork = new int_4[8*minmn +GARDMEM];
[2875]935 cgesdd(&jobz,&m,&n,(complex<r_4>*)a.Data(),&lda,
[2561]936 (r_4*)sloc,(complex<r_4>*)u.Data(),&ldu,(complex<r_4>*)vt.Data(),&ldvt,
[2572]937 (complex<r_4>*)wkget,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
938 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
[2875]939 cgesdd(&jobz,&m,&n,(complex<r_4>*)a.Data(),&lda,
[2572]940 (r_4*)sloc,(complex<r_4>*)u.Data(),&ldu,(complex<r_4>*)vt.Data(),&ldvt,
[2561]941 (complex<r_4>*)work,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
[2563]942 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
[2572]943 delete [] sloc; delete [] rwork;
[2561]944 } else if(typeid(T) == typeid(complex<r_8>) ) {
[2567]945 r_8* rwork = new r_8[5*minmn*minmn+5*minmn +GARDMEM];
[2572]946 iwork = new int_4[8*minmn +GARDMEM];
[2875]947 zgesdd(&jobz,&m,&n,(complex<r_8>*)a.Data(),&lda,
[2563]948 (r_8*)s.Data(),(complex<r_8>*)u.Data(),&ldu,(complex<r_8>*)vt.Data(),&ldvt,
[2572]949 (complex<r_8>*)wkget,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
950 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
[2875]951 zgesdd(&jobz,&m,&n,(complex<r_8>*)a.Data(),&lda,
[2572]952 (r_8*)s.Data(),(complex<r_8>*)u.Data(),&ldu,(complex<r_8>*)vt.Data(),&ldvt,
[2561]953 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
[2572]954 delete [] rwork;
[2561]955 } else {
[2572]956 if(work) delete [] work; work=NULL;
957 if(iwork) delete [] iwork; iwork=NULL;
[2561]958 string tn = typeid(T).name();
959 cerr << " LapackServer::SVD_DC(...) - Unsupported DataType T = " << tn << endl;
960 throw TypeMismatchExc("LapackServer::SVD_DC - Unsupported DataType (T)");
961 }
962
[2572]963 if(work) delete [] work; if(iwork) delete [] iwork;
[2561]964 return(info);
965}
966
967
[2556]968////////////////////////////////////////////////////////////////////////////////////
969/*! Computes the eigen values and eigen vectors of a symetric (or hermitian) matrix \b a.
970 Input arrays should have FortranMemoryMapping (column packed).
971 \param a : input symetric (or hermitian) n-by-n matrix
972 \param b : Vector of eigenvalues (descending order)
973 \param eigenvector : if true compute eigenvectors, if not only eigenvalues
974 \param a : on return array of eigenvectors (same order than eval, one vector = one column)
[2561]975 \return : return code from lapack driver
[2556]976 */
977
978template <class T>
979int LapackServer<T>::LapackEigenSym(TArray<T>& a, TVector<r_8>& b, bool eigenvector)
980{
981 if ( a.NbDimensions() != 2 )
982 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a NbDimensions() != 2"));
983 int_4 rowa = a.RowsKA();
984 int_4 cola = a.ColsKA();
985 if ( a.Size(rowa) != a.Size(cola))
986 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a Not a square Array"));
987 if (!a.IsPacked(rowa))
988 throw(SzMismatchError("LapackServer::LapackEigenSym(a,b) a Not Column Packed"));
989
[2561]990 char uplo='U';
[2556]991 char jobz='N'; if(eigenvector) jobz='V';
992
993 int_4 n = a.Size(rowa);
994 int_4 lda = a.Step(cola);
995 int_4 info = 0;
[2572]996 int_4 lwork = -1;
997 T * work = NULL;
998 T wkget[2];
[2556]999
1000 b.ReSize(n); b = 0.;
1001
1002 if (typeid(T) == typeid(r_4) ) {
1003 r_4* w = new r_4[n];
[2875]1004 ssyev(&jobz,&uplo,&n,(r_4 *)a.Data(),&lda,(r_4 *)w,(r_4 *)wkget,&lwork,&info);
[2572]1005 lwork = type2i4(&wkget[0],4); /* 3*n-1;*/ work = new T[lwork +GARDMEM];
[2875]1006 ssyev(&jobz,&uplo,&n,(r_4 *)a.Data(),&lda,(r_4 *)w,(r_4 *)work,&lwork,&info);
[2556]1007 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
[2572]1008 delete [] w;
[2556]1009 } else if (typeid(T) == typeid(r_8) ) {
1010 r_8* w = new r_8[n];
[2875]1011 dsyev(&jobz,&uplo,&n,(r_8 *)a.Data(),&lda,(r_8 *)w,(r_8 *)wkget,&lwork,&info);
[2572]1012 lwork = type2i4(&wkget[0],8); /* 3*n-1;*/ work = new T[lwork +GARDMEM];
[2875]1013 dsyev(&jobz,&uplo,&n,(r_8 *)a.Data(),&lda,(r_8 *)w,(r_8 *)work,&lwork,&info);
[2556]1014 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
[2572]1015 delete [] w;
[2556]1016 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]1017 r_4* rwork = new r_4[3*n-2 +GARDMEM]; r_4* w = new r_4[n];
[2875]1018 cheev(&jobz,&uplo,&n,(complex<r_4> *)a.Data(),&lda,(r_4 *)w
[2572]1019 ,(complex<r_4> *)wkget,&lwork,(r_4 *)rwork,&info);
1020 lwork = type2i4(&wkget[0],4); /* 2*n-1;*/ work = new T[lwork +GARDMEM];
[2875]1021 cheev(&jobz,&uplo,&n,(complex<r_4> *)a.Data(),&lda,(r_4 *)w
[2556]1022 ,(complex<r_4> *)work,&lwork,(r_4 *)rwork,&info);
1023 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
[2572]1024 delete [] rwork; delete [] w;
[2556]1025 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]1026 r_8* rwork = new r_8[3*n-2 +GARDMEM]; r_8* w = new r_8[n];
[2875]1027 zheev(&jobz,&uplo,&n,(complex<r_8> *)a.Data(),&lda,(r_8 *)w
[2572]1028 ,(complex<r_8> *)wkget,&lwork,(r_8 *)rwork,&info);
1029 lwork = type2i4(&wkget[0],8); /* 2*n-1;*/ work = new T[lwork +GARDMEM];
[2875]1030 zheev(&jobz,&uplo,&n,(complex<r_8> *)a.Data(),&lda,(r_8 *)w
[2556]1031 ,(complex<r_8> *)work,&lwork,(r_8 *)rwork,&info);
1032 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
[2572]1033 delete [] rwork; delete [] w;
[2556]1034 } else {
[2572]1035 if(work) delete [] work; work=NULL;
[2556]1036 string tn = typeid(T).name();
1037 cerr << " LapackServer::LapackEigenSym(a,b) - Unsupported DataType T = " << tn << endl;
1038 throw TypeMismatchExc("LapackServer::LapackEigenSym(a,b) - Unsupported DataType (T)");
1039 }
1040
[2572]1041 if(work) delete [] work;
[2556]1042 return(info);
1043}
1044
1045////////////////////////////////////////////////////////////////////////////////////
1046/*! Computes the eigen values and eigen vectors of a general squared matrix \b a.
1047 Input arrays should have FortranMemoryMapping (column packed).
1048 \param a : input general n-by-n matrix
1049 \param eval : Vector of eigenvalues (complex double precision)
1050 \param evec : Matrix of eigenvector (same order than eval, one vector = one column)
1051 \param eigenvector : if true compute (right) eigenvectors, if not only eigenvalues
1052 \param a : on return array of eigenvectors
[2561]1053 \return : return code from lapack driver
[2556]1054 \verbatim
1055 eval : contains the computed eigenvalues.
1056 --- For real matrices "a" :
1057 Complex conjugate pairs of eigenvalues appear consecutively
1058 with the eigenvalue having the positive imaginary part first.
1059 evec : the right eigenvectors v(j) are stored one after another
1060 in the columns of evec, in the same order as their eigenvalues.
1061 --- For real matrices "a" :
1062 If the j-th eigenvalue is real, then v(j) = evec(:,j),
1063 the j-th column of evec.
1064 If the j-th and (j+1)-st eigenvalues form a complex
1065 conjugate pair, then v(j) = evec(:,j) + i*evec(:,j+1) and
1066 v(j+1) = evec(:,j) - i*evec(:,j+1).
1067 \endverbatim
1068*/
1069
1070template <class T>
1071int LapackServer<T>::LapackEigen(TArray<T>& a, TVector< complex<r_8> >& eval, TMatrix<T>& evec, bool eigenvector)
1072{
1073 if ( a.NbDimensions() != 2 )
1074 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a NbDimensions() != 2"));
1075 int_4 rowa = a.RowsKA();
1076 int_4 cola = a.ColsKA();
1077 if ( a.Size(rowa) != a.Size(cola))
1078 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a Not a square Array"));
1079 if (!a.IsPacked(rowa))
1080 throw(SzMismatchError("LapackServer::LapackEigen(a,b) a Not Column Packed"));
1081
[2561]1082 char jobvl = 'N';
[2556]1083 char jobvr = 'N'; if(eigenvector) jobvr='V';
1084
1085 int_4 n = a.Size(rowa);
1086 int_4 lda = a.Step(cola);
1087 int_4 info = 0;
1088
1089 eval.ReSize(n); eval = complex<r_8>(0.,0.);
1090 if(eigenvector) {evec.ReSize(n,n); evec = (T) 0.;}
1091 int_4 ldvr = n, ldvl = 1;
1092
[2572]1093 int_4 lwork = -1;
1094 T * work = NULL;
1095 T wkget[2];
1096
[2556]1097 if (typeid(T) == typeid(r_4) ) {
1098 r_4* wr = new r_4[n]; r_4* wi = new r_4[n]; r_4* vl = NULL;
[2875]1099 sgeev(&jobvl,&jobvr,&n,(r_4 *)a.Data(),&lda,(r_4 *)wr,(r_4 *)wi,
[2556]1100 (r_4 *)vl,&ldvl,(r_4 *)evec.Data(),&ldvr,
[2572]1101 (r_4 *)wkget,&lwork,&info);
1102 lwork = type2i4(&wkget[0],4); /* 4*n;*/ work = new T[lwork +GARDMEM];
[2875]1103 sgeev(&jobvl,&jobvr,&n,(r_4 *)a.Data(),&lda,(r_4 *)wr,(r_4 *)wi,
[2572]1104 (r_4 *)vl,&ldvl,(r_4 *)evec.Data(),&ldvr,
[2556]1105 (r_4 *)work,&lwork,&info);
1106 if(info==0) for(int i=0;i<n;i++) eval(i) = complex<r_8>(wr[i],wi[i]);
[2572]1107 delete [] wr; delete [] wi;
[2556]1108 } else if (typeid(T) == typeid(r_8) ) {
1109 r_8* wr = new r_8[n]; r_8* wi = new r_8[n]; r_8* vl = NULL;
[2875]1110 dgeev(&jobvl,&jobvr,&n,(r_8 *)a.Data(),&lda,(r_8 *)wr,(r_8 *)wi,
[2556]1111 (r_8 *)vl,&ldvl,(r_8 *)evec.Data(),&ldvr,
[2572]1112 (r_8 *)wkget,&lwork,&info);
1113 lwork = type2i4(&wkget[0],8); /* 4*n;*/ work = new T[lwork +GARDMEM];
[2875]1114 dgeev(&jobvl,&jobvr,&n,(r_8 *)a.Data(),&lda,(r_8 *)wr,(r_8 *)wi,
[2572]1115 (r_8 *)vl,&ldvl,(r_8 *)evec.Data(),&ldvr,
[2556]1116 (r_8 *)work,&lwork,&info);
1117 if(info==0) for(int i=0;i<n;i++) eval(i) = complex<r_8>(wr[i],wi[i]);
[2572]1118 delete [] wr; delete [] wi;
[2556]1119 } else if (typeid(T) == typeid(complex<r_4>) ) {
[2567]1120 r_4* rwork = new r_4[2*n +GARDMEM]; r_4* vl = NULL; TVector< complex<r_4> > w(n);
[2875]1121 cgeev(&jobvl,&jobvr,&n,(complex<r_4> *)a.Data(),&lda,(complex<r_4> *)w.Data(),
[2556]1122 (complex<r_4> *)vl,&ldvl,(complex<r_4> *)evec.Data(),&ldvr,
[2572]1123 (complex<r_4> *)wkget,&lwork,(r_4 *)rwork,&info);
1124 lwork = type2i4(&wkget[0],4); /* 2*n;*/ work = new T[lwork +GARDMEM];
[2875]1125 cgeev(&jobvl,&jobvr,&n,(complex<r_4> *)a.Data(),&lda,(complex<r_4> *)w.Data(),
[2572]1126 (complex<r_4> *)vl,&ldvl,(complex<r_4> *)evec.Data(),&ldvr,
[2556]1127 (complex<r_4> *)work,&lwork,(r_4 *)rwork,&info);
1128 if(info==0) for(int i=0;i<n;i++) eval(i) = w(i);
[2572]1129 delete [] rwork;
[2556]1130 } else if (typeid(T) == typeid(complex<r_8>) ) {
[2567]1131 r_8* rwork = new r_8[2*n +GARDMEM]; r_8* vl = NULL;
[2875]1132 zgeev(&jobvl,&jobvr,&n,(complex<r_8> *)a.Data(),&lda,(complex<r_8> *)eval.Data(),
[2556]1133 (complex<r_8> *)vl,&ldvl,(complex<r_8> *)evec.Data(),&ldvr,
[2572]1134 (complex<r_8> *)wkget,&lwork,(r_8 *)rwork,&info);
1135 lwork = type2i4(&wkget[0],8); /* 2*n;*/ work = new T[lwork +GARDMEM];
[2875]1136 zgeev(&jobvl,&jobvr,&n,(complex<r_8> *)a.Data(),&lda,(complex<r_8> *)eval.Data(),
[2572]1137 (complex<r_8> *)vl,&ldvl,(complex<r_8> *)evec.Data(),&ldvr,
[2556]1138 (complex<r_8> *)work,&lwork,(r_8 *)rwork,&info);
[2572]1139 delete [] rwork;
[2556]1140 } else {
[2572]1141 if(work) delete [] work; work=NULL;
[2556]1142 string tn = typeid(T).name();
1143 cerr << " LapackServer::LapackEigen(a,b) - Unsupported DataType T = " << tn << endl;
1144 throw TypeMismatchExc("LapackServer::LapackEigen(a,b) - Unsupported DataType (T)");
1145 }
1146
[2572]1147 if(work) delete [] work;
[2556]1148 return(info);
1149}
1150
1151
1152
1153
[814]1154///////////////////////////////////////////////////////////////
1155#ifdef __CXX_PRAGMA_TEMPLATES__
1156#pragma define_template LapackServer<r_4>
1157#pragma define_template LapackServer<r_8>
1158#pragma define_template LapackServer< complex<r_4> >
1159#pragma define_template LapackServer< complex<r_8> >
1160#endif
1161
1162#if defined(ANSI_TEMPLATES) || defined(GNU_TEMPLATES)
[2875]1163namespace SOPHYA {
[814]1164template class LapackServer<r_4>;
1165template class LapackServer<r_8>;
1166template class LapackServer< complex<r_4> >;
1167template class LapackServer< complex<r_8> >;
[2875]1168}
[814]1169#endif
1170
1171#if defined(OS_LINUX)
1172// Pour le link avec f2c sous Linux
1173extern "C" {
1174 void MAIN__();
1175}
1176
1177void MAIN__()
1178{
1179 cerr << "MAIN__() function for linking with libf2c.a " << endl;
1180 cerr << " This function should never be called !!! " << endl;
1181 throw PError("MAIN__() should not be called - see intflapack.cc");
1182}
1183#endif
Note: See TracBrowser for help on using the repository browser.