summaryrefslogtreecommitdiff
path: root/lib/LAPACK/lapack-aux.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/LAPACK/lapack-aux.c')
-rw-r--r--lib/LAPACK/lapack-aux.c579
1 files changed, 579 insertions, 0 deletions
diff --git a/lib/LAPACK/lapack-aux.c b/lib/LAPACK/lapack-aux.c
new file mode 100644
index 0000000..3e8c015
--- /dev/null
+++ b/lib/LAPACK/lapack-aux.c
@@ -0,0 +1,579 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <math.h>
5#include <time.h>
6#include "lapack-aux.h"
7
8#define MACRO(B) do {B} while (0)
9#define ERROR(CODE) MACRO(return CODE;)
10#define REQUIRES(COND, CODE) MACRO(if(!(COND)) {ERROR(CODE);})
11
12#define MIN(A,B) ((A)<(B)?(A):(B))
13#define MAX(A,B) ((A)>(B)?(A):(B))
14
15#ifdef DBGL
16#define DEBUGMSG(M) printf("LAPACK Wrapper "M"\n: "); size_t t0 = time(NULL);
17#define OK MACRO(printf("%ld s\n",time(0)-t0); return 0;);
18#else
19#define DEBUGMSG(M)
20#define OK return 0;
21#endif
22
23#define CHECK(RES,CODE) MACRO(if(RES) return CODE;)
24
25#define BAD_SIZE 1000
26#define BAD_CODE 1001
27#define MEM 1002
28#define BAD_FILE 1003
29#define SINGULAR 1004
30#define NOCONVER 1005
31
32//////////////////// real svd ////////////////////////////////////
33
34int svd_l_R(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) {
35 integer m = ar;
36 integer n = ac;
37 integer q = MIN(m,n);
38 REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE);
39 DEBUGMSG("svd_l_R");
40 double *B = (double*)malloc(m*n*sizeof(double));
41 CHECK(!B,MEM);
42 memcpy(B,ap,m*n*sizeof(double));
43 integer lwork = -1;
44 integer res;
45 // ask for optimal lwork
46 double ans;
47 //printf("ask zgesvd\n");
48 char* job = "A";
49 dgesvd_ (job,job,
50 &m,&n,B,&m,
51 sp,
52 up,&m,
53 vp,&n,
54 &ans, &lwork,
55 &res);
56 lwork = ceil(ans);
57 //printf("ans = %d\n",lwork);
58 double * work = (double*)malloc(lwork*sizeof(double));
59 CHECK(!work,MEM);
60 //printf("dgesdd\n");
61 dgesvd_ (job,job,
62 &m,&n,B,&m,
63 sp,
64 up,&m,
65 vp,&n,
66 work, &lwork,
67 &res);
68 CHECK(res,res);
69 free(work);
70 free(B);
71 OK
72}
73
74// (alternative version)
75
76int svd_l_Rdd(KDMAT(a),DMAT(u), DVEC(s),DMAT(v)) {
77 integer m = ar;
78 integer n = ac;
79 integer q = MIN(m,n);
80 REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE);
81 DEBUGMSG("svd_l_Rdd");
82 double *B = (double*)malloc(m*n*sizeof(double));
83 CHECK(!B,MEM);
84 memcpy(B,ap,m*n*sizeof(double));
85 integer* iwk = (integer*) malloc(8*q*sizeof(int));
86 CHECK(!iwk,MEM);
87 integer lwk = -1;
88 integer res;
89 // ask for optimal lwk
90 double ans;
91 //printf("ask dgesdd\n");
92 dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,&ans,&lwk,iwk,&res);
93 lwk = 2*ceil(ans); // ????? otherwise 50x100 rejects lwk
94 //printf("lwk = %d\n",lwk);
95 double * workv = (double*)malloc(lwk*sizeof(double));
96 CHECK(!workv,MEM);
97 //printf("dgesdd\n");
98 dgesdd_ ("A",&m,&n,B,&m,sp,up,&m,vp,&n,workv,&lwk,iwk,&res);
99 CHECK(res,res);
100 free(iwk);
101 free(workv);
102 free(B);
103 OK
104}
105
106//////////////////// complex svd ////////////////////////////////////
107
108// not in clapack.h
109
110int zgesvd_(char *jobu, char *jobvt, integer *m, integer *n,
111 doublecomplex *a, integer *lda, doublereal *s, doublecomplex *u,
112 integer *ldu, doublecomplex *vt, integer *ldvt, doublecomplex *work,
113 integer *lwork, doublereal *rwork, integer *info);
114
115int svd_l_C(KCMAT(a),CMAT(u), DVEC(s),CMAT(v)) {
116 integer m = ar;
117 integer n = ac;
118 integer q = MIN(m,n);
119 REQUIRES(ur==m && uc==m && sn==q && vr==n && vc==n,BAD_SIZE);
120 DEBUGMSG("svd_l_C");
121 double *B = (double*)malloc(2*m*n*sizeof(double));
122 CHECK(!B,MEM);
123 memcpy(B,ap,m*n*2*sizeof(double));
124
125 double *rwork = (double*) malloc(5*q*sizeof(double));
126 CHECK(!rwork,MEM);
127 integer lwork = -1;
128 integer res;
129 // ask for optimal lwork
130 doublecomplex ans;
131 //printf("ask zgesvd\n");
132 char* job = "A";
133 zgesvd_ (job,job,
134 &m,&n,(doublecomplex*)B,&m,
135 sp,
136 (doublecomplex*)up,&m,
137 (doublecomplex*)vp,&n,
138 &ans, &lwork,
139 rwork,
140 &res);
141 lwork = ceil(ans.r);
142 //printf("ans = %d\n",lwork);
143 doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double));
144 CHECK(!work,MEM);
145 //printf("zgesvd\n");
146 zgesvd_ (job,job,
147 &m,&n,(doublecomplex*)B,&m,
148 sp,
149 (doublecomplex*)up,&m,
150 (doublecomplex*)vp,&n,
151 work, &lwork,
152 rwork,
153 &res);
154 CHECK(res,res);
155 free(work);
156 free(rwork);
157 free(B);
158 OK
159}
160
161
162
163//////////////////// general complex eigensystem ////////////
164
165int eig_l_C(KCMAT(a),CMAT(u), CVEC(s),CMAT(v)) {
166 integer n = ar;
167 REQUIRES(n>=2 && (ur==1 || (ur==n && uc==n)) && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE);
168 DEBUGMSG("eig_l_C");
169 double *B = (double*)malloc(2*n*n*sizeof(double));
170 CHECK(!B,MEM);
171 memcpy(B,ap,n*n*2*sizeof(double));
172
173 double *rwork = (double*) malloc(2*n*sizeof(double));
174 CHECK(!rwork,MEM);
175 integer lwork = -1;
176 char jobvl = ur==1?'N':'V';
177 char jobvr = vr==1?'N':'V';
178 integer res;
179 // ask for optimal lwork
180 doublecomplex ans;
181 //printf("ask zgeev\n");
182 zgeev_ (&jobvl,&jobvr,
183 &n,(doublecomplex*)B,&n,
184 (doublecomplex*)sp,
185 (doublecomplex*)up,&n,
186 (doublecomplex*)vp,&n,
187 &ans, &lwork,
188 rwork,
189 &res);
190 lwork = ceil(ans.r);
191 //printf("ans = %d\n",lwork);
192 doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double));
193 CHECK(!work,MEM);
194 //printf("zgeev\n");
195 zgeev_ (&jobvl,&jobvr,
196 &n,(doublecomplex*)B,&n,
197 (doublecomplex*)sp,
198 (doublecomplex*)up,&n,
199 (doublecomplex*)vp,&n,
200 work, &lwork,
201 rwork,
202 &res);
203 CHECK(res,res);
204 free(work);
205 free(rwork);
206 free(B);
207 OK
208}
209
210
211
212//////////////////// general real eigensystem ////////////
213
214int eig_l_R(KDMAT(a),DMAT(u), CVEC(s),DMAT(v)) {
215 integer n = ar;
216 REQUIRES(n>=2 && (ur==1 || (ur==n && uc==n)) && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE);
217 DEBUGMSG("eig_l_R");
218 double *B = (double*)malloc(n*n*sizeof(double));
219 CHECK(!B,MEM);
220 memcpy(B,ap,n*n*sizeof(double));
221 integer lwork = -1;
222 char jobvl = ur==1?'N':'V';
223 char jobvr = vr==1?'N':'V';
224 integer res;
225 // ask for optimal lwork
226 double ans;
227 //printf("ask dgeev\n");
228 dgeev_ (&jobvl,&jobvr,
229 &n,B,&n,
230 sp, sp+n,
231 up,&n,
232 vp,&n,
233 &ans, &lwork,
234 &res);
235 lwork = ceil(ans);
236 //printf("ans = %d\n",lwork);
237 double * work = (double*)malloc(lwork*sizeof(double));
238 CHECK(!work,MEM);
239 //printf("dgeev\n");
240 dgeev_ (&jobvl,&jobvr,
241 &n,B,&n,
242 sp, sp+n,
243 up,&n,
244 vp,&n,
245 work, &lwork,
246 &res);
247 CHECK(res,res);
248 free(work);
249 free(B);
250 OK
251}
252
253
254//////////////////// symmetric real eigensystem ////////////
255
256
257int eig_l_S(KDMAT(a),DVEC(s),DMAT(v)) {
258 integer n = ar;
259 REQUIRES(n>=2 && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE);
260 DEBUGMSG("eig_l_S");
261 memcpy(vp,ap,n*n*sizeof(double));
262 integer lwork = -1;
263 char jobz = vr==1?'N':'V';
264 char uplo = 'U';
265 integer res;
266 // ask for optimal lwork
267 double ans;
268 //printf("ask dsyev\n");
269 dsyev_ (&jobz,&uplo,
270 &n,vp,&n,
271 sp,
272 &ans, &lwork,
273 &res);
274 lwork = ceil(ans);
275 //printf("ans = %d\n",lwork);
276 double * work = (double*)malloc(lwork*sizeof(double));
277 CHECK(!work,MEM);
278 dsyev_ (&jobz,&uplo,
279 &n,vp,&n,
280 sp,
281 work, &lwork,
282 &res);
283 CHECK(res,res);
284 free(work);
285 OK
286}
287
288//////////////////// hermitian complex eigensystem ////////////
289
290int eig_l_H(KCMAT(a),DVEC(s),CMAT(v)) {
291 integer n = ar;
292 REQUIRES(n>=2 && sn==n && (vr==1 || (vr==n && vc==n)),BAD_SIZE);
293 DEBUGMSG("eig_l_H");
294 memcpy(vp,ap,2*n*n*sizeof(double));
295 double *rwork = (double*) malloc((3*n-2)*sizeof(double));
296 CHECK(!rwork,MEM);
297 integer lwork = -1;
298 char jobz = vr==1?'N':'V';
299 char uplo = 'U';
300 integer res;
301 // ask for optimal lwork
302 doublecomplex ans;
303 //printf("ask zheev\n");
304 zheev_ (&jobz,&uplo,
305 &n,(doublecomplex*)vp,&n,
306 sp,
307 &ans, &lwork,
308 rwork,
309 &res);
310 lwork = ceil(ans.r);
311 //printf("ans = %d\n",lwork);
312 doublecomplex * work = (doublecomplex*)malloc(lwork*2*sizeof(double));
313 CHECK(!work,MEM);
314 zheev_ (&jobz,&uplo,
315 &n,(doublecomplex*)vp,&n,
316 sp,
317 work, &lwork,
318 rwork,
319 &res);
320 CHECK(res,res);
321 free(work);
322 free(rwork);
323 OK
324}
325
326//////////////////// general real linear system ////////////
327
328int linearSolveR_l(KDMAT(a),KDMAT(b),DMAT(x)) {
329 integer n = ar;
330 integer nhrs = bc;
331 REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);
332 DEBUGMSG("linearSolveR_l");
333 double*AC = (double*)malloc(n*n*sizeof(double));
334 memcpy(AC,ap,n*n*sizeof(double));
335 memcpy(xp,bp,n*nhrs*sizeof(double));
336 integer * ipiv = (integer*)malloc(n*sizeof(integer));
337 integer res;
338 dgesv_ (&n,&nhrs,
339 AC, &n,
340 ipiv,
341 xp, &n,
342 &res);
343 if(res>0) {
344 return SINGULAR;
345 }
346 CHECK(res,res);
347 free(ipiv);
348 free(AC);
349 OK
350}
351
352//////////////////// general complex linear system ////////////
353
354int linearSolveC_l(KCMAT(a),KCMAT(b),CMAT(x)) {
355 integer n = ar;
356 integer nhrs = bc;
357 REQUIRES(n>=1 && ar==ac && ar==br,BAD_SIZE);
358 DEBUGMSG("linearSolveC_l");
359 double*AC = (double*)malloc(2*n*n*sizeof(double));
360 memcpy(AC,ap,2*n*n*sizeof(double));
361 memcpy(xp,bp,2*n*nhrs*sizeof(double));
362 integer * ipiv = (integer*)malloc(n*sizeof(integer));
363 integer res;
364 zgesv_ (&n,&nhrs,
365 (doublecomplex*)AC, &n,
366 ipiv,
367 (doublecomplex*)xp, &n,
368 &res);
369 if(res>0) {
370 return SINGULAR;
371 }
372 CHECK(res,res);
373 free(ipiv);
374 free(AC);
375 OK
376}
377
378//////////////////// least squares real linear system ////////////
379
380int linearSolveLSR_l(KDMAT(a),KDMAT(b),DMAT(x)) {
381 integer m = ar;
382 integer n = ac;
383 integer nrhs = bc;
384 integer ldb = xr;
385 REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);
386 DEBUGMSG("linearSolveLSR_l");
387 double*AC = (double*)malloc(m*n*sizeof(double));
388 memcpy(AC,ap,m*n*sizeof(double));
389 if (m>=n) {
390 memcpy(xp,bp,m*nrhs*sizeof(double));
391 } else {
392 int k;
393 for(k = 0; k<nrhs; k++) {
394 memcpy(xp+ldb*k,bp+m*k,m*sizeof(double));
395 }
396 }
397 integer res;
398 integer lwork = -1;
399 double ans;
400 dgels_ ("N",&m,&n,&nrhs,
401 AC,&m,
402 xp,&ldb,
403 &ans,&lwork,
404 &res);
405 lwork = ceil(ans);
406 //printf("ans = %d\n",lwork);
407 double * work = (double*)malloc(lwork*sizeof(double));
408 dgels_ ("N",&m,&n,&nrhs,
409 AC,&m,
410 xp,&ldb,
411 work,&lwork,
412 &res);
413 if(res>0) {
414 return SINGULAR;
415 }
416 CHECK(res,res);
417 free(work);
418 free(AC);
419 OK
420}
421
422//////////////////// least squares complex linear system ////////////
423
424int linearSolveLSC_l(KCMAT(a),KCMAT(b),CMAT(x)) {
425 integer m = ar;
426 integer n = ac;
427 integer nrhs = bc;
428 integer ldb = xr;
429 REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);
430 DEBUGMSG("linearSolveLSC_l");
431 double*AC = (double*)malloc(2*m*n*sizeof(double));
432 memcpy(AC,ap,2*m*n*sizeof(double));
433 memcpy(AC,ap,2*m*n*sizeof(double));
434 if (m>=n) {
435 memcpy(xp,bp,2*m*nrhs*sizeof(double));
436 } else {
437 int k;
438 for(k = 0; k<nrhs; k++) {
439 memcpy(xp+2*ldb*k,bp+2*m*k,m*2*sizeof(double));
440 }
441 }
442 integer res;
443 integer lwork = -1;
444 doublecomplex ans;
445 zgels_ ("N",&m,&n,&nrhs,
446 (doublecomplex*)AC,&m,
447 (doublecomplex*)xp,&ldb,
448 &ans,&lwork,
449 &res);
450 lwork = ceil(ans.r);
451 //printf("ans = %d\n",lwork);
452 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));
453 zgels_ ("N",&m,&n,&nrhs,
454 (doublecomplex*)AC,&m,
455 (doublecomplex*)xp,&ldb,
456 work,&lwork,
457 &res);
458 if(res>0) {
459 return SINGULAR;
460 }
461 CHECK(res,res);
462 free(work);
463 free(AC);
464 OK
465}
466
467//////////////////// least squares real linear system using SVD ////////////
468
469int linearSolveSVDR_l(double rcond,KDMAT(a),KDMAT(b),DMAT(x)) {
470 integer m = ar;
471 integer n = ac;
472 integer nrhs = bc;
473 integer ldb = xr;
474 REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);
475 DEBUGMSG("linearSolveSVDR_l");
476 double*AC = (double*)malloc(m*n*sizeof(double));
477 double*S = (double*)malloc(MIN(m,n)*sizeof(double));
478 memcpy(AC,ap,m*n*sizeof(double));
479 if (m>=n) {
480 memcpy(xp,bp,m*nrhs*sizeof(double));
481 } else {
482 int k;
483 for(k = 0; k<nrhs; k++) {
484 memcpy(xp+ldb*k,bp+m*k,m*sizeof(double));
485 }
486 }
487 integer res;
488 integer lwork = -1;
489 integer rank;
490 double ans;
491 dgelss_ (&m,&n,&nrhs,
492 AC,&m,
493 xp,&ldb,
494 S,
495 &rcond,&rank,
496 &ans,&lwork,
497 &res);
498 lwork = ceil(ans);
499 //printf("ans = %d\n",lwork);
500 double * work = (double*)malloc(lwork*sizeof(double));
501 dgelss_ (&m,&n,&nrhs,
502 AC,&m,
503 xp,&ldb,
504 S,
505 &rcond,&rank,
506 work,&lwork,
507 &res);
508 if(res>0) {
509 return NOCONVER;
510 }
511 CHECK(res,res);
512 free(work);
513 free(S);
514 free(AC);
515 OK
516}
517
518//////////////////// least squares complex linear system using SVD ////////////
519
520// not in clapack.h
521
522int zgelss_(integer *m, integer *n, integer *nhrs,
523 doublecomplex *a, integer *lda, doublecomplex *b, integer *ldb, doublereal *s,
524 doublereal *rcond, integer* rank,
525 doublecomplex *work, integer* lwork, doublereal* rwork,
526 integer *info);
527
528int linearSolveSVDC_l(double rcond, KCMAT(a),KCMAT(b),CMAT(x)) {
529 integer m = ar;
530 integer n = ac;
531 integer nrhs = bc;
532 integer ldb = xr;
533 REQUIRES(m>=1 && n>=1 && ar==br && xr==MAX(m,n) && xc == bc, BAD_SIZE);
534 DEBUGMSG("linearSolveSVDC_l");
535 double*AC = (double*)malloc(2*m*n*sizeof(double));
536 double*S = (double*)malloc(MIN(m,n)*sizeof(double));
537 double*RWORK = (double*)malloc(5*MIN(m,n)*sizeof(double));
538 memcpy(AC,ap,2*m*n*sizeof(double));
539 if (m>=n) {
540 memcpy(xp,bp,2*m*nrhs*sizeof(double));
541 } else {
542 int k;
543 for(k = 0; k<nrhs; k++) {
544 memcpy(xp+2*ldb*k,bp+2*m*k,m*2*sizeof(double));
545 }
546 }
547 integer res;
548 integer lwork = -1;
549 integer rank;
550 doublecomplex ans;
551 zgelss_ (&m,&n,&nrhs,
552 (doublecomplex*)AC,&m,
553 (doublecomplex*)xp,&ldb,
554 S,
555 &rcond,&rank,
556 &ans,&lwork,
557 RWORK,
558 &res);
559 lwork = ceil(ans.r);
560 //printf("ans = %d\n",lwork);
561 doublecomplex * work = (doublecomplex*)malloc(lwork*sizeof(doublecomplex));
562 zgelss_ (&m,&n,&nrhs,
563 (doublecomplex*)AC,&m,
564 (doublecomplex*)xp,&ldb,
565 S,
566 &rcond,&rank,
567 work,&lwork,
568 RWORK,
569 &res);
570 if(res>0) {
571 return NOCONVER;
572 }
573 CHECK(res,res);
574 free(work);
575 free(RWORK);
576 free(S);
577 free(AC);
578 OK
579}