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