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
Line 
1#include <iostream>
2#include <math.h>
3#include "sopnamsp.h"
4#include "intflapack.h"
5#include "tvector.h"
6#include "tmatrix.h"
7#include <typeinfo>
8
9#define GARDMEM 5
10
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
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
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
55 can be handled by LapackServer. LapackServer can be instanciated
56 for simple and double precision real or complex array types.
57 \warning The input array is overwritten in most cases.
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
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
89#define ilaenv ilaenv
90
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
132#define ilaenv ilaenv_
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
175////////////////////////////////////////////////////////////////////////////////////
176extern "C" {
177// Le calculateur de workingspace
178 int_4 ilaenv(int_4 *ispec,char *name,char *opts,int_4 *n1,int_4 *n2,int_4 *n3,int_4 *n4,
179 int_4 nc1,int_4 nc2);
180
181// Drivers pour resolution de systemes lineaires
182 void sgesv(int_4* n, int_4* nrhs, r_4* a, int_4* lda,
183 int_4* ipiv, r_4* b, int_4* ldb, int_4* info);
184 void dgesv(int_4* n, int_4* nrhs, r_8* a, int_4* lda,
185 int_4* ipiv, r_8* b, int_4* ldb, int_4* info);
186 void cgesv(int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
187 int_4* ipiv, complex<r_4>* b, int_4* ldb, int_4* info);
188 void zgesv(int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
189 int_4* ipiv, complex<r_8>* b, int_4* ldb, int_4* info);
190
191// Drivers pour resolution de systemes lineaires symetriques
192 void ssysv(char* uplo, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
193 int_4* ipiv, r_4* b, int_4* ldb,
194 r_4* work, int_4* lwork, int_4* info);
195 void dsysv(char* uplo, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
196 int_4* ipiv, r_8* b, int_4* ldb,
197 r_8* work, int_4* lwork, int_4* info);
198 void csysv(char* uplo, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
199 int_4* ipiv, complex<r_4>* b, int_4* ldb,
200 complex<r_4>* work, int_4* lwork, int_4* info);
201 void zsysv(char* uplo, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
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
206 void sgels(char * trans, int_4* m, int_4* n, int_4* nrhs, r_4* a, int_4* lda,
207 r_4* b, int_4* ldb, r_4* work, int_4* lwork, int_4* info);
208 void dgels(char * trans, int_4* m, int_4* n, int_4* nrhs, r_8* a, int_4* lda,
209 r_8* b, int_4* ldb, r_8* work, int_4* lwork, int_4* info);
210 void cgels(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_4>* a, int_4* lda,
211 complex<r_4>* b, int_4* ldb, complex<r_4>* work, int_4* lwork, int_4* info);
212 void zgels(char * trans, int_4* m, int_4* n, int_4* nrhs, complex<r_8>* a, int_4* lda,
213 complex<r_8>* b, int_4* ldb, complex<r_8>* work, int_4* lwork, int_4* info);
214
215// Driver pour resolution de systemes au sens de Xi2 par SVD Divide & Conquer
216 void sgelsd(int_4* m,int_4* n,int_4* nrhs,r_4* a,int_4* lda,
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);
219 void dgelsd(int_4* m,int_4* n,int_4* nrhs,r_8* a,int_4* lda,
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);
222 void cgelsd(int_4* m,int_4* n,int_4* nrhs,complex<r_4>* a,int_4* lda,
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);
225 void zgelsd(int_4* m,int_4* n,int_4* nrhs,complex<r_8>* a,int_4* lda,
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
229// Driver pour decomposition SVD
230 void sgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, r_4* a, int_4* lda,
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);
233 void dgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, r_8* a, int_4* lda,
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);
236 void cgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
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);
239 void zgesvd(char* jobu, char* jobvt, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
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);
242
243// Driver pour decomposition SVD Divide and Conquer
244 void sgesdd(char* jobz, int_4* m, int_4* n, r_4* a, int_4* lda,
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);
247 void dgesdd(char* jobz, int_4* m, int_4* n, r_8* a, int_4* lda,
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);
250 void cgesdd(char* jobz, int_4* m, int_4* n, complex<r_4>* a, int_4* lda,
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);
253 void zgesdd(char* jobz, int_4* m, int_4* n, complex<r_8>* a, int_4* lda,
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
257// Driver pour eigen decomposition for symetric/hermitian matrices
258 void ssyev(char* jobz, char* uplo, int_4* n, r_4* a, int_4* lda, r_4* w,
259 r_4* work, int_4 *lwork, int_4* info);
260 void dsyev(char* jobz, char* uplo, int_4* n, r_8* a, int_4* lda, r_8* w,
261 r_8* work, int_4 *lwork, int_4* info);
262 void cheev(char* jobz, char* uplo, int_4* n, complex<r_4>* a, int_4* lda, r_4* w,
263 complex<r_4>* work, int_4 *lwork, r_4* rwork, int_4* info);
264 void zheev(char* jobz, char* uplo, int_4* n, complex<r_8>* a, int_4* lda, r_8* w,
265 complex<r_8>* work, int_4 *lwork, r_8* rwork, int_4* info);
266
267// Driver pour eigen decomposition for general squared matrices
268 void sgeev(char* jobl, char* jobvr, int_4* n, r_4* a, int_4* lda, r_4* wr, r_4* wi,
269 r_4* vl, int_4* ldvl, r_4* vr, int_4* ldvr,
270 r_4* work, int_4 *lwork, int_4* info);
271 void dgeev(char* jobl, char* jobvr, int_4* n, r_8* a, int_4* lda, r_8* wr, r_8* wi,
272 r_8* vl, int_4* ldvl, r_8* vr, int_4* ldvr,
273 r_8* work, int_4 *lwork, int_4* info);
274 void cgeev(char* jobl, char* jobvr, int_4* n, complex<r_4>* a, int_4* lda, complex<r_4>* w,
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);
277 void zgeev(char* jobl, char* jobvr, int_4* n, complex<r_8>* a, int_4* lda, complex<r_8>* w,
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
281}
282
283// -------------- Classe LapackServer<T> --------------
284
285////////////////////////////////////////////////////////////////////////////////////
286template <class T>
287LapackServer<T>::LapackServer()
288{
289 SetWorkSpaceSizeFactor();
290}
291
292template <class T>
293LapackServer<T>::~LapackServer()
294{
295}
296
297////////////////////////////////////////////////////////////////////////////////////
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{
301 int_4 nc1 = strlen(name), nc2 = strlen(opts), rc=0;
302 rc = ilaenv(&ispec,name,opts,&n1,&n2,&n3,&n4,nc1,nc2);
303 //cout<<"ilaenv_en_C("<<ispec<<","<<name<<"("<<nc1<<"),"<<opts<<"("<<nc2<<"),"
304 // <<n1<<","<<n2<<","<<n3<<","<<n4<<") = "<<rc<<endl;
305 return rc;
306}
307
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
323////////////////////////////////////////////////////////////////////////////////////
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).
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 */
331template <class T>
332int LapackServer<T>::LinSolve(TArray<T>& a, TArray<T> & b)
333{
334 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
335 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b NbDimensions() != 2"));
336
337 int_4 rowa = a.RowsKA();
338 int_4 cola = a.ColsKA();
339 int_4 rowb = b.RowsKA();
340 int_4 colb = b.ColsKA();
341 if ( a.Size(rowa) != a.Size(cola))
342 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Not a square Array"));
343 if ( a.Size(rowa) != b.Size(rowb))
344 throw(SzMismatchError("LapackServer::LinSolve(a,b) RowSize(a <> b) "));
345
346 if (!a.IsPacked(rowa) || !b.IsPacked(rowb))
347 throw(SzMismatchError("LapackServer::LinSolve(a,b) a Or b Not Column Packed"));
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) )
357 sgesv(&n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb, &info);
358 else if (typeid(T) == typeid(r_8) )
359 dgesv(&n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb, &info);
360 else if (typeid(T) == typeid(complex<r_4>) )
361 cgesv(&n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
362 (complex<r_4> *)b.Data(), &ldb, &info);
363 else if (typeid(T) == typeid(complex<r_8>) )
364 zgesv(&n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
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;
373 return(info);
374}
375
376////////////////////////////////////////////////////////////////////////////////////
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).
380 \param a : input matrix symetric , overwritten on output
381 \param b : input-output, input vector b, contains x on exit
382 \return : return code from lapack driver _sysv()
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
390// sont plus de deux fois plus lentes que les LinSolve generales sur OSF
391// et sensiblement plus lentes sous Linux ???
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;
415 T wkget[2];
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) ) {
421 ssysv(&uplo, &n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb,
422 (r_4 *)wkget, &lwork, &info);
423 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
424 ssysv(&uplo, &n, &nrhs, (r_4 *)a.Data(), &lda, ipiv, (r_4 *)b.Data(), &ldb,
425 (r_4 *)work, &lwork, &info);
426 } else if (typeid(T) == typeid(r_8) ) {
427 dsysv(&uplo, &n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb,
428 (r_8 *)wkget, &lwork, &info);
429 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
430 dsysv(&uplo, &n, &nrhs, (r_8 *)a.Data(), &lda, ipiv, (r_8 *)b.Data(), &ldb,
431 (r_8 *)work, &lwork, &info);
432 } else if (typeid(T) == typeid(complex<r_4>) ) {
433 csysv(&uplo, &n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
434 (complex<r_4> *)b.Data(), &ldb,
435 (complex<r_4> *)wkget, &lwork, &info);
436 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
437 csysv(&uplo, &n, &nrhs, (complex<r_4> *)a.Data(), &lda, ipiv,
438 (complex<r_4> *)b.Data(), &ldb,
439 (complex<r_4> *)work, &lwork, &info);
440 } else if (typeid(T) == typeid(complex<r_8>) ) {
441 zsysv(&uplo, &n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
442 (complex<r_8> *)b.Data(), &ldb,
443 (complex<r_8> *)wkget, &lwork, &info);
444 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
445 zsysv(&uplo, &n, &nrhs, (complex<r_8> *)a.Data(), &lda, ipiv,
446 (complex<r_8> *)b.Data(), &ldb,
447 (complex<r_8> *)work, &lwork, &info);
448 } else {
449 if(work) delete[] work;
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 }
455 if(work) delete[] work;
456 delete[] ipiv;
457 return(info);
458}
459
460////////////////////////////////////////////////////////////////////////////////////
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
463 \b a and an m element vector \b b , using QR or LQ factorization .
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
479template <class T>
480int LapackServer<T>::LeastSquareSolve(TArray<T>& a, TArray<T> & b)
481{
482 if ( ( a.NbDimensions() != 2 ) || ( b.NbDimensions() != 2 ) )
483 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b NbDimensions() != 2"));
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))
495 throw(SzMismatchError("LapackServer::LeastSquareSolve(a,b) a Or b Not Column Packed"));
496
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 }
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
515 int_4 lwork = -1; //minmn+maxmnrhs*5;
516 T * work = NULL;
517 T wkget[2];
518
519 char trans = 'N';
520
521 if (typeid(T) == typeid(r_4) ) {
522 sgels(&trans, &m, &n, &nrhs, (r_4 *)a.Data(), &lda,
523 (r_4 *)b.Data(), &ldb, (r_4 *)wkget, &lwork, &info);
524 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
525 sgels(&trans, &m, &n, &nrhs, (r_4 *)a.Data(), &lda,
526 (r_4 *)b.Data(), &ldb, (r_4 *)work, &lwork, &info);
527 } else if (typeid(T) == typeid(r_8) ) {
528 dgels(&trans, &m, &n, &nrhs, (r_8 *)a.Data(), &lda,
529 (r_8 *)b.Data(), &ldb, (r_8 *)wkget, &lwork, &info);
530 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
531 dgels(&trans, &m, &n, &nrhs, (r_8 *)a.Data(), &lda,
532 (r_8 *)b.Data(), &ldb, (r_8 *)work, &lwork, &info);
533 } else if (typeid(T) == typeid(complex<r_4>) ) {
534 cgels(&trans, &m, &n, &nrhs, (complex<r_4> *)a.Data(), &lda,
535 (complex<r_4> *)b.Data(), &ldb, (complex<r_4> *)wkget, &lwork, &info);
536 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
537 cgels(&trans, &m, &n, &nrhs, (complex<r_4> *)a.Data(), &lda,
538 (complex<r_4> *)b.Data(), &ldb, (complex<r_4> *)work, &lwork, &info);
539 } else if (typeid(T) == typeid(complex<r_8>) ) {
540 zgels(&trans, &m, &n, &nrhs, (complex<r_8> *)a.Data(), &lda,
541 (complex<r_8> *)b.Data(), &ldb, (complex<r_8> *)wkget, &lwork, &info);
542 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
543 zgels(&trans, &m, &n, &nrhs, (complex<r_8> *)a.Data(), &lda,
544 (complex<r_8> *)b.Data(), &ldb, (complex<r_8> *)work, &lwork, &info);
545 } else {
546 if(work) delete [] work; work=NULL;
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 }
551 if(work) delete [] work;
552 return(info);
553}
554
555////////////////////////////////////////////////////////////////////////////////////
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////////////////////////////////////////////////////////////////////////////////////
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.
596 \param rank : output the rank of the matrix.
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"));
608
609 int_4 m = a.NRows();
610 int_4 n = a.NCols();
611
612 if(b.NRows() != m)
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
623 { // Use {} for automatic des-allocation of "bsave"
624 TMatrix<T> bsave(m,nrhs); bsave.SetMemoryMapping(BaseArray::FortranMemoryMapping);
625 bsave = b;
626 b.ReSize(maxmn,nrhs); b = (T) 0;
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"
629 s.ReSize(minmn);
630
631 int_4 smlsiz = 25; // Normallement ilaenv_en_C(9,...) renvoie toujours 25
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
640 T * work = NULL;
641 int_4 * iwork = NULL;
642 int_4 lwork=-1, lrwork;
643 T wkget[2];
644
645 if(typeid(T) == typeid(r_4) ) {
646 r_4* sloc = new r_4[minmn];
647 r_4 srcond = rcond;
648 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
649 sgelsd(&m,&n,&nrhs,(r_4*)a.Data(),&lda,
650 (r_4*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
651 (r_4*)wkget,&lwork,(int_4*)iwork,&info);
652 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
653 sgelsd(&m,&n,&nrhs,(r_4*)a.Data(),&lda,
654 (r_4*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
655 (r_4*)work,&lwork,(int_4*)iwork,&info);
656 for(int_4 i=0;i<minmn;i++) s(i) = sloc[i];
657 delete [] sloc;
658 } else if(typeid(T) == typeid(r_8) ) {
659 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
660 dgelsd(&m,&n,&nrhs,(r_8*)a.Data(),&lda,
661 (r_8*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
662 (r_8*)wkget,&lwork,(int_4*)iwork,&info);
663 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
664 dgelsd(&m,&n,&nrhs,(r_8*)a.Data(),&lda,
665 (r_8*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
666 (r_8*)work,&lwork,(int_4*)iwork,&info);
667 } else if(typeid(T) == typeid(complex<r_4>) ) {
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;
672 r_4* rwork = new r_4[lrwork +GARDMEM];
673 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
674 r_4* sloc = new r_4[minmn];
675 r_4 srcond = rcond;
676 cgelsd(&m,&n,&nrhs,(complex<r_4>*)a.Data(),&lda,
677 (complex<r_4>*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
678 (complex<r_4>*)wkget,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
679 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
680 cgelsd(&m,&n,&nrhs,(complex<r_4>*)a.Data(),&lda,
681 (complex<r_4>*)b.Data(),&ldb,(r_4*)sloc,&srcond,&rank,
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];
684 delete [] sloc; delete [] rwork;
685 } else if(typeid(T) == typeid(complex<r_8>) ) {
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;
691 r_8* rwork = new r_8[lrwork +GARDMEM];
692 iwork = new int_4[3*minmn*nlvl+11*minmn +GARDMEM];
693 zgelsd(&m,&n,&nrhs,(complex<r_8>*)a.Data(),&lda,
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];
697 zgelsd(&m,&n,&nrhs,(complex<r_8>*)a.Data(),&lda,
698 (complex<r_8>*)b.Data(),&ldb,(r_8*)s.Data(),&rcond,&rank,
699 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
700 delete [] rwork;
701 } else {
702 if(work) delete [] work; work=NULL;
703 if(iwork) delete [] iwork; iwork=NULL;
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
709 if(work) delete [] work; if(iwork) delete [] iwork;
710 return(info);
711}
712
713
714////////////////////////////////////////////////////////////////////////////////////
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
723template <class T>
724int LapackServer<T>::SVD(TArray<T>& a, TArray<T> & s)
725{
726 return (SVDDriver(a, s, NULL, NULL) );
727}
728
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.
739 \param a : input m-by-n matrix (in FortranMemoryMapping)
740 \param s : Vector of min(m,n) singular values (descending order)
741 \param u : m-by-m Matrix of left singular vectors
742 \param vt : Transpose of right singular vectors (n-by-n matrix).
743 \return : return code from lapack driver _gesvd()
744 */
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
751
752//! Interface to Lapack SVD driver s/d/c/zgesv().
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 ) )
757 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a.NbDimensions() != 2"));
758
759 int_4 rowa = a.RowsKA();
760 int_4 cola = a.ColsKA();
761
762 if ( !a.IsPacked(rowa) )
763 throw(SzMismatchError("LapackServer::SVDDriver(a, ...) a Not Column Packed "));
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) )
777 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for u !") );
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) )
789 throw( TypeMismatchExc("LapackServer::SVDDriver() Wrong type (=TVector<T>) for vt !") );
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());
814 int_4 info;
815
816 int_4 lwork = -1; // maxmn*5 *wspace_size_factor;
817 T * work = NULL; // = new T[lwork];
818 T wkget[2];
819
820 if (typeid(T) == typeid(r_4) ) {
821 sgesvd(&jobu, &jobvt, &m, &n, (r_4 *)a.Data(), &lda,
822 (r_4 *)s.Data(), (r_4 *) up->Data(), &ldu, (r_4 *)vtp->Data(), &ldvt,
823 (r_4 *)wkget, &lwork, &info);
824 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
825 sgesvd(&jobu, &jobvt, &m, &n, (r_4 *)a.Data(), &lda,
826 (r_4 *)s.Data(), (r_4 *) up->Data(), &ldu, (r_4 *)vtp->Data(), &ldvt,
827 (r_4 *)work, &lwork, &info);
828 } else if (typeid(T) == typeid(r_8) ) {
829 dgesvd(&jobu, &jobvt, &m, &n, (r_8 *)a.Data(), &lda,
830 (r_8 *)s.Data(), (r_8 *) up->Data(), &ldu, (r_8 *)vtp->Data(), &ldvt,
831 (r_8 *)wkget, &lwork, &info);
832 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
833 dgesvd(&jobu, &jobvt, &m, &n, (r_8 *)a.Data(), &lda,
834 (r_8 *)s.Data(), (r_8 *) up->Data(), &ldu, (r_8 *)vtp->Data(), &ldvt,
835 (r_8 *)work, &lwork, &info);
836 } else if (typeid(T) == typeid(complex<r_4>) ) {
837 r_4 * rwork = new r_4[5*minmn +GARDMEM];
838 r_4 * sloc = new r_4[minmn];
839 cgesvd(&jobu, &jobvt, &m, &n, (complex<r_4> *)a.Data(), &lda,
840 (r_4 *)sloc, (complex<r_4> *) up->Data(), &ldu,
841 (complex<r_4> *)vtp->Data(), &ldvt,
842 (complex<r_4> *)wkget, &lwork, (r_4 *)rwork, &info);
843 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
844 cgesvd(&jobu, &jobvt, &m, &n, (complex<r_4> *)a.Data(), &lda,
845 (r_4 *)sloc, (complex<r_4> *) up->Data(), &ldu,
846 (complex<r_4> *)vtp->Data(), &ldvt,
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>) ) {
851 r_8 * rwork = new r_8[5*minmn +GARDMEM];
852 r_8 * sloc = new r_8[minmn];
853 zgesvd(&jobu, &jobvt, &m, &n, (complex<r_8> *)a.Data(), &lda,
854 (r_8 *)sloc, (complex<r_8> *) up->Data(), &ldu,
855 (complex<r_8> *)vtp->Data(), &ldvt,
856 (complex<r_8> *)wkget, &lwork, (r_8 *)rwork, &info);
857 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
858 zgesvd(&jobu, &jobvt, &m, &n, (complex<r_8> *)a.Data(), &lda,
859 (r_8 *)sloc, (complex<r_8> *) up->Data(), &ldu,
860 (complex<r_8> *)vtp->Data(), &ldvt,
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 {
865 if(work) delete [] work; work=NULL;
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;
870 throw TypeMismatchExc("LapackServer::SVDDriver(a,b) - Unsupported DataType (T)");
871 }
872
873 if(work) delete [] work;
874 if (jobu == 'N') delete up;
875 if (jobvt == 'N') delete vtp;
876 return(info);
877}
878
879
880//! Interface to Lapack SVD driver s/d/c/zgesdd().
881/*! Same as SVD but with Divide and Conquer method */
882template <class T>
883int LapackServer<T>::SVD_DC(TMatrix<T>& a, TVector<r_8>& s, TMatrix<T>& u, TMatrix<T>& vt)
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
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
910 if(typeid(T) == typeid(r_4) ) {
911 r_4* sloc = new r_4[minmn];
912 iwork = new int_4[8*minmn +GARDMEM];
913 sgesdd(&jobz,&m,&n,(r_4*)a.Data(),&lda,
914 (r_4*)sloc,(r_4*)u.Data(),&ldu,(r_4*)vt.Data(),&ldvt,
915 (r_4*)wkget,&lwork,(int_4*)iwork,&info);
916 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
917 sgesdd(&jobz,&m,&n,(r_4*)a.Data(),&lda,
918 (r_4*)sloc,(r_4*)u.Data(),&ldu,(r_4*)vt.Data(),&ldvt,
919 (r_4*)work,&lwork,(int_4*)iwork,&info);
920 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
921 delete [] sloc;
922 } else if(typeid(T) == typeid(r_8) ) {
923 iwork = new int_4[8*minmn +GARDMEM];
924 dgesdd(&jobz,&m,&n,(r_8*)a.Data(),&lda,
925 (r_8*)s.Data(),(r_8*)u.Data(),&ldu,(r_8*)vt.Data(),&ldvt,
926 (r_8*)wkget,&lwork,(int_4*)iwork,&info);
927 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
928 dgesdd(&jobz,&m,&n,(r_8*)a.Data(),&lda,
929 (r_8*)s.Data(),(r_8*)u.Data(),&ldu,(r_8*)vt.Data(),&ldvt,
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];
933 r_4* rwork = new r_4[5*minmn*minmn+5*minmn +GARDMEM];
934 iwork = new int_4[8*minmn +GARDMEM];
935 cgesdd(&jobz,&m,&n,(complex<r_4>*)a.Data(),&lda,
936 (r_4*)sloc,(complex<r_4>*)u.Data(),&ldu,(complex<r_4>*)vt.Data(),&ldvt,
937 (complex<r_4>*)wkget,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
938 lwork = type2i4(&wkget[0],4); work = new T[lwork +GARDMEM];
939 cgesdd(&jobz,&m,&n,(complex<r_4>*)a.Data(),&lda,
940 (r_4*)sloc,(complex<r_4>*)u.Data(),&ldu,(complex<r_4>*)vt.Data(),&ldvt,
941 (complex<r_4>*)work,&lwork,(r_4*)rwork,(int_4*)iwork,&info);
942 for(int_4 i=0;i<minmn;i++) s(i) = (r_8) sloc[i];
943 delete [] sloc; delete [] rwork;
944 } else if(typeid(T) == typeid(complex<r_8>) ) {
945 r_8* rwork = new r_8[5*minmn*minmn+5*minmn +GARDMEM];
946 iwork = new int_4[8*minmn +GARDMEM];
947 zgesdd(&jobz,&m,&n,(complex<r_8>*)a.Data(),&lda,
948 (r_8*)s.Data(),(complex<r_8>*)u.Data(),&ldu,(complex<r_8>*)vt.Data(),&ldvt,
949 (complex<r_8>*)wkget,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
950 lwork = type2i4(&wkget[0],8); work = new T[lwork +GARDMEM];
951 zgesdd(&jobz,&m,&n,(complex<r_8>*)a.Data(),&lda,
952 (r_8*)s.Data(),(complex<r_8>*)u.Data(),&ldu,(complex<r_8>*)vt.Data(),&ldvt,
953 (complex<r_8>*)work,&lwork,(r_8*)rwork,(int_4*)iwork,&info);
954 delete [] rwork;
955 } else {
956 if(work) delete [] work; work=NULL;
957 if(iwork) delete [] iwork; iwork=NULL;
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
963 if(work) delete [] work; if(iwork) delete [] iwork;
964 return(info);
965}
966
967
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)
975 \return : return code from lapack driver
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
990 char uplo='U';
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;
996 int_4 lwork = -1;
997 T * work = NULL;
998 T wkget[2];
999
1000 b.ReSize(n); b = 0.;
1001
1002 if (typeid(T) == typeid(r_4) ) {
1003 r_4* w = new r_4[n];
1004 ssyev(&jobz,&uplo,&n,(r_4 *)a.Data(),&lda,(r_4 *)w,(r_4 *)wkget,&lwork,&info);
1005 lwork = type2i4(&wkget[0],4); /* 3*n-1;*/ work = new T[lwork +GARDMEM];
1006 ssyev(&jobz,&uplo,&n,(r_4 *)a.Data(),&lda,(r_4 *)w,(r_4 *)work,&lwork,&info);
1007 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
1008 delete [] w;
1009 } else if (typeid(T) == typeid(r_8) ) {
1010 r_8* w = new r_8[n];
1011 dsyev(&jobz,&uplo,&n,(r_8 *)a.Data(),&lda,(r_8 *)w,(r_8 *)wkget,&lwork,&info);
1012 lwork = type2i4(&wkget[0],8); /* 3*n-1;*/ work = new T[lwork +GARDMEM];
1013 dsyev(&jobz,&uplo,&n,(r_8 *)a.Data(),&lda,(r_8 *)w,(r_8 *)work,&lwork,&info);
1014 if(info==0) for(int i=0;i<n;i++) b(i) = w[i];
1015 delete [] w;
1016 } else if (typeid(T) == typeid(complex<r_4>) ) {
1017 r_4* rwork = new r_4[3*n-2 +GARDMEM]; r_4* w = new r_4[n];
1018 cheev(&jobz,&uplo,&n,(complex<r_4> *)a.Data(),&lda,(r_4 *)w
1019 ,(complex<r_4> *)wkget,&lwork,(r_4 *)rwork,&info);
1020 lwork = type2i4(&wkget[0],4); /* 2*n-1;*/ work = new T[lwork +GARDMEM];
1021 cheev(&jobz,&uplo,&n,(complex<r_4> *)a.Data(),&lda,(r_4 *)w
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];
1024 delete [] rwork; delete [] w;
1025 } else if (typeid(T) == typeid(complex<r_8>) ) {
1026 r_8* rwork = new r_8[3*n-2 +GARDMEM]; r_8* w = new r_8[n];
1027 zheev(&jobz,&uplo,&n,(complex<r_8> *)a.Data(),&lda,(r_8 *)w
1028 ,(complex<r_8> *)wkget,&lwork,(r_8 *)rwork,&info);
1029 lwork = type2i4(&wkget[0],8); /* 2*n-1;*/ work = new T[lwork +GARDMEM];
1030 zheev(&jobz,&uplo,&n,(complex<r_8> *)a.Data(),&lda,(r_8 *)w
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];
1033 delete [] rwork; delete [] w;
1034 } else {
1035 if(work) delete [] work; work=NULL;
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
1041 if(work) delete [] work;
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
1053 \return : return code from lapack driver
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
1082 char jobvl = 'N';
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
1093 int_4 lwork = -1;
1094 T * work = NULL;
1095 T wkget[2];
1096
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;
1099 sgeev(&jobvl,&jobvr,&n,(r_4 *)a.Data(),&lda,(r_4 *)wr,(r_4 *)wi,
1100 (r_4 *)vl,&ldvl,(r_4 *)evec.Data(),&ldvr,
1101 (r_4 *)wkget,&lwork,&info);
1102 lwork = type2i4(&wkget[0],4); /* 4*n;*/ work = new T[lwork +GARDMEM];
1103 sgeev(&jobvl,&jobvr,&n,(r_4 *)a.Data(),&lda,(r_4 *)wr,(r_4 *)wi,
1104 (r_4 *)vl,&ldvl,(r_4 *)evec.Data(),&ldvr,
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]);
1107 delete [] wr; delete [] wi;
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;
1110 dgeev(&jobvl,&jobvr,&n,(r_8 *)a.Data(),&lda,(r_8 *)wr,(r_8 *)wi,
1111 (r_8 *)vl,&ldvl,(r_8 *)evec.Data(),&ldvr,
1112 (r_8 *)wkget,&lwork,&info);
1113 lwork = type2i4(&wkget[0],8); /* 4*n;*/ work = new T[lwork +GARDMEM];
1114 dgeev(&jobvl,&jobvr,&n,(r_8 *)a.Data(),&lda,(r_8 *)wr,(r_8 *)wi,
1115 (r_8 *)vl,&ldvl,(r_8 *)evec.Data(),&ldvr,
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]);
1118 delete [] wr; delete [] wi;
1119 } else if (typeid(T) == typeid(complex<r_4>) ) {
1120 r_4* rwork = new r_4[2*n +GARDMEM]; r_4* vl = NULL; TVector< complex<r_4> > w(n);
1121 cgeev(&jobvl,&jobvr,&n,(complex<r_4> *)a.Data(),&lda,(complex<r_4> *)w.Data(),
1122 (complex<r_4> *)vl,&ldvl,(complex<r_4> *)evec.Data(),&ldvr,
1123 (complex<r_4> *)wkget,&lwork,(r_4 *)rwork,&info);
1124 lwork = type2i4(&wkget[0],4); /* 2*n;*/ work = new T[lwork +GARDMEM];
1125 cgeev(&jobvl,&jobvr,&n,(complex<r_4> *)a.Data(),&lda,(complex<r_4> *)w.Data(),
1126 (complex<r_4> *)vl,&ldvl,(complex<r_4> *)evec.Data(),&ldvr,
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);
1129 delete [] rwork;
1130 } else if (typeid(T) == typeid(complex<r_8>) ) {
1131 r_8* rwork = new r_8[2*n +GARDMEM]; r_8* vl = NULL;
1132 zgeev(&jobvl,&jobvr,&n,(complex<r_8> *)a.Data(),&lda,(complex<r_8> *)eval.Data(),
1133 (complex<r_8> *)vl,&ldvl,(complex<r_8> *)evec.Data(),&ldvr,
1134 (complex<r_8> *)wkget,&lwork,(r_8 *)rwork,&info);
1135 lwork = type2i4(&wkget[0],8); /* 2*n;*/ work = new T[lwork +GARDMEM];
1136 zgeev(&jobvl,&jobvr,&n,(complex<r_8> *)a.Data(),&lda,(complex<r_8> *)eval.Data(),
1137 (complex<r_8> *)vl,&ldvl,(complex<r_8> *)evec.Data(),&ldvr,
1138 (complex<r_8> *)work,&lwork,(r_8 *)rwork,&info);
1139 delete [] rwork;
1140 } else {
1141 if(work) delete [] work; work=NULL;
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
1147 if(work) delete [] work;
1148 return(info);
1149}
1150
1151
1152
1153
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)
1163namespace SOPHYA {
1164template class LapackServer<r_4>;
1165template class LapackServer<r_8>;
1166template class LapackServer< complex<r_4> >;
1167template class LapackServer< complex<r_8> >;
1168}
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.