diff options
Diffstat (limited to 'lib/LinearAlgebra/LAPACK/lapack-aux.c')
-rw-r--r-- | lib/LinearAlgebra/LAPACK/lapack-aux.c | 656 |
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 | |||
35 | int 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 | |||
77 | int 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 | |||
111 | int 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 | |||
116 | int 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 | |||
166 | int 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 | |||
215 | int 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 | |||
258 | int 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 | |||
291 | int 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 | |||
329 | int 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 | |||
355 | int 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 | |||
381 | int 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 | |||
425 | int 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 | |||
470 | int 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 | |||
523 | int 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 | |||
529 | int 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 | |||
584 | int 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 | |||
604 | int 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 | |||
626 | int 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 | |||
642 | int 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 | } | ||